Skip to content

test(integration): begin moving from Karma to Web Test Runner #5386

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

Merged
merged 40 commits into from
Jun 13, 2025
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
7dfbce7
hi dale
wjhsf May 20, 2025
831da5a
chore: make `Mocha` available for mutation
divmain May 20, 2025
14762b5
hi mom
wjhsf May 22, 2025
5150f28
Merge branch 'master' into wjh/web-test-runner
wjhsf May 29, 2025
1a3540f
chore: update yarn.lock
wjhsf May 29, 2025
13f2584
chore: remove debuggers
wjhsf May 29, 2025
d710806
fix(wtr): properly inject mocha modifications
wjhsf May 29, 2025
7fcb93d
chore: remove unused matcher
wjhsf May 29, 2025
72593eb
test(wtr): expose LWC_VERSION via process.env
wjhsf May 30, 2025
d99d753
test(wtr): export API features
wjhsf May 30, 2025
ece53a5
test(wtr): just let matchers all pass for now
wjhsf May 30, 2025
304535c
test(wtr): make it more jasminey
wjhsf May 30, 2025
c37ae03
test(wtr): resolve components that don't have JS
wjhsf May 30, 2025
254f2fd
chore: tidy
wjhsf Jun 2, 2025
b93389d
test(wtr): clean up resolve and serve logic
wjhsf Jun 3, 2025
bb70516
test(wtr): some matchers get functions that should be called
wjhsf Jun 3, 2025
34c45b3
test(wtr): add env vars
wjhsf Jun 3, 2025
95d5ed9
test(wtr): replace test-karma-lwc
wjhsf Jun 3, 2025
786a09d
test(wtr): create bridge from jasmine spy to vitest spy
wjhsf Jun 3, 2025
e008650
test(wtr): restore original karma tests and move wtr to not-karma
wjhsf Jun 9, 2025
1127b69
Merge branch 'master' into wjh/web-test-runner
wjhsf Jun 9, 2025
4e84f40
chore(wtr): fix version
wjhsf Jun 9, 2025
47f7ef3
chore(wtr): remove karma stuff from not-karma
wjhsf Jun 9, 2025
addf407
test(wtr): remove wtr files from karma directory
wjhsf Jun 12, 2025
29068fa
test(wtr): make all tests pass
wjhsf Jun 12, 2025
35684a2
test(wtr): rename integration to webdriver
wjhsf Jun 12, 2025
e2b6aa1
test(wtr): add wtr tests to CI
wjhsf Jun 12, 2025
1ca19af
Merge branch 'master' into wjh/web-test-runner
wjhsf Jun 12, 2025
5385e1d
test(wtr): use existing karma tests for smaller diff
wjhsf Jun 12, 2025
7693eab
test(wtr): explain the cross-package file search
wjhsf Jun 12, 2025
7ae54d9
test(wtr): clean up options
wjhsf Jun 12, 2025
e1b5f94
test(wtr): clean up options
wjhsf Jun 12, 2025
1278d69
test(wtr): clean up options
wjhsf Jun 12, 2025
389f678
test(wtr): clean up setup
wjhsf Jun 12, 2025
b43624f
test(wtr): ugh, test-karma-lwc
wjhsf Jun 12, 2025
03c4a63
test(wtr): use symlinks instead of reaching out of the directory
wjhsf Jun 12, 2025
fafb8c7
test(wtr): ignore more tests
wjhsf Jun 12, 2025
f245dd4
test(wtr): lint fixes
wjhsf Jun 12, 2025
415dd09
Apply suggestions from code review
wjhsf Jun 13, 2025
aa4a6bb
chore: fix deps so unit tests pass
wjhsf Jun 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .github/workflows/web-test-runner.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Run Web Test Runner integration tests

on:
push:
branches:
- master
- release
- 'spring*'
- 'summer*'
- 'winter*'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be better to just run on master at first, since older branches won't have the tweaks that are necessary for the Karma-to-WTR migration. We can still run Karma locally for back-ported bug fixes.

pull_request:
branches:
- master
- release
- 'spring*'
- 'summer*'
- 'winter*'

env:
SAUCE_USERNAME: ${{secrets.SAUCE_USERNAME}}
SAUCE_ACCESS_KEY: ${{secrets.SAUCE_ACCESS_KEY}}
GITHUB_RUN_ID: ${{github.run_id}}
COVERAGE: '1'
NODE_VERSION: '20.18.1'

jobs:
# Starting with the basics, just get tests running in CI
# TODO: add env var combos we use for Karma tests
# TODO: upload result artifacts
# TODO: make it saucy 🥫
run-wtr-tests-group-1:
runs-on: ubuntu-22.04
env:
SAUCE_TUNNEL_ID: github-action-tunnel-wtr-${{github.run_id}}-group-1
defaults:
run:
working-directory: ./packages/@lwc/integration-not-karma
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'yarn'

- name: Install dependencies
run: yarn install --frozen-lockfile
working-directory: ./

# - uses: saucelabs/sauce-connect-action@v3.0.0
# with:
# username: ${{ secrets.SAUCE_USERNAME }}
# accessKey: ${{ secrets.SAUCE_ACCESS_KEY }}
# tunnelName: ${{ env.SAUCE_TUNNEL_ID }}
# region: us

- run: yarn test

