mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 09:36:08 +00:00
Second pass over the suite, driven by the inventory in the gaps document. Nine agents wrote suites in parallel against private databases, then a tenth read all of it adversarially and five of its findings were fixed. unit + component 2076 -> 2079 (+888 over the round) api 647 -> 1015 e2e 18 -> 29 What was closed: - lib/route-access.ts, the page-level authorization layer, went from zero tests to 48. Every API route was guarded and none of the pages were. - The five media proxy routes now have a real 2xx beside every 403. The blocker was the positive control, solved by stubbing r2Client.send() and leaving lib/r2-media-proxy.ts itself real. - Every remaining server-side lib module: invitations, email verification, the upload tokens, the logger, request origin, the whole R2 and Bunny lifecycle, notifications and admin stats. - Six video-page hooks, and the chunking arithmetic extracted out of lib/client/r2-video-upload.ts as a pure module. - Five end-to-end flows: workspace members, bulk operations, the admin area, player interaction and failure recovery. Three things about the harness itself turned out to be wrong: - Two @/lib/r2 stubs in tests/setup/api.ts had the wrong return shape, so every route reaching finalizeR2VideoUpload silently took the "not a valid video" branch and no test noticed. - The auth matrix asserted only "not 2xx", which two entries satisfied without their guard existing. It now requires 401 or 403, which makes both load-bearing, and all 60 routes pass the stricter form. - Both admin API routes had no positive control anywhere: replacing their guard with an unconditional refusal left the entire suite green. Found by the adversarial review, now covered. Process: - bun run test:mutation runs StrykerJS over the authorization and validation modules. Diagnostic, not a gate, weekly in CI rather than on a push. - playwright.config.ts gains an opt-in webkit project for the player spec. - AGENTS.md now requires a batch of new tests to be reviewed by somebody who did not write them. Only two production files change, both deliberate: lib/auth.ts loses a verbatim copy of its own permission formulas, and lib/client/r2-video-upload.ts calls the extracted arithmetic. No behaviour change in either.
62 lines
2.3 KiB
JSON
62 lines
2.3 KiB
JSON
{
|
|
"$schema": "./node_modules/@stryker-mutator/core/schema/stryker-schema.json",
|
|
"_comment": [
|
|
"Mutation testing. Stryker rewrites one line of a source file at a time and reruns",
|
|
"the suite; a mutant that survives is a line no test disagrees with, which is the",
|
|
"machine-checkable version of 'this test cannot fail'.",
|
|
"",
|
|
"This suite was built with three tests that could not fail, all found by hand. This",
|
|
"config is what finds the fourth. It is diagnostic and it does not gate a merge: see",
|
|
"`break: null` below, and TESTING.md section 11 for the same reasoning applied to",
|
|
"coverage.",
|
|
"",
|
|
"Run it with `bun run test:mutation`, which puts it in a node container because",
|
|
"Stryker needs node and the report lands in reports/mutation/. CI runs it weekly and",
|
|
"on demand, never on a push, because a full run is minutes rather than seconds."
|
|
],
|
|
"packageManager": "npm",
|
|
"testRunner": "vitest",
|
|
"vitest": {
|
|
"configFile": "vitest.mutation.config.ts"
|
|
},
|
|
"reporters": ["html", "clear-text", "progress"],
|
|
"htmlReporter": {
|
|
"fileName": "reports/mutation/index.html"
|
|
},
|
|
"coverageAnalysis": "perTest",
|
|
"timeoutMS": 60000,
|
|
"concurrency": 4,
|
|
"_mutate_comment": [
|
|
"Listed one by one rather than globbed as `lib/**`, and the reason matters. Stryker",
|
|
"reports every mutant in a file with no unit coverage as survived, so globbing the",
|
|
"whole of lib/ would bury the real findings under modules whose only coverage is an",
|
|
"API integration test that this config deliberately does not run (see",
|
|
"vitest.mutation.config.ts). A report that is mostly noise gets ignored.",
|
|
"",
|
|
"So the list is the authorization and input-validation surface, the places where a",
|
|
"test that cannot fail is actually dangerous. Add a module here once it has real",
|
|
"unit coverage."
|
|
],
|
|
"mutate": [
|
|
"lib/route-access.ts",
|
|
"lib/rate-limit.ts",
|
|
"lib/share-links.ts",
|
|
"lib/r2-upload-token.ts",
|
|
"lib/bunny-upload-token.ts",
|
|
"lib/request-origin.ts",
|
|
"lib/logger.ts",
|
|
"lib/validation.ts",
|
|
"lib/email-validation.ts",
|
|
"lib/image-upload-validation.ts",
|
|
"lib/video-upload-validation.ts",
|
|
"lib/guest-identity.ts",
|
|
"lib/billing.ts",
|
|
"lib/content-security-policy.ts"
|
|
],
|
|
"thresholds": {
|
|
"high": 85,
|
|
"low": 70,
|
|
"break": null
|
|
}
|
|
}
|