mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
443bbd0cb8
Stryker runs the suite from a sandbox copy under `.tmp/stryker/`, so a test that asserts about the repository checkout itself — its files on disk, or its git history — reads a repository that does not exist. `test-file-size-ratchet.test.ts` is such a gate, and it fails there for two independent reasons: `disableTypeChecks` (Stryker's default) prepends `// @ts-nocheck` to every copied file, so all 26 pinned files read one line longer than they are; and the sandbox has no `origin/main`, so the gate's history-backed half cannot resolve its merge-base. Fixing either leaves the other. Its own `.tmp` skip entry cannot help: that is matched relative to `REPO_ROOT`, which inside the sandbox *is* the sandbox. Move it to `scripts/__tests__/` and include it explicitly in `unit-core`, the address the repo already uses for maintained gates that are not `src` tests. `KERNEL_TEST_FILE_RE` admits only root/package `src` tests, and its comment already names `scripts/__tests__` as unreachable by construction — so the gate leaves every mutation lane by virtue of where it lives, with no classifier to recognise it and nothing to keep in sync. This replaces the source-text scanner of the previous revision, which was the wrong boundary: it sniffed for a single-quoted `walk-files` import or the string `origin/main`, so a behavioral test could match and be silently excluded while an equivalent repo gate using double quotes, another walker, or another base ref would be missed. The scanner, its test, and its justifying comment are all gone. `REPO_ROOT` and the walked roots are unchanged — both addresses are two levels below the repo root, and `TEST_ROOTS` already included `scripts`, so the gate measures exactly what it did before. The one new assertion pins the invariant this now depends on: `isKernelTestFile` accepts root/package `src` tests and rejects `scripts/__tests__`. Widening that pattern would silently pull the gate back into every lane. Verified with `pnpm mutation:run --modules kernel-errors`: scope 804 -> 803 test files, dry run clean, lane `pass` at stage complete, score 74.8% (187 killed / 63 survived / 250) — unchanged. `pnpm mutation:test` 39/39, `pnpm check:layering` 181/181, `typecheck`, `lint`, `format` clean. `stryker.config.json` is untouched, so scores stay comparable. Unblocks #1964, whose two mutation checks fail on main's tip without its code.
92 lines
3.8 KiB
TypeScript
92 lines
3.8 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { test } from 'node:test';
|
|
import { fileURLToPath } from 'node:url';
|
|
import {
|
|
affectedModules,
|
|
ALL_MODULE_IDS,
|
|
isKernelTestFile,
|
|
KERNEL_MODULES,
|
|
moduleForFile,
|
|
mutateGlobs,
|
|
shardMatrix,
|
|
} from './modules.ts';
|
|
|
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
|
|
|
|
test('every enumerated kernel path exists', () => {
|
|
for (const module of KERNEL_MODULES) {
|
|
for (const owned of module.owns) {
|
|
assert.ok(
|
|
fs.existsSync(path.join(repoRoot, owned)),
|
|
`${module.id} owns a path that no longer exists: ${owned}`,
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('changed sources map onto the module that owns them', () => {
|
|
assert.equal(moduleForFile('packages/kernel/src/errors.ts'), 'kernel-errors');
|
|
assert.equal(moduleForFile('./src/daemon/ref-frame.ts'), 'daemon-ref-frame');
|
|
assert.equal(moduleForFile('packages/selectors/src/internal/parse.ts'), 'selectors');
|
|
// Selector tests live under the owned prefix; every other kernel's tests are
|
|
// attributed by ownership.ts, not by this path match.
|
|
assert.equal(moduleForFile('packages/selectors/src/internal/resolve.test.ts'), 'selectors');
|
|
assert.equal(moduleForFile('packages/kernel/src/rect.ts'), undefined);
|
|
assert.equal(moduleForFile('README.md'), undefined);
|
|
});
|
|
|
|
test('affected selection is deduplicated and registry-ordered', () => {
|
|
assert.deepEqual(
|
|
affectedModules([
|
|
'packages/selectors/src/internal/parse.ts',
|
|
'packages/selectors/src/internal/match.ts',
|
|
'packages/kernel/src/errors.ts',
|
|
'docs/agents/testing.md',
|
|
]),
|
|
['kernel-errors', 'selectors'],
|
|
);
|
|
assert.deepEqual(affectedModules(['docs/agents/testing.md']), []);
|
|
});
|
|
|
|
test('mutate globs default to every module and narrow on request', () => {
|
|
assert.deepEqual(mutateGlobs(), mutateGlobs(ALL_MODULE_IDS));
|
|
assert.deepEqual(mutateGlobs(['kernel-errors']), ['packages/kernel/src/errors.ts']);
|
|
});
|
|
|
|
// One job per module is only affordable while a module fits the lane's budget;
|
|
// the shard count is registry data so the workflows and the runner agree on it.
|
|
test('the shard matrix slices only the modules that declare shards', () => {
|
|
assert.deepEqual(shardMatrix(['kernel-errors']), [
|
|
{ name: 'kernel-errors', module: 'kernel-errors' },
|
|
]);
|
|
assert.deepEqual(shardMatrix(['selectors']), [
|
|
{ name: 'selectors-1', module: 'selectors', shard: '1/4' },
|
|
{ name: 'selectors-2', module: 'selectors', shard: '2/4' },
|
|
{ name: 'selectors-3', module: 'selectors', shard: '3/4' },
|
|
{ name: 'selectors-4', module: 'selectors', shard: '4/4' },
|
|
]);
|
|
assert.equal(shardMatrix().length, ALL_MODULE_IDS.length + 3);
|
|
// Every registry module reaches the matrix: an unsharded sweep is not a sweep.
|
|
for (const id of ALL_MODULE_IDS) {
|
|
assert.ok(
|
|
shardMatrix().some((spec) => spec.module === id),
|
|
`${id} has no shard`,
|
|
);
|
|
}
|
|
});
|
|
|
|
test('a kernel test is reachable only under root or package src', () => {
|
|
// Load-bearing for where `test-file-size-ratchet.test.ts` lives. It measures the
|
|
// repository's own files and git history, neither of which Stryker's sandbox copy can
|
|
// answer, so it sits in `scripts/__tests__/` (explicitly included by `unit-core`) and
|
|
// this predicate is what keeps it out of every mutation lane. Widening the pattern to
|
|
// scripts/ would silently pull it back in and fail every dry run.
|
|
assert.ok(isKernelTestFile('src/daemon/__tests__/ref-frame.test.ts'));
|
|
assert.ok(isKernelTestFile('packages/selectors/src/parse.test.ts'));
|
|
assert.ok(!isKernelTestFile('scripts/__tests__/test-file-size-ratchet.test.ts'));
|
|
assert.ok(!isKernelTestFile('test/integration/daemon.test.ts'));
|
|
assert.ok(!isKernelTestFile('src/daemon/ref-frame.ts'));
|
|
});
|