Skip to content

chore: Replace mocha and sinon with node:test - #247

Merged
RobinBol merged 2 commits into
masterfrom
chore/node-test
Oct 23, 2026
Merged

RobinBol merged 2 commits into
masterfrom
chore/node-test

Conversation

@RobinBol

@RobinBol RobinBol commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

What

mocha and sinon out, node:test in. @types/sinon goes with them.

"test": "node --test --test-reporter=spec --test-timeout=5000 \"test/*.js\""

Why

The suite barely used either. mocha: describe, it and the four hooks, no this.timeout, no .only, no chai; assertions were already node:assert. sinon: createSandbox in four files, and from it spy, stub().callsFake(), stub().returns() and restore(). All of it maps onto the mock API one for one.

How

22 callback tests were silently asserting nothing. With function(done) node:test sees a one-parameter function, treats the test as synchronous, passes it and never runs the assertions:

$ node -e "const {it}=require('node:test'); it('fake', function(done){ setTimeout(()=>{ try{done()}catch(e){console.log('DONE THREW:',e.message)} },20); });"
✔ fake (0.292333ms)
DONE THREW: done is not a function
ℹ pass 1   fail 0

All 22 are now function(t, done) (testMfgSpecificCommands.js 17, doorLock.js 2, iasZone.js 2, attributeReport.js 1). This is the main thing to review here.

node:test has no default timeout, so a done that never fires hangs instead of failing after 2000ms. Hence --test-timeout=5000. Sabotaging an assertion inside a done handler hung for 120s without it and fails properly with it, which doubles as proof the converted tests really do assert.

The only real delay is gone. testClusterResponseTimeout.js waited 150ms against a 100ms command timeout; it now uses mock.timers. Still load-bearing: moving the setTimeout in lib/Cluster.js out of sendFrame().then() fails both the old version (102ms) and the new one (1.7ms).

test/*.js keeps exactly mocha's file set; a bare node --test would also pick up test/util/ and test/manual/, which are helpers.

Testing

npm ci && npm test -> 114 pass, 0 fail. Five consecutive runs, no unhandled rejections, no flakes. lint, format:check, build, generate-types with an unchanged index.d.ts and tsc --noEmit all clean.

With the four PRs before it: devDependencies 14 -> 9, lockfile 584 -> 203 entries, npm audit 19 -> 2. The two left are taffydb via @athombv/jsdoc-template.

@RobinBol
RobinBol force-pushed the chore/docs-preview-without-serve branch from 598d9b9 to 8b055a7 Compare October 22, 2026 15:05
@RobinBol
RobinBol requested a balanced review from Copilot October 22, 2026 15:12

Copilot AI 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.

🟢 Approval recommended

Static review found no blocking issues in the callback conversions, mock replacements, timer sequencing, or dependency cleanup.

No open issues 🎉

What changed in this PR

Replaces Mocha and Sinon with Node.js’s built-in test runner and mocking APIs for the Zigbee cluster library, without changing production code.

Changes:

  • Migrates test imports, hooks, spies, and stubs, including all 22 callback-style tests.
  • Adds a five-second test timeout and replaces the response-timeout test’s real delay with mock timers.
  • Removes obsolete dependencies and Mocha lint globals, and updates contributor documentation.
File Description
test/​testZCLError.js Imports built-in test functions.
test/​testTrxSequenceNumber.js Converts random-value stubbing and mock cleanup.
test/​testNode.js Migrates spies and call assertions to native mocks.
test/​testMfgSpecificCommands.js Updates 17 callback tests to accept test context first.
test/​testConfigureReportingRecordsStruct.js Imports built-in test functions.
test/​testClusterResponseTimeout.js Migrates mocks and replaces the real delay with mock timers.
test/​ota.js Imports built-in test functions.
test/​onOff.js Imports built-in test functions.
test/​levelControl.js Imports built-in test functions.
test/​iasZone.js Converts notification callback tests.
test/​endpointStandalone.js Imports built-in test functions.
test/​doorLock.js Converts notification callback tests.
test/​defaultResponse.js Imports built-in test functions.
test/​colorControl.js Migrates frame spies and mock cleanup.
test/​boundClusterAttributeStatus.js Imports built-in test functions.
test/​attributeReport.js Converts the attribute-report callback test.
README.md Updates the documented test framework.
package.json Switches test runners and removes Mocha and Sinon dependencies.
package-lock.json Removes obsolete test dependency entries.
eslint.config.js Removes Mocha globals.
AGENTS.md Documents native test commands and callback signatures.

Review effort: Balanced

Copilot AI 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.

🟢 Approval recommended

Static review found no blocking issues in the callback conversions, mock migration, timer handling, or dependency cleanup.

No open issues 🎉

Review effort: Balanced

Copilot AI 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.

🟢 Approval recommended

The callback conversions, mock lifecycle, timer handling, and dependency cleanup are consistent with the new runner, with no blocking issues identified.

No open issues 🎉

Review effort: Balanced

@RobinBol
RobinBol force-pushed the chore/docs-preview-without-serve branch from bd3b924 to 98eabb9 Compare October 23, 2026 07:32
@RobinBol RobinBol changed the title chore: replace mocha and sinon with node:test chore: Replace mocha and sinon with node:test Oct 23, 2026
@RobinBol
RobinBol requested a balanced review from Copilot October 23, 2026 07:33

Copilot AI 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.

🟢 Approval recommended

The callback and mock conversions are consistent with the native test APIs, and no blocking issues were identified.

No open issues 🎉

Review effort: Balanced

node:test covers describe/it/hooks and the mock API covers the four
sinon sandbox uses (spy, stub, callsFake, restore), so both packages
and @types/sinon can go.

Two things node:test does differently:
- A callback test must take the context first, function(t, done). With
  function(done) node:test treats the test as synchronous, passes it and
  never runs the assertions. All 22 callback tests are updated.
- There is no default test timeout, so a done that never fires hangs
  instead of failing. --test-timeout=5000 restores mocha's safety net.

The one test that waited on a real 150ms timer now uses mock.timers.
The test files already require `node:test` on the line above, so the
unprefixed `assert` next to it was the odd one out.
@RobinBol
RobinBol force-pushed the chore/docs-preview-without-serve branch from 98eabb9 to 96d21d5 Compare October 23, 2026 08:05
@RobinBol
RobinBol requested a balanced review from Copilot October 23, 2026 08:05

Copilot AI 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.

🟢 Approval recommended

Static review found no blocking defects in the callback conversions, native mocks, timer sequencing, or dependency cleanup.

No open issues 🎉

Review effort: Balanced

Base automatically changed from chore/docs-preview-without-serve to master October 23, 2026 08:08
@RobinBol
RobinBol merged commit 48eaef4 into master Oct 23, 2026
3 checks passed
@RobinBol
RobinBol deleted the chore/node-test branch October 23, 2026 08:08
@RobinBol RobinBol added the internal Tooling, CI or docs, left out of the release notes label Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal Tooling, CI or docs, left out of the release notes

Development

Successfully merging this pull request may close these issues.

2 participants