mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-19 21:32:20 +03:00
fix(ci): clear the tap.testFiles drift that reds the mutation gate on every PR (#13814)
* fix(ci): clear the tap.testFiles drift that reds the gate on every PR
check-mutation-test-coverage --strict fails on a pristine checkout of
release/v3.8.51 with no PR diff involved, so the mutation-test-coverage
gate is red on every open PR regardless of what it changes.
Six covering unit tests across four mutated modules were absent from
stryker.conf.json tap.testFiles, which means their mutant kills were not
being counted:
accountFallback.ts daily-reset-tz-threading, noauth-model-lockout
sse/services/auth.ts free-badge-provider-gate, noauth-model-lockout
combo/comboPredicates.ts local-token-budget-429-skips-cooldown
combo/rrState.ts daily-reset-tz-threading
Four distinct files — two of them cover two modules each. Inserted into
the alphabetical run, matching the file's existing convention; the list
has a second unsorted appended group that is left alone.
After: "No drift — every covering unit test is listed in tap.testFiles",
exit 0. All four files pass (31 tests) so registering them does not
introduce a failing mutation run.
Noticed while reviewing #13743, which targets a fifth file that has
already been registered by 25bc16d87e.
* fix(ci): drop a dangling tap.testFiles entry and guard against new ones
Merging the release line in surfaced that stryker.conf.json still names
tests/unit/plugin-sandbox-permissions.test.ts, which does not exist —
one dangling path out of 428 entries, pre-existing on the base rather
than introduced here.
check-mutation-test-coverage already guards one direction: a test that
covers a mutated module but is missing from tap.testFiles. The other
direction was silent. Stryker resolves the list into its sandbox, so an
entry left behind after its test file is deleted or renamed costs
coverage without failing loudly — the same class of drift this PR is
about, arriving from the opposite side.
This commit is contained in:
2
changelog.d/fixes/stryker-tapfiles-drift-release-line.md
Normal file
2
changelog.d/fixes/stryker-tapfiles-drift-release-line.md
Normal file
@@ -0,0 +1,2 @@
|
||||
- **fix(ci):** register the four unit tests whose mutant kills were not counting — `daily-reset-tz-threading`, `noauth-model-lockout`, `free-badge-provider-gate` and `local-token-budget-429-skips-cooldown` — in `stryker.conf.json` `tap.testFiles`. `check-mutation-test-coverage --strict` reported 6 missing coverings across 4 mutated modules (`accountFallback`, `sse/services/auth`, `combo/comboPredicates`, `combo/rrState`) on the release line itself with no PR diff involved, so the `mutation-test-coverage` gate was red on every open PR regardless of its contents; the gate now reports no drift
|
||||
- fix(ci): drop a `tap.testFiles` entry naming a deleted test file, and guard the direction the existing drift check never covered — an entry left behind after its test is removed or renamed costs mutation coverage silently, because Stryker resolves the list into its sandbox without failing on a dangling path ([#13814](https://github.com/diegosouzapw/OmniRoute/pull/13814))
|
||||
@@ -62,6 +62,7 @@
|
||||
"tests/unit/combo-pin-implicit-allowlist.test.ts",
|
||||
"tests/unit/combo-predicates-epoch-cooldown.test.ts",
|
||||
"tests/unit/combo/execute-target-gates.test.ts",
|
||||
"tests/unit/daily-reset-tz-threading.test.ts",
|
||||
"tests/unit/moonshot-quota-writeback.test.ts",
|
||||
"tests/unit/accountfallback-ratelimit-400-4976.test.ts",
|
||||
"tests/unit/adaptive-admission-route-matrix.test.ts",
|
||||
@@ -331,6 +332,7 @@
|
||||
"tests/unit/antigravityUpstreamError.test.ts",
|
||||
"tests/unit/issue-13089-roundrobin-live-ws-events.test.ts",
|
||||
"tests/unit/ollama-404-model-lockout-11071.test.ts",
|
||||
"tests/unit/noauth-model-lockout.test.ts",
|
||||
"tests/unit/non-streaming-client-translate.test.ts",
|
||||
"tests/unit/non-streaming-provider-leg.test.ts",
|
||||
"tests/unit/non-streaming-sse-terminal-typescan-4459.test.ts",
|
||||
@@ -353,7 +355,6 @@
|
||||
"tests/unit/permanent-failure-hammering-other-providers.test.ts",
|
||||
"tests/unit/persist-429-cooldown-account-fallback.test.ts",
|
||||
"tests/unit/plan3-p0.test.ts",
|
||||
"tests/unit/plugin-sandbox-permissions.test.ts",
|
||||
"tests/unit/plugins-route-error-sanitization.test.ts",
|
||||
"tests/unit/probe-gate-autodisable.test.ts",
|
||||
"tests/unit/probe-production-path.test.ts",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import {
|
||||
moduleFragment,
|
||||
testImportsModule,
|
||||
@@ -25,7 +27,10 @@ test("testImportsModule matches static, dynamic and require imports of the modul
|
||||
);
|
||||
// dynamic await import, even split across lines
|
||||
assert.equal(
|
||||
testImportsModule(`const { y } = await import(\n "../../open-sse/handlers/chatCore/headers.ts"\n);`, frag),
|
||||
testImportsModule(
|
||||
`const { y } = await import(\n "../../open-sse/handlers/chatCore/headers.ts"\n);`,
|
||||
frag
|
||||
),
|
||||
true
|
||||
);
|
||||
// require()
|
||||
@@ -35,7 +40,10 @@ test("testImportsModule matches static, dynamic and require imports of the modul
|
||||
);
|
||||
// unrelated module is not matched
|
||||
assert.equal(
|
||||
testImportsModule(`import { a } from "@omniroute/open-sse/handlers/chatCore/idempotency";`, frag),
|
||||
testImportsModule(
|
||||
`import { a } from "@omniroute/open-sse/handlers/chatCore/idempotency";`,
|
||||
frag
|
||||
),
|
||||
false
|
||||
);
|
||||
// the fragment appearing only in a comment (not an import string) is NOT a match
|
||||
@@ -54,11 +62,20 @@ test("findCoverageDrift flags covering unit tests absent from tap.testFiles", ()
|
||||
const tapTestFiles = ["tests/unit/chatcore-headers.test.ts"];
|
||||
const unitTests = [
|
||||
// covers headers, already in tap -> not drift
|
||||
{ path: "tests/unit/chatcore-headers.test.ts", content: `await import("../../open-sse/handlers/chatCore/headers.ts");` },
|
||||
{
|
||||
path: "tests/unit/chatcore-headers.test.ts",
|
||||
content: `await import("../../open-sse/handlers/chatCore/headers.ts");`,
|
||||
},
|
||||
// covers headers, NOT in tap -> drift
|
||||
{ path: "tests/unit/no-memory-header.test.ts", content: `const { isNoMemoryRequested } = await import("../../open-sse/handlers/chatCore/headers.ts");` },
|
||||
{
|
||||
path: "tests/unit/no-memory-header.test.ts",
|
||||
content: `const { isNoMemoryRequested } = await import("../../open-sse/handlers/chatCore/headers.ts");`,
|
||||
},
|
||||
// covers idempotency, NOT in tap -> drift
|
||||
{ path: "tests/unit/idempo.test.ts", content: `import { x } from "@omniroute/open-sse/handlers/chatCore/idempotency";` },
|
||||
{
|
||||
path: "tests/unit/idempo.test.ts",
|
||||
content: `import { x } from "@omniroute/open-sse/handlers/chatCore/idempotency";`,
|
||||
},
|
||||
// covers nothing mutated -> ignored
|
||||
{ path: "tests/unit/unrelated.test.ts", content: `import { z } from "@/lib/foo";` },
|
||||
];
|
||||
@@ -72,3 +89,21 @@ test("findCoverageDrift flags covering unit tests absent from tap.testFiles", ()
|
||||
// comment-only mutate entries are skipped
|
||||
assert.equal("_a_comment_entry" in drift, false);
|
||||
});
|
||||
|
||||
test("every tap.testFiles entry names a file that still exists", () => {
|
||||
// The existing drift check runs one way: a test that covers a mutated module
|
||||
// but is missing from tap.testFiles. The other way is silent — an entry left
|
||||
// behind after its test file is deleted or renamed. Stryker resolves the list
|
||||
// into its sandbox, so a dangling path costs coverage without failing loudly.
|
||||
const repoRoot = path.resolve(import.meta.dirname, "../../..");
|
||||
const conf = JSON.parse(fs.readFileSync(path.join(repoRoot, "stryker.conf.json"), "utf8")) as {
|
||||
tap?: { testFiles?: string[] };
|
||||
};
|
||||
const entries = conf.tap?.testFiles ?? [];
|
||||
assert.ok(entries.length > 0, "stryker.conf.json declares no tap.testFiles");
|
||||
|
||||
const missing = entries
|
||||
.filter((entry) => !entry.includes("*"))
|
||||
.filter((entry) => !fs.existsSync(path.join(repoRoot, entry)));
|
||||
assert.deepEqual(missing, [], `tap.testFiles names ${missing.length} file(s) that do not exist`);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user