Skip to content

Commit 9223fc6

Browse files
authored
test(wtr): run integration tests in native and synthetic shadow modes @W-19098130 (#5517)
* test(wtr): run all the flavors and see what happens * test(wtr): prefer DISABLE_SYNTHETIC over duplicate env var name * test(wtr): fix hydration tests they weren't actually running before 😰 * test(wtr): create `process.env` with only string values * test(wtr): split integration and hydration tests into separate jobs * Revert "test(wtr): prefer DISABLE_SYNTHETIC over duplicate env var name" This reverts commit 0c81acb. * test(wtr): revert to using original env var * test(wtr): make integration and hydration tests have different default shadow modes they were supposed to all along, but it was implemented incorrectly * test(wtr): fix tests running in native shadow mode * test(wtr): make working tests fail for real in CI if they break * test(wtr): avoid accidentally not running tests again * test(wtr): enable FORCE_NATIVE_SHADOW_MODE_FOR_TEST in CI * test(wtr): enable DISABLE_DETACHED_REHYDRATION=1 in CI * test(wtr): enable more test scenarios in CI * test(wtr): split CI job into groups * test(wtr): remove matrix config from job that doesn't need it oops * test(wtr): enable API_VERSION tests in CI and alphabetize list also make john fix it later * test(wtr): use vitest spy instead of jasmine spy * test(wtr): fix broken test assertion
1 parent e9cf8c7 commit 9223fc6

File tree

13 files changed

+257
-145
lines changed

13 files changed

+257
-145
lines changed

.github/workflows/web-test-runner.yml

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,18 @@ env:
1818
NODE_VERSION: '20.19.4'
1919

2020
jobs:
21-
# Starting with the basics, just get tests running in CI
22-
# TODO: add env var combos we use for Karma tests
2321
# TODO: upload result artifacts
2422
# TODO: make it saucy 🥫
25-
wtr-group-1:
23+
integration-tests:
24+
name: Integration tests (${{ matrix.shadow_mode }} shadow)
25+
strategy:
26+
matrix:
27+
shadow_mode: [native, synthetic]
28+
2629
runs-on: ubuntu-22.04
2730
env:
2831
SAUCE_TUNNEL_ID: github-action-tunnel-wtr-${{github.run_id}}-group-1
32+
SHADOW_MODE_OVERRIDE: ${{ matrix.shadow_mode }}
2933
defaults:
3034
run:
3135
working-directory: ./packages/@lwc/integration-not-karma
@@ -51,4 +55,93 @@ jobs:
5155
# region: us
5256

5357
- run: yarn test
58+
- run: API_VERSION=58 yarn test
59+
- run: API_VERSION=59 yarn test
60+
- run: API_VERSION=60 yarn test
61+
- run: API_VERSION=61 yarn test
62+
- run: API_VERSION=62 yarn test
63+
- run: DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE=1 yarn test || true
64+
- run: DISABLE_STATIC_CONTENT_OPTIMIZATION=1 yarn test
65+
- run: ENABLE_ARIA_REFLECTION_GLOBAL_POLYFILL=1 yarn test
66+
- run: NODE_ENV_FOR_TEST=production yarn test
67+
68+
integration-tests-not-both-modes:
69+
# Tests that should run in only synthetic or native shadow, not both
70+
name: Integration tests (singleton batch)
71+
runs-on: ubuntu-22.04
72+
env:
73+
SAUCE_TUNNEL_ID: github-action-tunnel-wtr-${{github.run_id}}-group-1
74+
SHADOW_MODE_OVERRIDE: ${{ matrix.shadow_mode }}
75+
defaults:
76+
run:
77+
working-directory: ./packages/@lwc/integration-not-karma
78+
steps:
79+
- name: Checkout repository
80+
uses: actions/checkout@v4
81+
82+
- name: Setup Node
83+
uses: actions/setup-node@v4
84+
with:
85+
node-version: ${{ env.NODE_VERSION }}
86+
cache: 'yarn'
87+
88+
- name: Install dependencies
89+
run: yarn install --frozen-lockfile
90+
working-directory: ./
91+
92+
# - uses: saucelabs/sauce-connect-action@v3.0.0
93+
# with:
94+
# username: ${{ secrets.SAUCE_USERNAME }}
95+
# accessKey: ${{ secrets.SAUCE_ACCESS_KEY }}
96+
# tunnelName: ${{ env.SAUCE_TUNNEL_ID }}
97+
# region: us
98+
99+
# Synthetic shadow only
100+
- run: LEGACY_BROWSERS=1 yarn test || true
101+
- run: FORCE_NATIVE_SHADOW_MODE_FOR_TEST=1 yarn test
102+
- run: DISABLE_DETACHED_REHYDRATION=1 yarn test
103+
- run: DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE=1 DISABLE_DETACHED_REHYDRATION=1 yarn test || true
104+
105+
# Native shadow only -- don't forget SHADOW_MODE_OVERRIDE!
106+
- run: SHADOW_MODE_OVERRIDE=native DISABLE_SYNTHETIC_SHADOW_SUPPORT_IN_COMPILER=1 yarn test
107+
- run: SHADOW_MODE_OVERRIDE=native DISABLE_SYNTHETIC_SHADOW_SUPPORT_IN_COMPILER=1 DISABLE_STATIC_CONTENT_OPTIMIZATION=1 yarn test
108+
109+
hydration-tests:
110+
runs-on: ubuntu-22.04
111+
env:
112+
SAUCE_TUNNEL_ID: github-action-tunnel-wtr-${{github.run_id}}-group-1
113+
defaults:
114+
run:
115+
working-directory: ./packages/@lwc/integration-not-karma
116+
steps:
117+
- name: Checkout repository
118+
uses: actions/checkout@v4
119+
120+
- name: Setup Node
121+
uses: actions/setup-node@v4
122+
with:
123+
node-version: ${{ env.NODE_VERSION }}
124+
cache: 'yarn'
125+
126+
- name: Install dependencies
127+
run: yarn install --frozen-lockfile
128+
working-directory: ./
129+
130+
# - uses: saucelabs/sauce-connect-action@v3.0.0
131+
# with:
132+
# username: ${{ secrets.SAUCE_USERNAME }}
133+
# accessKey: ${{ secrets.SAUCE_ACCESS_KEY }}
134+
# tunnelName: ${{ env.SAUCE_TUNNEL_ID }}
135+
# region: us
136+
- run: ENGINE_SERVER=1 yarn test:hydration
137+
- run: ENGINE_SERVER=1 SHADOW_MODE_OVERRIDE=synthetic yarn test:hydration
138+
- run: ENGINE_SERVER=1 NODE_ENV_FOR_TEST=production yarn test:hydration
139+
- run: ENGINE_SERVER=1 DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE=1 yarn test:hydration
140+
- run: ENGINE_SERVER=1 DISABLE_STATIC_CONTENT_OPTIMIZATION=1 yarn test:hydration
141+
- run: ENGINE_SERVER=1 DISABLE_DETACHED_REHYDRATION=1 yarn test:hydration
142+
- run: ENGINE_SERVER=1 DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE=1 DISABLE_DETACHED_REHYDRATION=1 yarn test:hydration
54143
- run: yarn test:hydration
144+
- run: SHADOW_MODE_OVERRIDE=synthetic yarn test:hydration
145+
- run: NODE_ENV_FOR_TEST=production yarn test:hydration
146+
- run: DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE=1 yarn test:hydration
147+
- run: DISABLE_STATIC_CONTENT_OPTIMIZATION=1 yarn test:hydration
Lines changed: 60 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,70 @@
11
import { join } from 'node:path';
22
import { LWC_VERSION } from '@lwc/shared';
3-
import * as options from '../helpers/options.js';
43
import { resolvePathOutsideRoot } from '../helpers/utils.js';
54

5+
/**
6+
* We want to convert from parsed options (true/false) to a `process.env` with only strings.
7+
* This drops `false` values and converts everything else to a string.
8+
*/
9+
const envify = (obj) => {
10+
const clone = {};
11+
for (const [key, val] of Object.entries(obj)) {
12+
if (val !== false) {
13+
clone[key] = String(val);
14+
}
15+
}
16+
return clone;
17+
};
618
const pluck = (obj, keys) => Object.fromEntries(keys.map((k) => [k, obj[k]]));
719
const maybeImport = (file, condition) => (condition ? `await import('${file}');` : '');
820

9-
/** `process.env` to inject into test environment. */
10-
const env = {
11-
...pluck(options, [
12-
'API_VERSION',
13-
'DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE',
14-
'DISABLE_STATIC_CONTENT_OPTIMIZATION',
15-
'DISABLE_SYNTHETIC',
16-
'ENABLE_ARIA_REFLECTION_GLOBAL_POLYFILL',
17-
'ENGINE_SERVER',
18-
'FORCE_NATIVE_SHADOW_MODE_FOR_TEST',
19-
'NATIVE_SHADOW',
20-
'DISABLE_DETACHED_REHYDRATION',
21-
]),
22-
LWC_VERSION,
23-
NODE_ENV: options.NODE_ENV_FOR_TEST,
24-
};
21+
/** @type {() => import("@web/test-runner").TestRunnerConfig} */
22+
export default (options) => {
23+
/** `process.env` to inject into test environment. */
24+
const env = envify({
25+
...pluck(options, [
26+
'API_VERSION',
27+
'DISABLE_DETACHED_REHYDRATION',
28+
'DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE',
29+
'DISABLE_STATIC_CONTENT_OPTIMIZATION',
30+
'ENABLE_ARIA_REFLECTION_GLOBAL_POLYFILL',
31+
'ENGINE_SERVER',
32+
'FORCE_NATIVE_SHADOW_MODE_FOR_TEST',
33+
'NATIVE_SHADOW',
34+
]),
35+
LWC_VERSION,
36+
NODE_ENV: options.NODE_ENV_FOR_TEST,
37+
});
2538

26-
/** @type {import("@web/test-runner").TestRunnerConfig} */
27-
export default {
28-
// FIXME: Parallelism breaks tests that rely on focus/requestAnimationFrame, because they often
29-
// time out before they receive focus. But it also makes the full suite take 3x longer to run...
30-
// Potential workaround: https://github.com/modernweb-dev/web/issues/2588
31-
concurrency: 1,
32-
browserLogs: false,
33-
nodeResolve: true,
34-
rootDir: join(import.meta.dirname, '..'),
35-
plugins: [
36-
{
37-
name: 'lwc-base-plugin',
38-
resolveImport({ source }) {
39-
if (source === 'wire-service') {
40-
return resolvePathOutsideRoot('../wire-service/dist/index.js');
41-
}
42-
},
43-
async transform(ctx) {
44-
if (ctx.type === 'application/javascript') {
45-
// FIXME: copy/paste Nolan's spiel about why we do this ugly thing
46-
return ctx.body.replace(/process\.env\.NODE_ENV === 'test-karma-lwc'/g, 'true');
47-
}
39+
return {
40+
// FIXME: Parallelism breaks tests that rely on focus/requestAnimationFrame, because they often
41+
// time out before they receive focus. But it also makes the full suite take 3x longer to run...
42+
// Potential workaround: https://github.com/modernweb-dev/web/issues/2588
43+
concurrency: 1,
44+
browserLogs: false,
45+
nodeResolve: true,
46+
rootDir: join(import.meta.dirname, '..'),
47+
plugins: [
48+
{
49+
name: 'lwc-base-plugin',
50+
resolveImport({ source }) {
51+
if (source === 'wire-service') {
52+
return resolvePathOutsideRoot('../wire-service/dist/index.js');
53+
}
54+
},
55+
async transform(ctx) {
56+
if (ctx.type === 'application/javascript') {
57+
// FIXME: copy/paste Nolan's spiel about why we do this ugly thing
58+
return ctx.body.replace(
59+
/process\.env\.NODE_ENV === 'test-karma-lwc'/g,
60+
'true'
61+
);
62+
}
63+
},
4864
},
49-
},
50-
],
51-
testRunnerHtml: (testFramework) =>
52-
`<!DOCTYPE html>
65+
],
66+
testRunnerHtml: (testFramework) =>
67+
`<!DOCTYPE html>
5368
<html>
5469
<head>
5570
<script type="module">
@@ -61,11 +76,12 @@ export default {
6176
])
6277
)};
6378
64-
${maybeImport('@lwc/synthetic-shadow', !options.DISABLE_SYNTHETIC)}
79+
${maybeImport('@lwc/synthetic-shadow', !options.NATIVE_SHADOW)}
6580
${maybeImport('@lwc/aria-reflection', options.ENABLE_ARIA_REFLECTION_GLOBAL_POLYFILL)}
6681
</script>
6782
<script type="module" src="./helpers/setup.js"></script>
6883
<script type="module" src="${testFramework}"></script>
6984
</head>
7085
</html>`,
86+
};
7187
};

packages/@lwc/integration-not-karma/configs/hydration.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
// Use native shadow by default in hydration tests; MUST be set before imports
2-
process.env.DISABLE_SYNTHETIC ??= 'true';
3-
import baseConfig from './base.js';
1+
import * as options from '../helpers/options.js';
2+
import createConfig from './base.js';
43
import hydrationTestPlugin from './plugins/serve-hydration.js';
54

5+
const SHADOW_MODE = options.SHADOW_MODE_OVERRIDE ?? 'native';
6+
7+
const baseConfig = createConfig({
8+
...options,
9+
NATIVE_SHADOW: SHADOW_MODE === 'native' || options.FORCE_NATIVE_SHADOW_MODE_FOR_TEST,
10+
});
11+
612
/** @type {import("@web/test-runner").TestRunnerConfig} */
713
export default {
814
...baseConfig,

packages/@lwc/integration-not-karma/configs/integration.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
import { importMapsPlugin } from '@web/dev-server-import-maps';
2-
import baseConfig from './base.js';
2+
import * as options from '../helpers/options.js';
3+
import createConfig from './base.js';
34
import testPlugin from './plugins/serve-integration.js';
45

6+
const SHADOW_MODE = options.SHADOW_MODE_OVERRIDE ?? 'synthetic';
7+
8+
const baseConfig = createConfig({
9+
...options,
10+
NATIVE_SHADOW: SHADOW_MODE === 'native' || options.FORCE_NATIVE_SHADOW_MODE_FOR_TEST,
11+
});
12+
513
/** @type {import("@web/test-runner").TestRunnerConfig} */
614
export default {
715
...baseConfig,
8-
files: ['test/**/*.spec.js'],
16+
files: [
17+
'test/**/*.spec.js',
18+
// Make John fix this after his PR is merged
19+
'!test/template-expressions/errors/index.spec.js',
20+
'!test/template-expressions/smoke-test/index.spec.js',
21+
],
922
plugins: [
1023
...baseConfig.plugins,
1124
importMapsPlugin({ inject: { importMap: { imports: { lwc: './mocks/lwc.js' } } } }),

packages/@lwc/integration-not-karma/configs/plugins/test-hydration.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ export function runTest(configPath, componentPath, ssrRendered) {
5252
let Component;
5353

5454
beforeAll(async () => {
55-
testConfig = await import(configPath);
56-
Component = await import(componentPath);
55+
testConfig = (await import(configPath)).default;
56+
Component = (await import(componentPath)).default;
5757
setFeatureFlags(testConfig.requiredFeatureFlags, true);
5858
});
5959

@@ -93,6 +93,8 @@ export function runTest(configPath, componentPath, ssrRendered) {
9393
container,
9494
selector,
9595
});
96+
} else {
97+
throw new Error(`Missing test or advancedTest function in ${configPath}.`);
9698
}
9799
});
98100
}

packages/@lwc/integration-not-karma/helpers/options.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import { HIGHEST_API_VERSION } from '@lwc/shared';
88

99
export const LEGACY_BROWSERS = Boolean(process.env.LEGACY_BROWSERS);
1010

11-
export const DISABLE_SYNTHETIC = Boolean(process.env.DISABLE_SYNTHETIC);
12-
1311
export const FORCE_NATIVE_SHADOW_MODE_FOR_TEST = Boolean(
1412
process.env.FORCE_NATIVE_SHADOW_MODE_FOR_TEST
1513
);
@@ -36,20 +34,26 @@ export const ENGINE_SERVER = Boolean(process.env.ENGINE_SERVER);
3634

3735
// --- Test config --- //
3836

37+
/**
38+
* Integration tests default to synthetic shadow mode, while hydration tests default to native.
39+
* This should be set to "native" or "synthetic" to override the default mode.
40+
* @type {'native'|'synthetic'|undefined}
41+
*/
42+
// NOTE: NATIVE_SHADOW is not defined here because integration/hydration have different defaults
43+
export const SHADOW_MODE_OVERRIDE = process.env.SHADOW_MODE_OVERRIDE;
44+
3945
export const API_VERSION = process.env.API_VERSION
4046
? parseInt(process.env.API_VERSION, 10)
4147
: HIGHEST_API_VERSION;
4248

4349
export const NODE_ENV_FOR_TEST = process.env.NODE_ENV_FOR_TEST || 'development';
4450

45-
export const NATIVE_SHADOW = DISABLE_SYNTHETIC || FORCE_NATIVE_SHADOW_MODE_FOR_TEST;
46-
4751
/** Unique directory name that encodes the flags that the tests were executed with. */
4852
export const COVERAGE_DIR_FOR_OPTIONS =
4953
Object.entries({
5054
API_VERSION,
5155
DISABLE_STATIC_CONTENT_OPTIMIZATION,
52-
DISABLE_SYNTHETIC,
56+
SHADOW_MODE_OVERRIDE,
5357
DISABLE_SYNTHETIC_SHADOW_SUPPORT_IN_COMPILER,
5458
ENABLE_ARIA_REFLECTION_GLOBAL_POLYFILL,
5559
FORCE_NATIVE_SHADOW_MODE_FOR_TEST,

packages/@lwc/integration-not-karma/test-hydration/synthetic-shadow/index.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export default {
2222
expect(child.shadowRoot.synthetic).toBeUndefined();
2323

2424
// sanity check that the env var is working
25-
if (process.env.DISABLE_SYNTHETIC) {
25+
if (process.env.NATIVE_SHADOW) {
2626
expect(document.body.attachShadow.toString()).toContain('[native code');
2727
} else {
2828
expect(document.body.attachShadow.toString()).not.toContain('[native code');

packages/@lwc/integration-not-karma/test/component/LightningElement.attachInternals/elementInternals/sanity/index.spec.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ beforeEach(() => {
99
document.body.appendChild(elm);
1010
});
1111

12-
afterEach(() => {
13-
document.body.removeChild(elm);
14-
});
15-
1612
describe.runIf(
1713
ENABLE_ELEMENT_INTERNALS_AND_FACE &&
1814
process.env.NATIVE_SHADOW &&

0 commit comments

Comments
 (0)