run-karma-tests:
runs-on: ubuntu-22.04
defaults:
run:
working-directory: ./packages/@lwc/integration-not-karma
needs:
- run-wtr-tests-group-1
File renamed without changes.
4 changes: 2 additions & 2 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ export default tseslint.config(
},
},
{
files: ['packages/@lwc/integration-karma/**'],
files: ['packages/@lwc/integration-karma/**', 'packages/@lwc/integration-not-karma/**'],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent package name.


languageOptions: {
globals: {
Expand Down Expand Up @@ -355,7 +355,7 @@ export default tseslint.config(
},
},
{
files: ['packages/@lwc/integration-karma/**'],
files: ['packages/@lwc/integration-karma/**', 'packages/@lwc/integration-not-karma/**'],

languageOptions: {
globals: {
Expand Down
108 changes: 108 additions & 0 deletions packages/@lwc/integration-not-karma/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# LWC core license

MIT LICENSE

Copyright (c) 2025, Salesforce, Inc.
All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

# Licenses of bundled dependencies

## @parse5/tools

The MIT License (MIT)

Copyright © 2024 James Garbutt

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

## entities

Copyright (c) Felix Böhm
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

## estree-walker

Copyright (c) 2015-20 [these people](https://github.com/Rich-Harris/estree-walker/graphs/contributors)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

## observable-membrane

MIT License

Copyright (c) 2017 Salesforce

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

## parse5

Copyright (c) 2013-2019 Ivan Nikulin (ifaaan@gmail.com, https://github.com/inikulin)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
3 changes: 3 additions & 0 deletions packages/@lwc/integration-not-karma/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# @lwc/integration-not-karma

It's not karma, it's something else!
97 changes: 97 additions & 0 deletions packages/@lwc/integration-not-karma/helpers/lwc.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import path from 'node:path';
import { rollup } from 'rollup';
import lwcRollupPlugin from '@lwc/rollup-plugin';

import {
DISABLE_SYNTHETIC_SHADOW_SUPPORT_IN_COMPILER,
API_VERSION,
DISABLE_STATIC_CONTENT_OPTIMIZATION,
} from './options.mjs';

// Cache reused between each compilation to speed up the compilation time.
let cache;

export default async (ctx) => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a custom wrapper of @lwc/rollup-plugin. It's largely copied from the one used for Karma tests. The primary reason we have this seems to be so that we can use different configs based on the file path of tests.

I don't like that pattern, and eventually I want to investigate using a normal human config file or something.

const input = ctx.path.slice(1); // strip leading / from URL path to get relative file path
const suiteDir = path.dirname(input);

// TODO [#3370]: remove experimental template expression flag
const experimentalComplexExpressions = suiteDir.includes('template-expressions');

const createRollupPlugin = (options) => {
return lwcRollupPlugin({
// Sourcemaps don't work with Istanbul coverage
sourcemap: !process.env.COVERAGE,
experimentalDynamicComponent: {
loader: 'test-utils',
strict: true,
},
enableDynamicComponents: true,
enableLwcOn: true,
experimentalComplexExpressions,
enableStaticContentOptimization: !DISABLE_STATIC_CONTENT_OPTIMIZATION,
disableSyntheticShadowSupport: DISABLE_SYNTHETIC_SHADOW_SUPPORT_IN_COMPILER,
apiVersion: API_VERSION,
modules: [
{
// Assume `ctx.path` is a component file, e.g. modules/x/foo/foo.js
dir: path.resolve(input, '../../..'),
},
],
...options,
});
};

const defaultRollupPlugin = createRollupPlugin();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this is a bit weird. It's okay for now, but it seems like something that the rollup plugin should be able to handle for us, without creating three different versions of the plugin.


const customLwcRollupPlugin = {
...defaultRollupPlugin,
transform(src, id) {
let rollupPluginToUse;

// Override the LWC Rollup plugin to specify different options based on file name patterns.
// This allows us to alter the API version or other compiler props on a filename-only basis.
const apiVersion = id.match(/useApiVersion(\d+)/)?.[1];
const nativeOnly = /\.native-only\./.test(id);
if (apiVersion) {
rollupPluginToUse = createRollupPlugin({
apiVersion: parseInt(apiVersion, 10),
});
} else if (nativeOnly) {
rollupPluginToUse = createRollupPlugin({ disableSyntheticShadowSupport: true });
} else {
rollupPluginToUse = defaultRollupPlugin;
}
return rollupPluginToUse.transform.call(this, src, id);
},
};

const bundle = await rollup({
input,
cache,
plugins: [customLwcRollupPlugin],

// Rollup should not attempt to resolve the engine and the test utils, Karma takes care of injecting it
// globally in the page before running the tests.
external: ['lwc', 'wire-service', 'test-utils', '@test/loader'],

onwarn(warning, warn) {
// Ignore warnings from our own Rollup plugin
if (warning.plugin !== 'rollup-plugin-lwc-compiler') {
warn(warning);
}
},
});

cache = bundle.cache;

const { output } = await bundle.generate({
format: 'esm',
// TODO: Does web-test-runner use istanbul?

Check failure on line 90 in packages/@lwc/integration-not-karma/helpers/lwc.mjs

View workflow job for this annotation

GitHub Actions / run-unit-tests

Invalid TODO comment format, the git issue reference is probably missing
// Sourcemaps don't work with Istanbul coverage
sourcemap: process.env.COVERAGE ? false : 'inline',
});

const { code } = output[0];
return code;
};
Loading
Loading