Skip to content

Commit a565ffa

Browse files
committed
test: generalize the Playwright guard into CI dependency compatibility
Also assert the exact vitest/vite couplings CI depends on: @vitest/browser-playwright and @vitest/coverage-v8 peer on the vitest version that vite-plus bundles, and vite must resolve to the vite-plus-core build that vite-plus ships.
1 parent 5dcbfcf commit a565ffa

4 files changed

Lines changed: 83 additions & 48 deletions

File tree

‎.github/workflows/test.yml‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ jobs:
4949
# font stack, which a bare runner does not provide.
5050
#
5151
# This tag must match the `playwright` devDependency, which ships the
52-
# matching browser build. Renovate groups the two so they always move
53-
# together; `scripts/visual.sh` reads the version straight from package.json.
52+
# matching browser build. `scripts/visual.sh` derives the image from it for
53+
# local runs, and `src/main/ciDependencyCompatibility.test.ts` asserts the
54+
# two stay in sync so the version cannot drift unnoticed.
5455
container: mcr.microsoft.com/playwright:v1.63.0-noble@sha256:eff16c30e6f3f4af0a03fa4b706120d5e9b0891c344a27d64559aff5900a4a27
5556

5657
steps:

‎renovate.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"allowedVersions": "<12"
1414
},
1515
{
16-
"description": "Leave the visual-regression Playwright container image to a deliberate bump rather than Renovate. It must match the playwright devDependency exactly (both ship the same browser build), but the npm package and the MCR image are separate datasources and MCR exposes no release timestamp for minimumReleaseAge to compare, so grouping them still drifts the versions and opens image-only PRs that strand the screenshot baselines. package.json is the source of truth; src/main/visualRegressionImage.test.ts enforces the match and scripts/visual.sh derives the same image locally. The digest stays pinned for zizmor.",
16+
"description": "Leave the visual-regression Playwright container image to a deliberate bump rather than Renovate. It must match the playwright devDependency exactly (both ship the same browser build), but the npm package and the MCR image are separate datasources and MCR exposes no release timestamp for minimumReleaseAge to compare, so grouping them still drifts the versions and opens image-only PRs that strand the screenshot baselines. package.json is the source of truth; src/main/ciDependencyCompatibility.test.ts enforces the match and scripts/visual.sh derives the same image locally. The digest stays pinned for zizmor.",
1717
"matchDatasources": ["docker"],
1818
"matchPackageNames": ["mcr.microsoft.com/playwright"],
1919
"enabled": false
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { readFileSync } from 'node:fs';
2+
3+
/**
4+
* Guards version couplings that CI depends on but that no single manifest
5+
* expresses. Renovate (or a manual edit) can move one half of a pair and leave
6+
* the other behind, which otherwise only surfaces as a confusing failure deep in
7+
* the test or visual-regression run. Asserting the couplings here — against the
8+
* versions actually installed — turns that into a fast, explicit failure.
9+
*
10+
* The vitest couplings are exact peer dependencies: `@vitest/browser-playwright`
11+
* and `@vitest/coverage-v8` peer on the same `vitest` version that `vite-plus`
12+
* bundles, and `vite` must resolve to the `@voidzero-dev/vite-plus-core` build
13+
* that `vite-plus` ships.
14+
*/
15+
const repoRoot = new URL('../../', import.meta.url);
16+
17+
function readJson<T>(path: string): T {
18+
return JSON.parse(readFileSync(new URL(path, repoRoot), 'utf8')) as T;
19+
}
20+
21+
type PackageJson = {
22+
name?: string;
23+
version: string;
24+
dependencies?: Record<string, string>;
25+
};
26+
27+
const workflow = readFileSync(new URL('.github/workflows/test.yml', repoRoot), 'utf8');
28+
29+
const playwright = readJson<PackageJson>('node_modules/playwright/package.json');
30+
const vitest = readJson<PackageJson>('node_modules/vitest/package.json');
31+
const browserPlaywright = readJson<PackageJson>(
32+
'node_modules/@vitest/browser-playwright/package.json',
33+
);
34+
const coverageV8 = readJson<PackageJson>('node_modules/@vitest/coverage-v8/package.json');
35+
const vitePlus = readJson<PackageJson>('node_modules/vite-plus/package.json');
36+
const vite = readJson<PackageJson>('node_modules/vite/package.json');
37+
38+
const PINNED_PLAYWRIGHT_IMAGE =
39+
/container:\s+mcr\.microsoft\.com\/playwright:v([^@\s]+)-noble@(sha256:[0-9a-f]{64})/;
40+
41+
describe('CI dependency compatibility', () => {
42+
describe('playwright', () => {
43+
it('pins the visual-regression image to the installed playwright version', () => {
44+
const pinned = workflow.match(PINNED_PLAYWRIGHT_IMAGE);
45+
46+
expect(
47+
pinned,
48+
'Expected a digest-pinned mcr.microsoft.com/playwright container in the visual-regression job of .github/workflows/test.yml.',
49+
).not.toBeNull();
50+
51+
expect(
52+
pinned?.[1],
53+
[
54+
`The visual-regression container must run mcr.microsoft.com/playwright:v${playwright.version}-noble to match the installed playwright (driven by the package.json devDependency).`,
55+
'Update the tag and refresh the pinned digest with:',
56+
` docker buildx imagetools inspect mcr.microsoft.com/playwright:v${playwright.version}-noble --format '{{.Manifest.Digest}}'`,
57+
].join('\n'),
58+
).toBe(playwright.version);
59+
});
60+
});
61+
62+
describe('vitest family', () => {
63+
it('installs the browser provider and coverage reporter at the vitest version', () => {
64+
expect(browserPlaywright.version).toBe(vitest.version);
65+
expect(coverageV8.version).toBe(vitest.version);
66+
});
67+
68+
it('installs vitest at the version bundled by vite-plus', () => {
69+
expect(vitest.version).toBe(vitePlus.dependencies?.vitest);
70+
});
71+
});
72+
73+
describe('vite family', () => {
74+
it('resolves vite to the vite-plus-core build that vite-plus ships', () => {
75+
expect(vite.name).toBe('@voidzero-dev/vite-plus-core');
76+
expect(vitePlus.dependencies?.vite).toBe(`npm:${vite.name}@${vite.version}`);
77+
});
78+
});
79+
});

‎src/main/visualRegressionImage.test.ts‎

Lines changed: 0 additions & 45 deletions
This file was deleted.

0 commit comments

Comments
 (0)