Skip to content

Commit d718ac3

Browse files
committed
test: prove desktop discovery preserves imported and unmeasured cases
1 parent 7cb16af commit d718ac3

2 files changed

Lines changed: 66 additions & 1 deletion

File tree

‎.github/CI.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,4 @@ The separate `desktop-e2e` workflow retains its desktop-specific path filters. I
4747

4848
The initial weights are median test durations in seconds from runs [39734295953](https://github.com/simstudioai/sim/actions/runs/39734295953), [39833640524](https://github.com/simstudioai/sim/actions/runs/39833640524), and [39836596108](https://github.com/simstudioai/sim/actions/runs/39836596108). Refresh them from complete `desktop-smoke-reports-*` artifacts when the workload changes: sum `tests[].results[].duration` by `spec.file` in each run, take the median across runs, and divide milliseconds by 1,000. The weights steer scheduling only; Playwright discovery owns coverage. Before adopting new weights, compare repeated paired runs and the complete case/status multiset, including skipped cases and retries.
4949

50-
Each shard uploads its coverage/timing report, the complete discovery report, and its deterministic shard plan. `bun run test:scripts scripts/duration-shards.test.ts` checks partition coverage, unknown files, deterministic ordering, and balancing without launching Electron.
50+
Each shard uploads its coverage/timing report, the complete discovery report, and its deterministic shard plan. `bun run test:scripts scripts/duration-shards.test.ts scripts/desktop-e2e.test.ts` checks partition coverage, unknown files, deterministic ordering, and balancing. The CLI regression executes tiny browser-free Playwright fixtures to prove that imported test factories and paths containing regex characters are selected correctly; it launches no Electron or browser.

‎scripts/desktop-e2e.test.ts‎

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { spawnSync } from 'node:child_process'
2+
import { mkdirSync, mkdtempSync, readFileSync, rmSync, symlinkSync, writeFileSync } from 'node:fs'
3+
import { tmpdir } from 'node:os'
4+
import { join, resolve } from 'node:path'
5+
import { expect, it } from 'vitest'
6+
7+
it('executes imported test factories and unmeasured files exactly once across desktop shards', () => {
8+
const root = resolve(import.meta.dirname, '..')
9+
const fixture = mkdtempSync(join(tmpdir(), 'desktop-shard-'))
10+
try {
11+
symlinkSync(join(root, 'node_modules'), join(fixture, 'node_modules'), 'dir')
12+
writeFileSync(join(fixture, 'package.json'), '{"type":"module"}')
13+
writeFileSync(
14+
join(fixture, 'playwright.config.ts'),
15+
"export default { testDir: './tests', workers: 1, retries: 0 }"
16+
)
17+
mkdirSync(join(fixture, 'tests/nested'), { recursive: true })
18+
mkdirSync(join(fixture, 'tests/support'), { recursive: true })
19+
writeFileSync(
20+
join(fixture, 'tests/support/factory.ts'),
21+
"import { test } from '@playwright/test'; export function register() { test('factory', () => {}); }"
22+
)
23+
writeFileSync(
24+
join(fixture, 'tests/nested/a[1].spec.ts'),
25+
"import { register } from '../support/factory'; register();"
26+
)
27+
for (const file of ['brand-new.test.ts', 'ordinary.spec.ts']) {
28+
writeFileSync(
29+
join(fixture, 'tests', file),
30+
`import { test } from '@playwright/test'; test('${file}', () => {});`
31+
)
32+
}
33+
const cases: { title: string; status: string }[] = []
34+
for (const index of [1, 2, 3]) {
35+
const reportPath = join(fixture, `${index}.json`)
36+
const result = spawnSync('bun', ['run', join(root, 'scripts/desktop-e2e.ts'), `${index}/3`], {
37+
cwd: fixture,
38+
env: { ...process.env, PLAYWRIGHT_JSON_OUTPUT_FILE: reportPath },
39+
encoding: 'utf8',
40+
timeout: 10_000,
41+
})
42+
expect(result.status, result.stdout + result.stderr).toBe(0)
43+
const report = JSON.parse(readFileSync(reportPath, 'utf8')) as {
44+
suites: { specs: { title: string; tests: { results: { status: string }[] }[] }[] }[]
45+
}
46+
for (const suite of report.suites) {
47+
for (const spec of suite.specs) {
48+
for (const test of spec.tests) {
49+
for (const run of test.results) cases.push({ title: spec.title, status: run.status })
50+
}
51+
}
52+
}
53+
}
54+
expect(cases).toEqual(
55+
expect.arrayContaining([
56+
{ title: 'factory', status: 'passed' },
57+
{ title: 'brand-new.test.ts', status: 'passed' },
58+
{ title: 'ordinary.spec.ts', status: 'passed' },
59+
])
60+
)
61+
expect(cases).toHaveLength(3)
62+
} finally {
63+
rmSync(fixture, { recursive: true, force: true })
64+
}
65+
})

0 commit comments

Comments
 (0)