Repository navigation
test(adapters/app): pin receiveWebhook's refusal texts and header guard, dedupe's capacity boundary and settings' unset-input omission (webhook.ts:35-56, dedupe.ts:15, settings.ts:37) - #612
Conversation
…rd, dedupe's capacity boundary and settings' unset-input omission
Stryker over src/adapters/app/{dedupe,scope,settings,webhook}.ts at 282b8e0
scored 81.08% with 21 survivors; this file kills 16 of them. The behavioural
ones: the header guard's || (a delivery with one of the two headers reached
signature verification under &&), the JSON-parse catch body, the capacity
comparison in memoryDeliveryStore (>= would forget an id at exactly
capacity) and settingsFromEnv's value !== undefined guard (toEqual treats an
explicit undefined key as absent). The rest are the response bodies and the
duplicate/bad-signature log lines that no test read.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: quality <280983584+hivecommons-hive[bot]@users.noreply.github.com>
|
Important Held for human review by the hive's ACMM level gate. This PR was opened by the "quality" agent while Hive policy required a human checkpoint for that agent. Agent PRs are held at ACMM L3–L5; an Hive will keep the |
There was a problem hiding this comment.
Read the diff against the tree at pr612 (0dcaa75), not just the patch. Test-only change — one new file, nothing under src/ — and the claimed mutant kills hold up:
- Header guard (
src/adapters/app/webhook.ts:35): I applied the||→&&mutant locally and ran the new file — the twoit.eachcases fail (a one-header delivery passes a valid signature and returns 202, not the asserted 400). Verified kill. - Dedupe boundary (
src/adapters/app/dedupe.ts:15, eviction atwebhook.ts-adjacentids.size > capacity):memoryDeliveryStore(2)with exactly 2 ids distinguishes>from>=— under the mutant,ais evicted andseen('a')returns false. Verified by readingdedupe.ts:91-99. - JSON-parse catch (
webhook.ts:48-49): the redelivery case is the sharp part — with the catch body removed, the malformed delivery's id would be consumed bydeliveries.seenat line 54, so asserting the corrected redelivery is dispatched (notalready handled) kills it. Correct by trace. - settings guard (
src/adapters/app/settings.ts:139):toStrictEqual+Object.keysdoes distinguish explicit-undefinedkeys thattoEqualcannot; the empty-string case pins the!== undefined(vs truthy) choice.
Helpers (__tests__/adapters/app/testApp.ts) are reused, not duplicated; the file set is disjoint from the held PRs it names (#611's new file is webhookNonErrorThrow.test.ts, different file, and webhook.ts:65-66 mutants are deliberately left to it). Full adapter suite: 4 files, 42 passed locally; CI green including e2e-coverage and DCO.
This looks correct to me. (I don't approve — a maintainer's signature is theirs — but I found nothing to change.)
— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.88
|
/kind cleanup |
Test Improvement
One new file,
__tests__/adapters/app/webhookGuards.test.ts(11 cases), for the GitHub App adapter #608 added. Nothing undersrc/,dist/, config or docs is touched.Why. The adapter landed at 100 % unit lines, but a Stryker pass over
src/adapters/app/{dedupe,scope,settings,webhook}.tsatmain@282b8e0(npx stryker runwith a config that only widensmutate;perTest,vitest.mutation.config.mjs) scored 81.08 % — 21 of 111 mutants survived. Four of them change behaviour:webhook.ts:35—!id || !eventName→&&: a delivery carrying only one of the two headers went on to signature verification instead of being refused. The existing case removes both headers, where||and&&agree.webhook.ts:48— the JSON-parsecatchbody removed: the 400body is not jsonis lost and the request falls through toappPlatform, which happens to throw a different 400.dedupe.ts:15—ids.size > capacity→>=: the store forgets an id at exactlycapacity. The existing case fills past capacity, where both comparisons evict.settings.ts:37—value !== undefinedguard →true: unset inputs become explicitundefinedkeys;toEqual({})cannot see them,toStrictEqualcan.The other 17 are response bodies and log lines nobody read (
missing delivery headers,bad signature,body is not json,pong,already handled,accepted; thewarning/infosink lines for a bad signature and a duplicate). The new file reads each of them once, checks that the header and signature refusals neither read the body (Request.bodyUsed) nor touch the delivery store, and that a malformed body leaves its delivery id unconsumed so a corrected redelivery is still handled.Re-run: 95.50 %,
dedupe.ts/scope.ts/settings.tsat 100 %. The five that remain are two equivalent mutants (new Response(…, {})defaults to 200) and the three onwebhook.ts:65-66, which #611 claims — left alone.Files / cluster claimed —
__tests__/adapters/app/webhookGuards.test.ts;src/adapters/app/dedupe.ts:15,settings.ts:37,webhook.ts:35-56,79. Disjoint from every held PR: #609 (src/platform/index.ts), #611 (src/server/**,webhook.ts:65, its ownwebhookNonErrorThrow.test.ts), #591/#593/#595/#597/#598/#599/#601/#603/#605 (plugins, dispatcher, labels, config, harness, typecheck, coverage hints, runtime). The bad-signature log line this file asserts in-process is the same text #611'sdist-serverbundle test looks for on stdout — different level, different file, and the unit assertion is what makes the Stryker mutant on line 40 die.No issue is filed for this: the repository's mutation-gate proposal (#594) is still awaiting a decision, and this is another instance of the class it covers.
Testing
npx vitest run __tests__/adapters/app— 4 files, 42 passednpx eslint __tests__/adapters/app/webhookGuards.test.ts— cleannpx stryker runover the four adapter files: 81.08 % → 95.50 %; each of the four behavioural mutants above is killed by the case named for itnpm run test:coverageat the base commit — 2525 passed, 99.88 % lines; the only branch misses are the four documented V8 await phantoms (close.ts:37,reopen.ts:34,approve.ts:502,auth.ts:224, negativeBRDAcounts) and the arms test(platform): pin platform()'s no-platform throw and installed-scope fall-back (src/platform/index.ts:49,51) #609/test(server,app): execute src/server's entry point and bundle, pin #614's cron arms, and gate src/adapters/app/** + src/server/** at 100% (main.ts, node.ts:24/67/82, webhook.ts:65, cron.ts:85, vitest.config.mjs) #611 claimFiled by quality agent (hold-gated mode). Human review required.
— hive: agent=quality backend=copilot model=claude-fable-5.1 copilot=1.0.88