Repository navigation
test: kill the surviving mutants in the shared ISO 8601 timestamp gate - #1786
Conversation
StrykerJS over scripts/lib/validate-utils.mjs scored 91.67% with 16 survivors. Five of them were unasserted behaviour in the strict ISO 8601 UTC gate that four validators share: - all four mutants over the composite roundTrips expression: nothing rejected a four-digit year below 0100, and Date.UTC(26, 0, 1) is 1926-01-01, so the year arm is the only one that catches it. Every other out-of-range component cascades into the next-higher unit and trips a second arm as well. - the EqualityOperator mutant turning the future-skew test from > into >=. The existing window tests sit 30s inside and 24h outside it, so neither observes the boundary itself. Three tests close those: a year Date.UTC remaps into the 1900s, the future-tolerance boundary and the millisecond past it, and text wrapped around an otherwise valid instant. The boundary case needs the clock pinned, since a value derived from a live Date.now() is already in the past by the time the comparison runs. The file now scores 94.27% with 11 survivors, all equivalent mutants: the per-arm roundTrips mutants cannot be isolated because of the cascade, Node accepts Buffer.from(text, '') as utf8, Date.parse rejects every wrapped form so neither ISO_8601_PATTERN anchor is observable through the helper, Date.now() + undefined is NaN either way, and CNCF_HOST_SUFFIXES holds a single entry so its join separator never appears. 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 |
✅ Deploy Preview for endusers ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Read the diff against scripts/lib/validate-utils.mjs at head ece221c; all three new tests pin real, previously unasserted behaviour:
- Year-remap test —
Date.UTC(26, 0, 1)does resolve to 1926, so for0026-01-01T00:00:00Zonly thegetUTCFullYear() === yeararm (validate-utils.mjs:118) rejects it; the other round-trip arms all pass. This genuinely isolates the year arm. - Boundary test — the skew check at
validate-utils.mjs:174-175is strict>, so a value exactlyfutureToleranceMsahead passes and the next millisecond fails, exactly as asserted.withFixedNowis sound:checkIsoTimestampreads the clock via theDate.nowglobal, which the helper swaps and restores infinally;Date.parseandnew Date(...)insideisoUtcTimeare untouched by the mock. - Anchor test —
ISO_8601_PATTERN(validate-utils.mjs:89-90) is^…$-anchored, so each wrapped form fails the match rather than reachingDate.parse, pinning the anchors' purpose.
Tests-only, one file, no overlap with the other held PRs (#1782 and #1784 touch the same test file but disjoint test blocks — no conflict). Mutation-testing and unit-coverage checks are green on this head. Looks correct to me; fine to land once a maintainer signs off.
— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.88
Test Improvement
Tests only — no production change. Touches one file,
tests/validate-utils.test.mjs, and only thecheckIsoTimestampcases plus alocal
withFixedNowhelper.StrykerJS over
scripts/lib/validate-utils.mjsscored 91.67% with 16surviving mutants. Five were unasserted behaviour in the strict ISO 8601 UTC
gate (
isoUtcTime/checkIsoTimestamp) thatvalidate-community-groups,validate-community-people,validate-enduser-membersandvalidate-launch-metricsall rely on:validate-utils.mjs:117— all four mutants over the compositeroundTripsexpression. Nothing rejected a four-digit year below
0100, andDate.UTC(26, 0, 1)is1926-01-01, so the year arm is the only one thatcatches it: every other out-of-range component cascades into the next-higher
unit and trips a second arm as well.
validate-utils.mjs:174— theEqualityOperatormutant turningtime > Date.now() + futureToleranceMsinto>=. The existing window testssit 30s inside and 24h outside the window, so neither observes the boundary.
Three added tests close those:
Date.UTCremaps into the 1900s (0026-01-01T00:00:00Z,0099-12-31T23:59:59Z) is rejected, isolating the year armwith the clock pinned — a value derived from a live
Date.now()is alreadyin the past by the time the comparison runs
ISO_8601_PATTERNanchors are there forThe file now scores 94.27% with 11 survivors. Those 11 are equivalent
mutants and are not chased here: the per-arm
roundTripsmutants (lines118-122) cannot be isolated because of the cascade above; Node accepts
Buffer.from(text, '')as utf8;Date.parserejects every wrapped form, soneither
ISO_8601_PATTERNanchor nor thevalue ?? ''default is observablethrough the helper;
Date.now() + undefinedisNaNeither way; andCNCF_HOST_SUFFIXESholds a single entry, so itsjoinseparator neverappears in the message.
Verification
Run locally at rev
18caa5e(node v26.12.0):TZ=UTC npx stryker run --mutate scripts/lib/validate-utils.mjs— 91.67% /16 survivors before, 94.27% / 11 survivors after
TZ=UTC npm run test:unit:coverage:check— exit 0, src files 100.00% lines /100.00% regions
npx prettier --checkandeslint --max-warnings 0on the changed fileRelated Issue
Refs #1759 — the hive folded this finding into #1759 as a comment because the
body named
stryker.config.mjs. #1759's own deliverable is different andunaffected by this PR: extracting
scripts/validate-architecture-assets.mjsinto a callable core so the existing
scripts/lib/**mutation glob reaches it.That remains open and parked at
stage/045-needs-decision(needs-human: it moves production code, which is outside this lane's PR remit,
and #1752 reserved the broader-adoption call to the maintainer).
No overlap with the open held PRs: #1765 is the SVG active-content allowlist,
#1773 the gitignored Stryker sandbox in two worktree walks, #1782
unescapeMdx, #1784profileImageUrl. None of them touchtests/validate-utils.test.mjsorscripts/lib/validate-utils.mjs.— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88