Skip to content

Commit 9987501

Browse files
committed
Migrate frontend tests from karma to vitest
1 parent 23dfe98 commit 9987501

File tree

11 files changed

+1274
-4119
lines changed

11 files changed

+1274
-4119
lines changed

.github/workflows/frontend.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
path: node_modules
1515
key: ${{ runner.os }}-node_modules-${{ hashFiles('yarn.lock') }}
1616
- name: Install
17-
run: yarn install --frozen-lockfile
17+
run: yarn install --frozen-lockfile && yarn playwright install chromium
1818
- name: Lint
1919
run: make frontend-lint
2020
- name: Test

frontend.mk

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ build/manifest.json: node_modules/.uptodate
2121
node_modules/.uptodate: package.json yarn.lock
2222
@echo installing javascript dependencies
2323
@yarn install
24+
@yarn playwright install chromium
2425
@touch $@
2526

2627
# Make some of the targets from Makefile depend on manifest.json.

gulpfile.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ gulp.task(
5757
gulp.parallel('build-css', () =>
5858
runTests({
5959
bootstrapFile: 'lms/static/scripts/bootstrap.js',
60-
karmaConfig: 'lms/static/scripts/karma.config.cjs',
60+
vitestConfig: 'vitest.config.js',
6161
rollupConfig: 'rollup-tests.config.js',
6262
testsPattern: 'lms/static/scripts/**/*-test.js',
6363
}),

lms/static/scripts/bootstrap.js

+7-25
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,20 @@
11
import { unmountAll } from '@hypothesis/frontend-testing';
2+
import { assert } from 'chai';
23
import { configure } from 'enzyme';
34
import { Adapter } from 'enzyme-adapter-preact-pure';
45
import 'preact/debug';
6+
import sinon from 'sinon';
57

68
// Expose sinon assertions.
79
sinon.assert.expose(assert, { prefix: null });
810

11+
// Expose these globally
12+
globalThis.assert = assert;
13+
globalThis.sinon = sinon;
14+
globalThis.context ??= globalThis.describe;
15+
916
// Configure Enzyme for UI tests.
1017
configure({ adapter: new Adapter() });
1118
afterEach(() => {
1219
unmountAll();
1320
});
14-
15-
// Ensure that uncaught exceptions between tests result in the tests failing.
16-
// This works around an issue with mocha / karma-mocha, see
17-
// https://github.com/hypothesis/client/issues/2249.
18-
let pendingError = null;
19-
let pendingErrorNotice = null;
20-
21-
/* istanbul ignore next */
22-
window.addEventListener('error', event => {
23-
pendingError = event.error;
24-
pendingErrorNotice = 'An uncaught exception was thrown between tests';
25-
});
26-
/* istanbul ignore next */
27-
window.addEventListener('unhandledrejection', event => {
28-
pendingError = event.reason;
29-
pendingErrorNotice = 'An uncaught promise rejection occurred between tests';
30-
});
31-
32-
afterEach(() => {
33-
/* istanbul ignore if */
34-
if (pendingError) {
35-
console.error(pendingErrorNotice);
36-
throw pendingError;
37-
}
38-
});

lms/static/scripts/karma.config.cjs

-55
This file was deleted.

lms/static/scripts/postmessage_json_rpc/test/server-test.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ describe('Server', () => {
5454
let listener;
5555
let receiveMessage;
5656

57-
beforeEach('set up the test server', () => {
57+
beforeEach(() => {
5858
// The test server normally runs on http://localhost:9876, but may be
5959
// on a higher port if multiple instances are running.
6060
// Use window.location.origin to be safe.
@@ -69,11 +69,11 @@ describe('Server', () => {
6969
server.register('registeredMethodErrorName', registeredMethodError);
7070
});
7171

72-
afterEach('tear down the test server', () => {
72+
afterEach(() => {
7373
server.off();
7474
});
7575

76-
beforeEach('listen for JSON-RPC responses', () => {
76+
beforeEach(() => {
7777
receiveMessage = sinon.stub();
7878

7979
listener = event => {
@@ -91,7 +91,7 @@ describe('Server', () => {
9191
window.addEventListener('message', listener);
9292
});
9393

94-
afterEach('tear down the JSON-RPC response listener', () => {
94+
afterEach(() => {
9595
window.removeEventListener('message', listener);
9696
});
9797

lms/static/scripts/tsconfig.json

-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
// Tests and test infrastructure
2020
"**/test/*.js",
2121
"bootstrap.js",
22-
"karma.config.js",
2322
"test-util/*.js"
2423
]
2524
}

package.json

+7-12
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"@babel/preset-env": "^7.26.9",
2626
"@babel/preset-react": "^7.26.3",
2727
"@babel/preset-typescript": "^7.27.0",
28-
"@hypothesis/frontend-build": "^3.0.0",
28+
"@hypothesis/frontend-build": "^3.2.1",
2929
"@hypothesis/frontend-shared": "^9.3.0",
3030
"@rollup/plugin-babel": "^6.0.4",
3131
"@rollup/plugin-commonjs": "^28.0.3",
@@ -38,7 +38,6 @@
3838
"classnames": "^2.5.1",
3939
"focus-visible": "^5.2.1",
4040
"gulp": "^5.0.0",
41-
"karma-chrome-launcher": "^3.2.0",
4241
"normalize.css": "^8.0.1",
4342
"postcss": "^8.4.47",
4443
"preact": "^10.25.1",
@@ -49,10 +48,12 @@
4948
"wouter-preact": "^3.5.1"
5049
},
5150
"devDependencies": {
52-
"@hypothesis/frontend-testing": "^1.5.0",
51+
"@hypothesis/frontend-testing": "^1.6.0",
5352
"@types/gapi": "^0.0.47",
5453
"@types/google.accounts": "^0.0.15",
5554
"@types/google.picker": "^0.0.50",
55+
"@vitest/browser": "^3.1.2",
56+
"@vitest/coverage-istanbul": "^3.1.2",
5657
"axe-core": "^4.10.3",
5758
"babel-plugin-istanbul": "^7.0.0",
5859
"babel-plugin-mockable-imports": "^2.0.1",
@@ -67,19 +68,13 @@
6768
"eslint-plugin-react": "^7.37.4",
6869
"eslint-plugin-react-hooks": "^5.2.0",
6970
"globals": "^15.11.0",
70-
"karma": "^6.4.4",
71-
"karma-chai": "^0.1.0",
72-
"karma-coverage-istanbul-reporter": "^3.0.3",
73-
"karma-mocha": "^2.0.1",
74-
"karma-mocha-reporter": "^2.0.4",
75-
"karma-sinon": "^1.0.5",
76-
"karma-source-map-support": "^1.4.0",
77-
"mocha": "^10.2.0",
7871
"navigation-api-types": "^0.5.1",
72+
"playwright": "^1.52.0",
7973
"prettier": "3.4.2",
8074
"sinon": "^19.0.2",
8175
"typescript": "^5.2.2",
82-
"typescript-eslint": "^8.29.0"
76+
"typescript-eslint": "^8.29.0",
77+
"vitest": "^3.1.2"
8378
},
8479
"prettier": {
8580
"arrowParens": "avoid",

rollup-tests.config.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,20 @@ export default {
7575
[
7676
'babel-plugin-istanbul',
7777
{
78-
exclude: ['**/test/**/*.js', '**/test-util/**'],
78+
// This needs to match the value set in coverage.exclude in vitest.config.js
79+
exclude: [
80+
'**/node_modules/**',
81+
'**/test/**/*.js',
82+
'**/test-util/**',
83+
],
84+
85+
// These two configuration options needed to match the values that
86+
// vitest sets internally, so that they pick the coverage
87+
// instrumentation generated by babel-plugin-istanbul instead of
88+
// trying to generate their own.
89+
// See https://github.com/vitest-dev/vitest/discussions/7841#discussioncomment-12855608
90+
coverageGlobalScope: 'globalThis',
91+
coverageVariable: '__VITEST_COVERAGE__',
7992
},
8093
],
8194
],

vitest.config.js

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { SummaryReporter } from '@hypothesis/frontend-testing/vitest';
2+
import { defineConfig } from 'vitest/config';
3+
4+
export default defineConfig({
5+
test: {
6+
globals: true,
7+
reporters: [new SummaryReporter()],
8+
9+
browser: {
10+
provider: 'playwright',
11+
enabled: true,
12+
headless: true,
13+
screenshotFailures: false,
14+
instances: [{ browser: 'chromium' }],
15+
viewport: { width: 1024, height: 768 },
16+
},
17+
18+
// CSS bundles, relied upon by accessibility tests (eg. for color-contrast
19+
// checks).
20+
setupFiles: [
21+
// TODO List dynamically
22+
'./build/styles/canvas_pages.css',
23+
'./build/styles/frontend_apps.css',
24+
'./build/styles/lms.css',
25+
'./build/styles/moodle_pages.css',
26+
'./build/styles/ui-playground.css',
27+
],
28+
include: [
29+
// Test bundle
30+
'./build/scripts/tests.bundle.js',
31+
],
32+
33+
coverage: {
34+
enabled: true,
35+
provider: 'istanbul',
36+
reportsDirectory: './coverage',
37+
reporter: ['json', 'html'],
38+
include: ['lms/static/scripts/frontend_apps/**/*.{ts,tsx}', '!**/*.d.ts'],
39+
exclude: ['**/node_modules/**', '**/test/**/*.js', '**/test-util/**'],
40+
},
41+
},
42+
});

0 commit comments

Comments
 (0)