From 23f95a2853bcacc080be99586ae3251d1ce668f0 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Wed, 8 Jul 2026 14:40:39 +0200 Subject: [PATCH 1/5] fx --- Testing.md | 20 +++++++++++++++++++- package.json | 6 ++++-- resources/shared/helpers.mjs | 6 ++++++ tests/unittests/benchmark-runner.mjs | 7 ++++--- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/Testing.md b/Testing.md index 684260b1c..a4ab7afc0 100644 --- a/Testing.md +++ b/Testing.md @@ -8,7 +8,25 @@ Tests are located in the `/tests` folder. ## Local Testing -To run this locally you'll need the browsers installed along with the corresponding driver: +Speedometer supports running unit tests directly in Node.js (without browser DOM dependencies) as well as running browser tests via WebDriver. + +### Node.js Unit Testing + +You can run the unit tests directly in Node.js using: + +```bash +npm run test +``` + +Or directly via the explicit script: + +```bash +npm run test:node +``` + +### In-Browser Testing + +To run the in-browser tests locally, you'll need the browsers installed along with the corresponding driver: - [chromedriver](https://chromedriver.chromium.org/getting-started) - [geckodriver](https://github.com/mozilla/geckodriver/releases) diff --git a/package.json b/package.json index f0884b94b..94b1f7a39 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "license": "SEE LICENSE IN LICENSE", "scripts": { "dev": "node tests/server.mjs", - "lint:check": "eslint **/*.{js,mjs,jsx,ts,tsx}", + "lint:check": "eslint \"**/*.{js,mjs,jsx,ts,tsx}\"", "lint:fix": "eslint \"**/*.{js,mjs,jsx,ts,tsx}\" --fix", "pretty:check": "prettier --check ./", "pretty:fix": "prettier --write ./", @@ -29,7 +29,9 @@ "test-e2e:chrome": "node tests/run-end2end.mjs --browser chrome", "test-e2e:firefox": "node tests/run-end2end.mjs --browser firefox", "test-e2e:safari": "node tests/run-end2end.mjs --browser safari", - "test-e2e:edge": "node tests/run-end2end.mjs --browser edge" + "test-e2e:edge": "node tests/run-end2end.mjs --browser edge", + "test": "npm run test:node", + "test:node": "mocha --require ./tests/setup-node.mjs \"tests/unittests/*.mjs\"" }, "devDependencies": { "@babel/core": "^7.21.3", diff --git a/resources/shared/helpers.mjs b/resources/shared/helpers.mjs index b6b004542..9c8df3c5b 100644 --- a/resources/shared/helpers.mjs +++ b/resources/shared/helpers.mjs @@ -53,3 +53,9 @@ export function forceLayout(body, layoutMode = "getBoundingRectAndElementFromPoi throw Error(`Invalid layoutMode: ${layoutMode}`); } } + +export function skipInShell(context) { + if (typeof window === "undefined" || typeof document === "undefined") + // Skip in non-browser environments + context.skip(); +} diff --git a/tests/unittests/benchmark-runner.mjs b/tests/unittests/benchmark-runner.mjs index 928ab8452..990509728 100644 --- a/tests/unittests/benchmark-runner.mjs +++ b/tests/unittests/benchmark-runner.mjs @@ -2,6 +2,7 @@ import { BenchmarkRunner } from "../../resources/benchmark-runner.mjs"; import { SuiteRunner } from "../../resources/suite-runner.mjs"; import { StepRunner } from "../../resources/shared/step-runner.mjs"; import { defaultParams } from "../../resources/shared/params.mjs"; +import { skipInShell } from "../../resources/shared/helpers.mjs"; function TEST_FIXTURE(name) { return { @@ -35,7 +36,8 @@ describe("BenchmarkRunner", () => { const { spy, stub, assert } = sinon; let runner; - before(() => { + before(function () { + skipInShell(this); runner = new BenchmarkRunner(SUITES_FIXTURE, CLIENT_FIXTURE); }); @@ -109,8 +111,7 @@ describe("BenchmarkRunner", () => { _loadFrameStub = stub(SuiteRunner.prototype, "_loadFrame").callsFake(async () => null); _appendFrameStub = stub(runner, "_appendFrame").callsFake(async () => null); _removeFrameStub = stub(runner, "_removeFrame").callsFake(() => null); - for (const suite of runner._suites) - spy(suite, "prepare"); + runner._suites.forEach((suite) => spy(suite, "prepare")); expect(runner._suites).not.to.have.length(0); await runner.runAllSuites(); }); From c0286c456002faa6eb62e6c3e552a1a609fb37fb Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Wed, 8 Jul 2026 14:45:45 +0200 Subject: [PATCH 2/5] update-instructions --- Testing.md | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Testing.md b/Testing.md index a4ab7afc0..7429a6462 100644 --- a/Testing.md +++ b/Testing.md @@ -8,18 +8,9 @@ Tests are located in the `/tests` folder. ## Local Testing -Speedometer supports running unit tests directly in Node.js (without browser DOM dependencies) as well as running browser tests via WebDriver. - -### Node.js Unit Testing +### Local Node.js Unit Testing You can run the unit tests directly in Node.js using: - -```bash -npm run test -``` - -Or directly via the explicit script: - ```bash npm run test:node ``` From f7ae39ea7294343fb22ae5b65882277893c5d11b Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Wed, 8 Jul 2026 14:46:23 +0200 Subject: [PATCH 3/5] fx --- tests/unittests/benchmark-runner.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unittests/benchmark-runner.mjs b/tests/unittests/benchmark-runner.mjs index 990509728..b512c799d 100644 --- a/tests/unittests/benchmark-runner.mjs +++ b/tests/unittests/benchmark-runner.mjs @@ -111,7 +111,8 @@ describe("BenchmarkRunner", () => { _loadFrameStub = stub(SuiteRunner.prototype, "_loadFrame").callsFake(async () => null); _appendFrameStub = stub(runner, "_appendFrame").callsFake(async () => null); _removeFrameStub = stub(runner, "_removeFrame").callsFake(() => null); - runner._suites.forEach((suite) => spy(suite, "prepare")); + for (const suite of runner._suites) + spy(suite, "prepare"); expect(runner._suites).not.to.have.length(0); await runner.runAllSuites(); }); From 2626f3b048fc751ee1d5cf4b2a13d2ba936cfaa6 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Wed, 8 Jul 2026 14:46:33 +0200 Subject: [PATCH 4/5] cleanup --- Testing.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Testing.md b/Testing.md index 7429a6462..20685a7b1 100644 --- a/Testing.md +++ b/Testing.md @@ -11,6 +11,7 @@ Tests are located in the `/tests` folder. ### Local Node.js Unit Testing You can run the unit tests directly in Node.js using: + ```bash npm run test:node ``` From d71fcc40ede5cdf803bbb101a03b040be33e3e1e Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Wed, 8 Jul 2026 14:50:09 +0200 Subject: [PATCH 5/5] enable-node-tests --- .github/workflows/test.yml | 19 +++++++++++++++++++ tests/setup-node.mjs | 11 +++++++++++ 2 files changed, 30 insertions(+) create mode 100644 tests/setup-node.mjs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4a2cc5882..1ba59d5b7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -41,6 +41,25 @@ jobs: exit 1 fi + test-node: + name: Node Unit Tests + runs-on: ubuntu-latest + steps: + - name: Checkout Branch + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version-file: "package.json" + cache: "npm" + + - name: Install Node Packages + run: npm ci + + - name: Run Node Unit Tests + run: npm test + build: name: Build runs-on: macos-latest diff --git a/tests/setup-node.mjs b/tests/setup-node.mjs new file mode 100644 index 000000000..35dae8cbf --- /dev/null +++ b/tests/setup-node.mjs @@ -0,0 +1,11 @@ +import expect from "expect.js"; +import sinon from "sinon"; + +globalThis.expect = expect; +globalThis.sinon = sinon; + +export const mochaHooks = { + afterEach() { + sinon.restore(); + }, +};