-
Notifications
You must be signed in to change notification settings - Fork 439
Expand file tree
/
Copy pathindex.spec.js
More file actions
105 lines (92 loc) · 4.11 KB
/
index.spec.js
File metadata and controls
105 lines (92 loc) · 4.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { createElement, setFeatureFlagForTest } from 'lwc';
import Component from 'x/component';
import Scoping from 'x/scoping';
import { jasmineSpyOn as spyOn } from '../../../helpers/jasmine.js';
import { catchUnhandledRejectionsAndErrors } from '../../../helpers/utils.js';
let caughtError;
let logger;
catchUnhandledRejectionsAndErrors((error) => {
caughtError = error;
});
beforeEach(() => {
logger = spyOn(console, 'warn');
});
afterEach(() => {
caughtError = undefined;
});
const props = ['stylesheetToken', 'stylesheetTokens', 'legacyStylesheetToken'];
const components = [
{
tagName: 'x-component',
Ctor: Component,
name: 'unscoped styles',
},
{
tagName: 'x-scoping',
Ctor: Scoping,
name: 'scoped styles',
},
];
props.forEach((prop) => {
describe(prop, () => {
components.forEach(({ tagName, Ctor, name }) => {
describe(name, () => {
beforeEach(() => {
setFeatureFlagForTest(
'ENABLE_LEGACY_SCOPE_TOKENS',
prop === 'legacyStylesheetToken'
);
});
afterEach(() => {
setFeatureFlagForTest('ENABLE_LEGACY_SCOPE_TOKENS', false);
// We keep a cache of parsed static fragments; these need to be reset
// since they can vary based on whether we use the legacy scope token or not.
window.__lwcResetFragmentCache();
// Reset template object for clean state between tests
Ctor.resetTemplate();
});
it('W-16614556 should not render arbitrary content via stylesheet token', async () => {
const elm = createElement(tagName, { is: Ctor });
elm.propToUse = prop;
try {
document.body.appendChild(elm);
} catch (err) {
// In synthetic custom element lifecycle, the error is thrown synchronously on `appendChild`
caughtError = err;
}
await Promise.resolve();
if (
process.env.NATIVE_SHADOW &&
process.env.DISABLE_STATIC_CONTENT_OPTIMIZATION &&
Ctor !== Scoping
) {
// If we're rendering in native shadow and the static content optimization is disabled,
// then there's no problem with invalid stylesheet tokens because they are only rendered
// as class attribute values using either `classList` or `setAttribute` (and this only applies
// when `*.scoped.css` is being used).
expect(elm.shadowRoot.children.length).toBe(1);
} else {
expect(elm.shadowRoot.children.length).toBe(0); // does not render
expect(caughtError).not.toBeUndefined();
expect(caughtError.message).toMatch(
/stylesheet token must be a valid string|Failed to execute 'setAttribute'|Invalid qualified name|String contains an invalid character|The string contains invalid characters/
);
if (process.env.NODE_ENV === 'production') {
// no warnings in prod mode
expect(logger).not.toHaveBeenCalled();
} else {
// dev mode
expect(logger).toHaveBeenCalledTimes(1);
const loggedError = logger.calls.allArgs()[0][0];
expect(loggedError.message).toMatch(
new RegExp(
`Mutating the "${prop}" property on a template is deprecated`
)
);
}
}
});
});
});
});
});