diff --git a/.github/workflows/web-test-runner.yml b/.github/workflows/web-test-runner.yml
deleted file mode 100644
index 73f91b39f2..0000000000
--- a/.github/workflows/web-test-runner.yml
+++ /dev/null
@@ -1,163 +0,0 @@
-name: Web Test Runner
-
-on:
- push:
- branches:
- - master
- - release
- - 'spring*'
- - 'summer*'
- - 'winter*'
- pull_request:
-
-env:
- COVERAGE: '1'
- NODE_VERSION: '20.19.4'
-
-defaults:
- run:
- working-directory: packages/@lwc/integration-not-karma
-
-jobs:
- # We run tests in parallel to speed up CI, with an arbitrary goal of ~20 minutes per job.
- # TODO: upload result artifacts
-
- integration-tests:
- name: Integration tests (${{ matrix.shadow_mode }} shadow; ${{ matrix.env || 'default env' }})
- runs-on: ubuntu-22.04
- strategy:
- fail-fast: false
- matrix:
- shadow_mode: [native, synthetic]
- env:
- - ''
- # TODO: Fix
- # - DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE=1
- - DISABLE_STATIC_CONTENT_OPTIMIZATION=1
- - ENABLE_ARIA_REFLECTION_GLOBAL_POLYFILL=1
- - NODE_ENV_FOR_TEST=production
- - API_VERSION=58
- - API_VERSION=59
- - API_VERSION=60
- - API_VERSION=61
- - API_VERSION=62
- # No need for 63-65
- - API_VERSION=66
-
- include:
- # Test modes for only synthetic or only native
- - shadow_mode: synthetic
- env: FORCE_NATIVE_SHADOW_MODE_FOR_TEST=1
- - shadow_mode: synthetic
- env: DISABLE_DETACHED_REHYDRATION=1
- # TODO: Fix
- # - shadow_mode: synthetic
- # env: DISABLE_DETACHED_REHYDRATION=1 DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE=1
- - shadow_mode: native
- env: DISABLE_SYNTHETIC_SHADOW_SUPPORT_IN_COMPILER=1
- - shadow_mode: native
- env: DISABLE_SYNTHETIC_SHADOW_SUPPORT_IN_COMPILER=1 DISABLE_STATIC_CONTENT_OPTIMIZATION=1
-
- env:
- SHADOW_MODE_OVERRIDE: ${{ matrix.shadow_mode }}
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v5
-
- - name: Setup Node
- uses: actions/setup-node@v6
- with:
- node-version: ${{ env.NODE_VERSION }}
- cache: 'yarn'
-
- - name: Install dependencies
- run: yarn install --frozen-lockfile
- working-directory: ./
-
- - name: Install playwright dependencies
- run: yarn playwright install chrome firefox webkit --with-deps
-
- - name: Set env vars
- run: echo '${{ matrix.env }}' | tr ' ' '\n' >> "$GITHUB_ENV"
-
- - name: Sanity check env vars
- run: |
- echo "API_VERSION=$API_VERSION"
- echo "DISABLE_DETACHED_REHYDRATION=$DISABLE_DETACHED_REHYDRATION"
- echo "DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE=$DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE"
- echo "DISABLE_STATIC_CONTENT_OPTIMIZATION=$DISABLE_STATIC_CONTENT_OPTIMIZATION"
- echo "DISABLE_SYNTHETIC_SHADOW_SUPPORT_IN_COMPILER=$DISABLE_SYNTHETIC_SHADOW_SUPPORT_IN_COMPILER"
- echo "ENABLE_ARIA_REFLECTION_GLOBAL_POLYFILL=$ENABLE_ARIA_REFLECTION_GLOBAL_POLYFILL"
- echo "FORCE_NATIVE_SHADOW_MODE_FOR_TEST=$FORCE_NATIVE_SHADOW_MODE_FOR_TEST"
- echo "NODE_ENV_FOR_TEST=$NODE_ENV_FOR_TEST"
-
- - name: Run integration tests
- run: yarn test
-
- - name: Upload coverage report
- # Upload coverage even if the test step failed
- if: always()
- run: |
- [ -f coverage/index.html ] && awk '/
/' coverage/index.html >> "$GITHUB_STEP_SUMMARY"
-
- hydration-tests:
- name: Hydration tests (${{ matrix.engine_server && 'engine-server' || 'SSR v2' }}; ${{ matrix.env || 'default env' }})
- runs-on: ubuntu-22.04
- strategy:
- fail-fast: false
- matrix:
- engine_server: ['', 1]
- env:
- - ''
- - SHADOW_MODE_OVERRIDE=synthetic
- - NODE_ENV_FOR_TEST=production
- - DISABLE_STATIC_CONTENT_OPTIMIZATION=1
- include:
- - engine_server: 1
- env: DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE=1
- - engine_server: 1
- env: DISABLE_DETACHED_REHYDRATION=1
- - engine_server: 1
- env: DISABLE_DETACHED_REHYDRATION=1 DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE=1
-
- env:
- ENGINE_SERVER: ${{ matrix.engine_server }}
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v5
-
- - name: Setup Node
- uses: actions/setup-node@v6
- with:
- node-version: ${{ env.NODE_VERSION }}
- cache: 'yarn'
-
- - name: Install dependencies
- run: yarn install --frozen-lockfile
- working-directory: ./
-
- - name: Install playwright dependencies
- run: yarn playwright install chrome firefox webkit --with-deps
-
- - name: Set env vars
- run: echo '${{ matrix.env }}' | tr ' ' '\n' >> "$GITHUB_ENV"
-
- - name: Sanity check env vars
- run: |
- echo "SHADOW_MODE_OVERRIDE=$SHADOW_MODE_OVERRIDE"
- echo "NODE_ENV_FOR_TEST=$NODE_ENV_FOR_TEST"
- echo "DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE=$DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE"
- echo "DISABLE_STATIC_CONTENT_OPTIMIZATION=$DISABLE_STATIC_CONTENT_OPTIMIZATION"
- echo "DISABLE_DETACHED_REHYDRATION=$DISABLE_DETACHED_REHYDRATION"
- echo "ENGINE_SERVER=$ENGINE_SERVER"
-
- - name: Run hydration tests
- run: yarn test:hydration
-
- - name: Upload coverage report
- # Upload coverage even if the test step failed
- if: always()
- run: |
- [ -f coverage/index.html ] && awk '//' coverage/index.html >> "$GITHUB_STEP_SUMMARY"
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
new file mode 100644
index 0000000000..67443e2187
--- /dev/null
+++ b/.github/workflows/windows.yml
@@ -0,0 +1,64 @@
+name: Smoke Test Windows
+
+on:
+ push:
+ branches:
+ - master
+ - release
+ - 'spring*'
+ - 'summer*'
+ - 'winter*'
+ pull_request:
+
+env:
+ COVERAGE: '1'
+
+jobs:
+ smoke-test-windows:
+ runs-on: windows-2025
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v5
+
+ - name: Setup Node
+ uses: actions/setup-node@v6
+ with:
+ node-version: '20.19.4'
+ cache: 'yarn'
+
+ - name: Install dependencies
+ run: yarn install --frozen-lockfile
+
+ - name: Run unit tests
+ run: yarn test run
+
+ - name: Get installed playwright version
+ id: playwright-version
+ run: |
+ version="$(yarn --silent --json list --depth 0 playwright 2>/dev/null | jq -r '.data.trees[0].name|split("@")[1]')"
+ echo "version=$version" >> "$GITHUB_OUTPUT"
+
+ - name: Restore playwright cache
+ uses: actions/cache@v4
+ id: playwright-cache
+ with:
+ path: ~\AppData\Local\ms-playwright
+ key: ${{ runner.os }}-playwright-${{ steps.playwright-version.outputs.version }}
+
+ - name: Install playwright dependencies
+ id: install-playwright
+ continue-on-error: true
+ run: yarn playwright install chromium --with-deps
+ timeout-minutes: 3 # Sometimes seems to just hang forever? :|
+
+ # If installing playwright times out, wait 1 minute then try again
+ - name: Install playwright dependencies
+ if: ${{ steps.install-playwright.outcome != 'success' }}
+ run: sleep 60 && yarn playwright install chromium --with-deps
+ timeout-minutes: 4
+
+ - name: Run integration tests
+ run: yarn test || yarn test
+ env:
+ BROWSERS: chromium
+ working-directory: packages/@lwc/integration-not-karma
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures.spec.ts b/packages/@lwc/engine-server/src/__tests__/fixtures.spec.ts
index 14a05b484a..9c36e5ef80 100755
--- a/packages/@lwc/engine-server/src/__tests__/fixtures.spec.ts
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures.spec.ts
@@ -70,7 +70,7 @@ async function compileFixture({
.join('-') || 'default';
const modulesDir = path.resolve(dirname, './modules');
const outputFile = path.resolve(dirname, `./dist/compiled-${optionsAsString}.js`);
- const input = 'virtual/fixture/test.js';
+ const input = path.normalize('virtual/fixture/test.js');
const bundle = await rollup({
input,
diff --git a/packages/@lwc/integration-not-karma/README.md b/packages/@lwc/integration-not-karma/README.md
index 37f6669c06..1cedb9ef75 100644
--- a/packages/@lwc/integration-not-karma/README.md
+++ b/packages/@lwc/integration-not-karma/README.md
@@ -24,6 +24,8 @@ Environment variables are used as controls to run tests in different modes (e.g
By default, the tests are run using Playwright. If the `USE_SAUCE` env var is set, then SauceLabs is used instead. To use SauceLabs, the `SAUCE_USERNAME`, `SAUCE_ACCESS_KEY`, and `SAUCE_TUNNEL_ID` env vars must be set.
+To run tests in a specific browser, rather than the defaults specified, set the `BROWSERS` env var.
+
### Integration Tests
Integration tests are simply `.spec.js` files that run in the browser. LWC components are transformed by a plugin defined in `serve-integration.js`.
diff --git a/packages/@lwc/integration-not-karma/configs/shared/browsers.js b/packages/@lwc/integration-not-karma/configs/shared/browsers.js
index 945452d5fa..7cc39769a6 100644
--- a/packages/@lwc/integration-not-karma/configs/shared/browsers.js
+++ b/packages/@lwc/integration-not-karma/configs/shared/browsers.js
@@ -45,10 +45,7 @@ export function getBrowsers(options) {
}),
];
} else {
- return [
- playwrightLauncher({ product: 'chromium' }),
- playwrightLauncher({ product: 'firefox' }),
- playwrightLauncher({ product: 'webkit' }),
- ];
+ const browsers = options.BROWSERS?.split(',') ?? ['chromium', 'firefox', 'webkit'];
+ return browsers.map((product) => playwrightLauncher({ product }));
}
}
diff --git a/packages/@lwc/integration-not-karma/helpers/options.js b/packages/@lwc/integration-not-karma/helpers/options.js
index 1adf5fdc36..3c8f3e5502 100644
--- a/packages/@lwc/integration-not-karma/helpers/options.js
+++ b/packages/@lwc/integration-not-karma/helpers/options.js
@@ -6,9 +6,6 @@ import { HIGHEST_API_VERSION } from '@lwc/shared';
// --- Boolean test flags --- //
-/** Run SauceLabs tests using only "legacy" browsers. */
-export const LEGACY_BROWSERS = Boolean(process.env.LEGACY_BROWSERS);
-
/** Force tests to run in native shadow mode with synthetic shadow polyfill patches. */
export const FORCE_NATIVE_SHADOW_MODE_FOR_TEST = Boolean(
process.env.FORCE_NATIVE_SHADOW_MODE_FOR_TEST
@@ -58,28 +55,16 @@ export const API_VERSION = process.env.API_VERSION
/** The `NODE_ENV` to set for tests (at runtime, in the browser). */
export const NODE_ENV_FOR_TEST = process.env.NODE_ENV_FOR_TEST || 'development';
-/** Unique directory name that encodes the flags that the tests were executed with. */
-export const COVERAGE_DIR_FOR_OPTIONS =
- Object.entries({
- API_VERSION,
- DISABLE_STATIC_CONTENT_OPTIMIZATION,
- SHADOW_MODE_OVERRIDE,
- DISABLE_SYNTHETIC_SHADOW_SUPPORT_IN_COMPILER,
- ENABLE_ARIA_REFLECTION_GLOBAL_POLYFILL,
- FORCE_NATIVE_SHADOW_MODE_FOR_TEST,
- LEGACY_BROWSERS,
- NODE_ENV_FOR_TEST,
- DISABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE,
- ENGINE_SERVER,
- DISABLE_DETACHED_REHYDRATION,
- })
- .filter(([, val]) => val)
- .map(([key, val]) => `${key}=${val}`)
- .join('/') || 'no-options';
+/**
+ * Comma-delimited list of browser names to run with Playwright.
+ * Possible values are `chromium`, `firefox`, and `webkit`.
+ * Ignored if the `USE_SAUCE` env var is set.
+ */
+export const BROWSERS = process.env.BROWSERS;
// --- CI config --- //
-/** Whether or not to report coverage. Currently unused. */
+/** Whether or not to report coverage. */
export const COVERAGE = Boolean(process.env.COVERAGE);
/** Whether or not we're running in CI. */
export const CI = Boolean(process.env.CI);
@@ -102,3 +87,5 @@ export const {
/** SauceLabs tunnel ID. */
SAUCE_TUNNEL_ID,
} = process.env;
+/** Run SauceLabs tests using only "legacy" browsers. */
+export const LEGACY_BROWSERS = Boolean(process.env.LEGACY_BROWSERS);
diff --git a/packages/@lwc/ssr-compiler/src/__tests__/fixtures.spec.ts b/packages/@lwc/ssr-compiler/src/__tests__/fixtures.spec.ts
index 559a30ae3d..169612f884 100644
--- a/packages/@lwc/ssr-compiler/src/__tests__/fixtures.spec.ts
+++ b/packages/@lwc/ssr-compiler/src/__tests__/fixtures.spec.ts
@@ -65,7 +65,7 @@ async function compileFixture({
}) {
const modulesDir = path.resolve(dirname, './modules');
const outputFile = path.resolve(dirname, './dist/compiled-experimental-ssr.js');
- const input = 'virtual/fixture/test.js';
+ const input = path.normalize('virtual/fixture/test.js');
const bundle = await rollup({
input,