Skip to content

chore(test): migrate node:assert/strict to plain node:assert; lint-enforce via oxlint (#1555) - #1558

Merged
kriszyp merged 3 commits into
mainfrom
chore/assert-strict-lint
Jul 6, 2026
Merged

kriszyp merged 3 commits into
mainfrom
chore/assert-strict-lint

Conversation

@heskew

@heskew heskew commented Jul 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Enforces the AGENTS.md test-style convention — plain `node:assert`, never `node:assert/strict` — mechanically and permanently:

  1. `.oxlintrc.json`: adds `no-restricted-imports` (error) rejecting `node:assert/strict` and `assert/strict`, with a message pointing at the house style and the explicit escape hatch (`assert.strictEqual` / `assert.deepStrictEqual` from plain assert).
  2. Migration: swaps the import specifier in 210 test files (119 `unitTests/`, 88 `integrationTests/`, 3 `benchmarks/ycsb/*.test.mts`) — import line only. `git diff --numstat` shows exactly 1 insertion / 1 deletion in every migrated file.
  3. Negative-assertion call-site fix: 37 call sites across 17 files that used `assert.notEqual` / `assert.notDeepEqual` are renamed to `assert.notStrictEqual` / `assert.notDeepStrictEqual`. See "Where to look" below.
  4. Cert-reload / replay-stress imports: 3 files that destructured `equal` from `node:assert/strict` (where it aliased `strictEqual`) now destructure `strictEqual as equal` from plain `node:assert`.
  5. AGENTS.md: the test-style bullet now notes the convention is lint-enforced and names the strict escape hatch.

No non-test source file imported `/strict` anywhere in the repo (full-tree grep across all extensions).

Why

The convention was documented but unenforced, and the codebase violated it ~8:1 — so the AI reviewer re-raised it as a non-blocking nit on every affected PR (most recently #1106) with no path to resolution.

Important correction from initial premise: the original commit message said "strict→loose only ever weakens an assertion, so no currently-green test can turn red." That is wrong for negative assertions. `node:assert/strict` makes `notEqual` an alias for `notStrictEqual` (`!==`); plain `node:assert`'s `notEqual` uses loose `!=`. So `assert.notEqual(null, undefined)` passes under strict (`null !== undefined`) but throws under loose (`null != undefined` is false). This is exactly why northwind LEFT OUTER JOIN integration tests failed on all runtimes: unmatched columns come back as `null`, and the tests asserted `notEqual(row[key], undefined)`. The fix — renaming those 37 call sites to `notStrictEqual` / `notDeepStrictEqual` — is behavior-preserving (restores what they were under `/strict`). Positive assertions (`equal`, `deepEqual`) are unaffected.

Where to look

  • Negative-assertion fixes (all 17 files are method-style `assert.notEqual` / `assert.notDeepEqual`, no destructured imports to worry about): `integrationTests/apiTests/northwind.test.mjs` (the deterministic CI failure), `integrationTests/apiTests/system-information.test.mjs`, `integrationTests/apiTests/token-auth.test.mjs`, `integrationTests/apiTests/components.test.mjs`, `unitTests/config/harperConfigEnvVars.test.js`, and 12 others.
  • Cert-reload `strictEqual as equal` alias (3 files): these were caught by Gemini's inline review; threads resolved.
  • The lint rule was validated TDD-style: enabled before migration it produced 92+ `no-restricted-imports` errors; after, zero.

Verification

  • `grep` for `(node:)?assert/strict` across every JS/TS extension: zero remaining.
  • `npm run lint:required` (the CI-enforced script): exit 0. `prettier --check` on all changed files: clean.
  • `npm run build`: identical to baseline (same pre-existing unrelated TS errors; dist emits fine).
  • Mocha subsets green: `unitTests/config/harperConfigEnvVars.test.js` (20 passing, exercises the 3 `notStrictEqual` hash assertions), `unitTests/components/mcp` sessions/registry/resources/transport (160 passing, exercises the `notStrictEqual` calls there), `unitTests/components/status` (135), `unitTests/resources/models` (283).
  • northwind / system-information / token-auth are integration tests needing a live instance — CI verifies those; the fix is deterministic (null !== undefined under strict).

Closes #1555


Generated by an LLM (Claude Sonnet 5, orchestrated via Claude Code).

🤖 Generated with Claude Code

…force via oxlint

AGENTS.md documents plain node:assert as house style and explicitly rules
out node:assert/strict, but nothing enforced it and 210 test files
(unitTests, integrationTests, benchmarks) violated the convention. Add
oxlint's no-restricted-imports rule to reject node:assert/strict and
assert/strict imports, then migrate all existing usages so the rule is
green.

The migration swaps only the import/require specifier
(node:assert/strict -> node:assert); call sites are untouched. This is
safe because strict->loose only ever weakens an assertion, so no
currently-green test can turn red, and the loosened assert.equal/deepEqual
semantics are the intended house-style outcome. Three integrationTests
files (cert-key-reload, cert-reload, replay-stress) destructure `equal`
from assert/strict, which silently becomes the loose alias after the
swap — flagged for reviewer awareness, not changed further, since
rewriting call sites to strictEqual would contradict the house style.

Closes #1555

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 2, 2026 •

Copy link
Copy Markdown
Contributor

1. README template still documents the banned import

File: integrationTests/README.md:93,112

What: The PR adds a no-restricted-imports lint rule banning node:assert/strict and updates AGENTS.md with the new convention, but integrationTests/README.md was not updated. Line 93 requires assertions from 'node:assert/strict' and the template on line 112 shows import { strictEqual } from 'node:assert/strict'.

Why it matters: Any contributor who follows this README to write a new integration test will immediately hit a lint error in CI. AGENTS.md and the lint rule point in the same direction; the README template points the opposite direction.

Suggested fix:

Line 93 — change:

with assertions from `node:assert/strict`

to:

with assertions from `node:assert` — use `assert.strictEqual`/`assert.deepStrictEqual` for strict checks (`node:assert/strict` is banned by lint; see AGENTS.md test style)

Line 112 — change:

import { strictEqual } from 'node:assert/strict';

to e.g.:

import assert from 'node:assert';

(then assert.strictEqual(response.status, 200) in the test body)


The two follow-on commits (840b349a, bf0fffd9) correctly fix the cert-reload/replay-stress alias and the 37 notEqual call sites — no new concerns from those pushes. This README update is the last outstanding item.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request replaces imports of node:assert/strict and assert/strict with plain node:assert and assert across the test suite, aligning with the project's house style. It also adds a lint rule in .oxlintrc.json to enforce this restriction and updates the AGENTS.md documentation. The review feedback highlights that in several files (cert-key-reload.test.ts, cert-reload.test.ts, and replay-stress.test.ts), changing the import to plain node:assert inadvertently changes the behavior of equal from strict equality to loose equality. It is recommended to alias strictEqual as equal in these imports to preserve strict semantics.

Comment thread integrationTests/security/cert-key-reload.test.ts Outdated
Comment thread integrationTests/security/cert-reload.test.ts Outdated
Comment thread integrationTests/server/replay-stress.test.ts Outdated
… strictEqual-as-equal alias (gemini review)

Three security/stress integration tests destructured `equal` from
node:assert/strict, where it aliased strictEqual (===). After the import
migration to plain node:assert, `equal` would silently become the loose
== version. Preserve strict semantics without touching any call sites by
aliasing: `import { ok, strictEqual as equal } from 'node:assert'`.

This is the documented strict escape hatch in AGENTS.md and does not
conflict with the no-restricted-imports lint rule, which only bans the
node:assert/strict path.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…iles

The initial migration ("strict→loose only weakens") was wrong for negative
assertions. node:assert/strict makes notEqual an alias for notStrictEqual
(!==); plain node:assert's notEqual uses loose !=. So
assert.notEqual(null, undefined) passes under strict but throws under
loose, which is exactly what broke the northwind LEFT OUTER JOIN
integration tests: unmatched columns come back as null, and tests asserted
notEqual(row[key], undefined).

Fix: rename 37 call sites across 17 files from assert.notEqual →
assert.notStrictEqual and assert.notDeepEqual → assert.notDeepStrictEqual.
All are method-style calls on the default assert namespace; no import
changes needed. This restores the exact behavior those files had under
node:assert/strict.

Positive assertions (equal, deepEqual) are unaffected — loosening those
is the intended house-style outcome.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@heskew
heskew marked this pull request as ready for review July 2, 2026 15:04

@kriszyp kriszyp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed via Claude review-queue — semantics-preserving node:assert/strict->plain migration, verified full-tree grep clean and negative-assertion renames diff 1:1 to strict variants. CI green. LGTM.

@kriszyp
kriszyp merged commit ecfb995 into main Jul 6, 2026
82 of 83 checks passed
@kriszyp
kriszyp deleted the chore/assert-strict-lint branch July 6, 2026 12:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enforce plain node:assert test style: migrate node:assert/strict usages + add oxlint no-restricted-imports

2 participants