-
Notifications
You must be signed in to change notification settings - Fork 439
test(integration): more web-test-runner test fixes @W-18763051 #5414
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 42 commits
a7bc370
85e8b0d
4d1615f
9d97689
38d8482
0f960b3
30cefce
d292d05
abca4bb
738f32b
e885a88
d09d5c7
1c5f80f
ecad806
1454b2e
aeaec17
ebfc163
2557b7f
ed8ec74
e53f159
c1f5623
a7371cc
92eddae
0d2d59a
1551364
c889881
113d86d
884655b
901ab22
446fcb0
3deb95a
3951273
ad4ca57
13c259a
9929ace
b4dbd54
9faeb90
da42d85
0773038
b076645
8a06494
1fc08b2
ee78dee
66cecd2
88d1346
2d9f4a4
c11f060
6827b4f
b5e1b60
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,7 +25,8 @@ const expectLogs = (regexes) => { | |
| const args = logger.calls.allArgs(); | ||
| expect(args.length).toBe(regexes.length); | ||
| for (let i = 0; i < args.length; i++) { | ||
| expect(args[i][0]).toMatch(regexes[i]); | ||
| expect(args[i][0]).toBeInstanceOf(Error); | ||
| expect(args[i][0].message).toMatch(regexes[i]); | ||
|
Comment on lines
+28
to
+29
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Karma's |
||
| } | ||
| } | ||
| }; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,7 +21,7 @@ function filterCalls(echoAdapterSpy, methodType) { | |
|
|
||
| describe('wiring', () => { | ||
| describe('component lifecycle and wire adapter', () => { | ||
| it('should call a connect when component is connected', () => { | ||
| it('should call a connect when component is connected', async () => { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The tests in this file use a shared global state. Most of the tests, but not all, have asynchronous behavior. In Karma, the state was properly cleaned for both sync and async tests. With web-test-runner, the state got polluted with the synchronous tests. Converting the sync tests to async functions (even with no inner Note that I added |
||
| const spy = []; | ||
| const elm = createElement('x-echo-adapter-consumer', { is: ComponentClass }); | ||
| AdapterId.setSpy(spy); | ||
|
|
@@ -30,7 +30,7 @@ describe('wiring', () => { | |
| expect(filterCalls(spy, 'connect').length).toBe(1); | ||
| }); | ||
|
|
||
| it('should call a disconnect when component is disconnected', () => { | ||
| it('should call a disconnect when component is disconnected', async () => { | ||
| const spy = []; | ||
| AdapterId.setSpy(spy); | ||
| const elm = createElement('x-echo-adapter-consumer', { is: ComponentClass }); | ||
|
|
@@ -40,7 +40,7 @@ describe('wiring', () => { | |
| expect(filterCalls(spy, 'disconnect').length).toBe(1); | ||
| }); | ||
|
|
||
| it('should call a connect and disconnect when component is connected, disconnected twice', () => { | ||
| it('should call a connect and disconnect when component is connected, disconnected twice', async () => { | ||
| const spy = []; | ||
| const elm = createElement('x-echo-adapter-consumer', { is: ComponentClass }); | ||
| AdapterId.setSpy(spy); | ||
|
|
@@ -59,7 +59,7 @@ describe('wiring', () => { | |
| }); | ||
|
|
||
| describe('update method on wire adapter', () => { | ||
| it('should be called in same tick when component with wire no dynamic params is created', () => { | ||
| it('should be called in same tick when component with wire no dynamic params is created', async () => { | ||
| const spy = []; | ||
| AdapterId.setSpy(spy); | ||
| expect(spy.length).toBe(0); | ||
|
|
@@ -83,7 +83,7 @@ describe('wiring', () => { | |
| setFeatureFlagForTest('ENABLE_WIRE_SYNC_EMIT', false); | ||
| }); | ||
|
|
||
| it('should be called synchronously after connect when a component with wire that has dynamic params is created', () => { | ||
| it('should be called synchronously after connect when a component with wire that has dynamic params is created', async () => { | ||
| const spy = []; | ||
| AdapterId.setSpy(spy); | ||
| expect(spy.length).toBe(0); | ||
|
|
@@ -96,7 +96,7 @@ describe('wiring', () => { | |
| expect(spy[1].method).toBe('update'); | ||
| }); | ||
|
|
||
| it('should call synchronously update only once when the component is created and a wire dynamic param is modified', () => { | ||
| it('should call synchronously update only once when the component is created and a wire dynamic param is modified', async () => { | ||
| const spy = []; | ||
| AdapterId.setSpy(spy); | ||
| expect(spy.length).toBe(0); | ||
|
|
@@ -112,7 +112,7 @@ describe('wiring', () => { | |
| }); | ||
| }); | ||
|
|
||
| it('should be called next tick when the component with wire that has dynamic params is created', () => { | ||
| it('should be called next tick when the component with wire that has dynamic params is created', async () => { | ||
| const spy = []; | ||
| AdapterId.setSpy(spy); | ||
| expect(spy.length).toBe(0); | ||
|
|
@@ -130,7 +130,7 @@ describe('wiring', () => { | |
| }); | ||
| }); | ||
|
|
||
| it('should call update only once when the component is created and a wire dynamic param is modified in the same tick', () => { | ||
| it('should call update only once when the component is created and a wire dynamic param is modified in the same tick', async () => { | ||
| const spy = []; | ||
| AdapterId.setSpy(spy); | ||
| expect(spy.length).toBe(0); | ||
|
|
@@ -147,7 +147,7 @@ describe('wiring', () => { | |
| }); | ||
| }); | ||
|
|
||
| it('should be called only once during multiple renders when the wire config does not change', () => { | ||
| it('should be called only once during multiple renders when the wire config does not change', async () => { | ||
| const spy = []; | ||
| AdapterId.setSpy(spy); | ||
| const elm = createElement('x-echo-adapter-consumer', { is: ComponentClass }); | ||
|
|
@@ -165,7 +165,7 @@ describe('wiring', () => { | |
| }); | ||
| }); | ||
|
|
||
| it('should be called when the wire parameters change its value.', () => { | ||
| it('should be called when the wire parameters change its value.', async () => { | ||
| const spy = []; | ||
| AdapterId.setSpy(spy); | ||
| const elm = createElement('x-echo-adapter-consumer', { is: ComponentClass }); | ||
|
|
@@ -186,7 +186,7 @@ describe('wiring', () => { | |
| }); | ||
| }); | ||
|
|
||
| it('should be called for common parameter when shared among wires', () => { | ||
| it('should be called for common parameter when shared among wires', async () => { | ||
| const spy = []; | ||
| AdapterId.setSpy(spy); | ||
| const elm = createElement('x-bc-consumer', { is: BroadcastConsumer }); | ||
|
|
@@ -209,7 +209,7 @@ describe('wiring', () => { | |
| }); | ||
| }); | ||
|
|
||
| it('should not update when setting parameter with same value', () => { | ||
| it('should not update when setting parameter with same value', async () => { | ||
| const spy = []; | ||
| const elm = createElement('x-echo-adapter-consumer', { is: ComponentClass }); | ||
| document.body.appendChild(elm); | ||
|
|
@@ -255,7 +255,7 @@ describe('wiring', () => { | |
| expect(dynamicValue.textContent).toBe('modified value'); | ||
| }); | ||
|
|
||
| it('should not call update when component is disconnected.', () => { | ||
| it('should not call update when component is disconnected.', async () => { | ||
| const spy = []; | ||
| AdapterId.setSpy(spy); | ||
| const elm = createElement('x-echo-adapter-consumer', { is: ComponentClass }); | ||
|
|
@@ -272,7 +272,7 @@ describe('wiring', () => { | |
| }); | ||
| }); | ||
|
|
||
| it('should call update when component is re-connected.', () => { | ||
| it('should call update when component is re-connected.', async () => { | ||
| const spy = []; | ||
| AdapterId.setSpy(spy); | ||
| const elm = createElement('x-echo-adapter-consumer', { is: ComponentClass }); | ||
|
|
@@ -302,7 +302,7 @@ describe('wiring', () => { | |
| }); | ||
|
|
||
| describe('wired fields', () => { | ||
| it('should rerender component when adapter pushes data', () => { | ||
| it('should rerender component when adapter pushes data', async () => { | ||
| BroadcastAdapter.clearInstances(); | ||
| const elm = createElement('x-bc-consumer', { is: BroadcastConsumer }); | ||
| document.body.appendChild(elm); | ||
|
|
@@ -322,7 +322,7 @@ describe('wired fields', () => { | |
| }); | ||
| }); | ||
|
|
||
| it('should rerender component when wired field is mutated from within the component', () => { | ||
| it('should rerender component when wired field is mutated from within the component', async () => { | ||
| BroadcastAdapter.clearInstances(); | ||
| const elm = createElement('x-bc-consumer', { is: BroadcastConsumer }); | ||
| document.body.appendChild(elm); | ||
|
|
@@ -343,7 +343,7 @@ describe('wired fields', () => { | |
| }); | ||
|
|
||
| describe('wired methods', () => { | ||
| it('should call component method when wired to a method', () => { | ||
| it('should call component method when wired to a method', async () => { | ||
| BroadcastAdapter.clearInstances(); | ||
| const elm = createElement('x-bc-consumer', { is: BroadcastConsumer }); | ||
| document.body.appendChild(elm); | ||
|
|
@@ -355,7 +355,7 @@ describe('wired methods', () => { | |
| }); | ||
| }); | ||
|
|
||
| it('should support method override', () => { | ||
| it('should support method override', async () => { | ||
| const spy = []; | ||
| EchoWireAdapter.setSpy(spy); | ||
| const elm = createElement('x-inherited-methods', { is: InheritedMethods }); | ||
|
|
@@ -376,7 +376,7 @@ describe('wired methods', () => { | |
| }); | ||
|
|
||
| describe('context aware', () => { | ||
| it('should receive the source element tag name when adapter is constructed', () => { | ||
| it('should receive the source element tag name when adapter is constructed', async () => { | ||
| const spy = []; | ||
| ContextLog.setSpy(spy); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,9 @@ | ||
| import { join } from 'node:path'; | ||
| import { LWC_VERSION } from '@lwc/shared'; | ||
| import * as options from './helpers/options.mjs'; | ||
| import wrapHydrationTest from './helpers/hydration-tests.mjs'; | ||
| import * as options from '../helpers/options.mjs'; | ||
|
|
||
| const pluck = (obj, keys) => Object.fromEntries(keys.map((k) => [k, Boolean(obj[k])])); | ||
| const pluck = (obj, keys) => Object.fromEntries(keys.map((k) => [k, obj[k]])); | ||
| const maybeImport = (file, condition) => (condition ? `await import('${file}');` : ''); | ||
|
|
||
| /** `process.env` to inject into test environment. */ | ||
| const env = { | ||
|
|
@@ -20,32 +21,19 @@ const env = { | |
| LWC_VERSION, | ||
| NODE_ENV: options.NODE_ENV_FOR_TEST, | ||
| }; | ||
|
|
||
| /** @type {import("@web/test-runner").TestRunnerConfig} */ | ||
| export default { | ||
| files: [ | ||
| // FIXME: These tests are just symlinks to integration-karma for now so the git diff smaller | ||
| 'test-hydration/**/*.spec.js', | ||
| '!test-hydration/light-dom/scoped-styles/replace-scoped-styles-with-dynamic-templates/index.spec.js', | ||
| ], | ||
| nodeResolve: true, | ||
| rootDir: import.meta.dirname, | ||
| rootDir: join(import.meta.dirname, '..'), | ||
| plugins: [ | ||
| { | ||
| resolveImport({ source }) { | ||
| if (source === 'test-utils') { | ||
| return '/helpers/wtr-utils.mjs'; | ||
| return '/helpers/utils.mjs'; | ||
| } else if (source === 'wire-service') { | ||
| return '@lwc/wire-service'; | ||
| } | ||
| }, | ||
| async serve(ctx) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| // Hydration test "index.spec.js" files are actually just config files. | ||
| // They don't directly define the tests. Instead, when we request the file, | ||
| // we wrap it with some boilerplate. That boilerplate must include the config | ||
| // file we originally requested, so the ?original query parameter is used | ||
| // to return the file unmodified. | ||
| if (ctx.path.endsWith('.spec.js') && !ctx.query.original) { | ||
| return await wrapHydrationTest(ctx.path.slice(1)); // remove leading / | ||
| // `/__wds-outside-roout__/${depth}/` === '../'.repeat(depth) | ||
wjhsf marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return '/__wds-outside-root__/1/wire-service/dist/index.js'; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Turns out what I originally had never actually worked. 😅
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand this path, is that where modules compiled by wtr ends up?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a magic path that WTR1 uses to serve files that exist outside the web root (the package directory). In our case, it's primarily used by WTR for resolving 1 technically |
||
| } | ||
| }, | ||
| async transform(ctx) { | ||
|
|
@@ -65,9 +53,11 @@ export default { | |
| globalThis.lwcRuntimeFlags = ${JSON.stringify( | ||
| pluck(options, ['DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE']) | ||
| )}; | ||
|
|
||
| ${maybeImport('@lwc/synthetic-shadow', !options.DISABLE_SYNTHETIC)} | ||
| ${maybeImport('@lwc/aria-reflection', options.ENABLE_ARIA_REFLECTION_GLOBAL_POLYFILL)} | ||
| </script> | ||
| <script type="module" src="./helpers/setup.mjs"></script> | ||
| <script type="module" src="./helpers/wtr-utils.mjs"></script> | ||
| <script type="module" src="${testFramework}"></script> | ||
| </body> | ||
| </html>`, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // Use native shadow by default in hydration tests; MUST be set before imports | ||
| process.env.DISABLE_SYNTHETIC ??= 'true'; | ||
|
Comment on lines
+1
to
+2
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's probably a more idiomatic way of doing this, but the hack works for now. 🤷 |
||
| import baseConfig from './base.mjs'; | ||
| import hydrationTestPlugin from './plugins/serve-hydration.mjs'; | ||
|
|
||
| /** @type {import("@web/test-runner").TestRunnerConfig} */ | ||
| export default { | ||
| ...baseConfig, | ||
| files: [ | ||
| // FIXME: These tests are just symlinks to integration-karma for now so the git diff smaller | ||
| 'test-hydration/**/*.spec.js', | ||
| // FIXME: hits timeout? | ||
| '!test-hydration/light-dom/scoped-styles/replace-scoped-styles-with-dynamic-templates/index.spec.js', | ||
| // FIXME: This uses ENABLE_SYNTHETIC_SHADOW_IN_MIGRATION to detect status, | ||
| // we should just use DISABLE_SYNTHETIC instead | ||
| '!test-hydration/synthetic-shadow/index.spec.js', | ||
| ], | ||
| plugins: [...baseConfig.plugins, hydrationTestPlugin], | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
toEqualWireSettingsis never actually used anywhere.