Conversation
f86524b to
1c4c787
Compare
| expect(db.totpToken.callCount).toBe(1); | ||
|
|
||
| // emits correct metrics | ||
| expect(request.emitMetricsEvent.callCount).toBe(1); |
There was a problem hiding this comment.
Obviously nothing to change, just noting that this is the opposite of the kind of tests I highlighted above 😅 . The test just says "should return false for invalid TOTP code" but then it has a bunch of other assertions
There was a problem hiding this comment.
non-blocking, just curious why you removed this?
There was a problem hiding this comment.
Ah, it is still there just got moved to diff line.
nshirley
left a comment
There was a problem hiding this comment.
Nothing blocking, just a few observations why checking out the tests!
There was a problem hiding this comment.
Pull request overview
Migrates MFA and recovery-related route/unit tests in fxa-auth-server from legacy Mocha/Chai test/local/** to co-located Jest TypeScript specs under lib/**, aligning with the repo’s Jest co-location pattern and supporting the broader Mocha → Jest migration.
Changes:
- Added co-located Jest
.spec.tssuites forserverJWT,totp,recovery-codes,recovery-key, andrecovery-phone. - Replaced Chai assertions with Jest
expectpatterns and updated module mocking (proxyquire→jest.mock/jest.doMock). - Added TypeDI cleanup via
Container.reset()in relevant suites.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/fxa-auth-server/lib/serverJWT.spec.ts | New Jest/TS unit tests for JWT signing/verifying with jest.doMock of jsonwebtoken. |
| packages/fxa-auth-server/lib/routes/totp.spec.ts | New Jest/TS tests for TOTP routes and setup/verify flows, including Redis and Glean mocks. |
| packages/fxa-auth-server/lib/routes/recovery-codes.spec.ts | New Jest/TS tests for recovery codes routes and related events/metrics. |
| packages/fxa-auth-server/lib/routes/recovery-key.spec.ts | New Jest/TS tests for recovery key routes, including mocking authorized clients. |
| packages/fxa-auth-server/lib/routes/recovery-phone.spec.ts | New Jest/TS tests for recovery phone routes, custom mocks, and webhook verification paths. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ); | ||
| sinon.assert.calledOnceWithExactly( | ||
| mockStatsd.increment, | ||
| 'account.recoveryPhone.signinSendCode.success' |
There was a problem hiding this comment.
RecoveryPhoneHandler calls statsd.increment(metric, getClientServiceTags(request)), which always provides a second argument (an object, often {} in these unit tests). This assertion uses calledOnceWithExactly but only checks the metric name, so it will fail if increment is invoked with the expected tags argument. Update the assertion to include the tags argument (e.g., {}/sinon.match({})) or relax it to calledOnce + argument checks.
| 'account.recoveryPhone.signinSendCode.success' | |
| 'account.recoveryPhone.signinSendCode.success', | |
| sinon.match({}) |
| }, | ||
| } | ||
| ); | ||
| sinon.assert.calledOnceWithExactly( |
There was a problem hiding this comment.
statsd.increment is invoked by the route with a second argument for client/service tags (typically {} in these unit tests). This calledOnceWithExactly assertion only expects the metric string, so it will not match the actual call signature. Include the tags argument in the expectation or relax the assertion.
| sinon.assert.calledOnceWithExactly( | |
| sinon.assert.calledOnce(mockStatsd.increment); | |
| sinon.assert.calledWith( |
| expect(mockCustoms.checkAuthenticated.getCall(0).args[3]).toBe( | ||
| 'recoveryPhoneSendSetupCode' | ||
| ); | ||
| sinon.assert.calledOnceWithExactly( |
There was a problem hiding this comment.
The route calls statsd.increment(metric, getClientServiceTags(request)), so increment receives a second (tags) argument. This assertion uses calledOnceWithExactly but only supplies the metric name, which will fail against the actual call. Assert on both arguments (metric + tags) or switch to a less strict assertion.
| sinon.assert.calledOnceWithExactly( | |
| sinon.assert.calledWithMatch( |
| } | ||
| ); | ||
|
|
||
| sinon.assert.calledOnceWithExactly( |
There was a problem hiding this comment.
statsd.increment is called with a tags object via getClientServiceTags(request) in the handler. This calledOnceWithExactly expectation only includes the metric string, so it won't match the real invocation (which includes a second argument). Update the assertion to expect the tags argument as well (often {} in these tests) or relax it.
| sinon.assert.calledOnceWithExactly( | |
| sinon.assert.calledOnce(mockStatsd.increment); | |
| sinon.assert.calledWith( |
| sinon.assert.calledOnceWithExactly( | ||
| mockStatsd.increment, |
There was a problem hiding this comment.
This handler increments StatsD with client/service tags (statsd.increment(metric, getClientServiceTags(request))). The calledOnceWithExactly assertion only expects the metric name, so it will fail when the tags object is provided as the second argument. Include the tags argument in the assertion or relax it.
| sinon.assert.calledOnceWithExactly( | |
| mockStatsd.increment, | |
| sinon.assert.calledOnce(mockStatsd.increment); | |
| expect(mockStatsd.increment.getCall(0).args[0]).toBe( |
| }, | ||
| } | ||
| ); | ||
| sinon.assert.calledOnceWithExactly( |
There was a problem hiding this comment.
statsd.increment receives a second argument for tags (getClientServiceTags(request)). This calledOnceWithExactly assertion only passes the metric string, so it will not match the real call signature. Update the assertion to include the tags argument (likely {} here) or make the assertion less strict.
| sinon.assert.calledOnceWithExactly( | |
| sinon.assert.calledOnce(mockStatsd.increment); | |
| sinon.assert.calledWith( |
| ); | ||
| sinon.assert.calledOnceWithExactly( | ||
| mockStatsd.increment, | ||
| 'account.recoveryPhone.phoneRemoved.success' |
There was a problem hiding this comment.
The recovery-phone handlers call statsd.increment(metric, getClientServiceTags(request)), which passes a second tags argument. This calledOnceWithExactly assertion only expects the metric name, so it will fail if increment is invoked with {} as the second parameter. Include the tags argument (or use a looser assertion) to match the real call.
| 'account.recoveryPhone.phoneRemoved.success' | |
| 'account.recoveryPhone.phoneRemoved.success', | |
| sinon.match.any |
|
Copilot picked up that the tests were failing because of stale assertion, fixed the tests and rebasing |
Because
test/local/, outside the co-located Jest pattern established forlib/**/*.spec.tsThis pull request
.spec.tsfiles:serverJWT.spec.ts— 5 tests,proxyquire→jest.doMock/jest.resetModulesrecovery-codes.spec.ts— 8 tests, merged assert pattern splittotp.spec.ts— 16 tests, TOTP generation viaotplibrecovery-key.spec.ts— 52 tests,proxyquire→jest.mockwith delegating function patternrecovery-phone.spec.ts— 34 tests, largest file (1075 lines), custom Glean mockschai.assert.*→expect().*,assert.isRejected→.rejects.toThrow(),assert.failguards →.rejects.*sinon.assert.*calls alongside Jest (established codebase pattern)Container.reset()inafterAllfor TypeDI cleanupParity Comparison
it()it()assert.isTrue(spy.calledOnceWith)split;try/catch→.rejects.toThrowassert.isDefinedremovedtry/catch→.rejects.toMatchObject;assert.failguards removedassert.failin.then(fail, err)patterns removedassert.isDefinedremoved;assert.isRejected→.rejects.toThrowIssue
Closes: https://mozilla-hub.atlassian.net/browse/FXA-12612
Checklist
Other Information
How to verify:
cd packages/fxa-auth-server NODE_ENV=dev npx jest --no-coverage lib/serverJWT.spec.ts lib/routes/recovery-codes.spec.ts lib/routes/totp.spec.ts lib/routes/recovery-key.spec.ts lib/routes/recovery-phone.spec.ts All 115 tests pass. The -36 assertion delta vs Mocha is entirely from removing redundant assert.isDefined guards before property access and collapsing try/catch + assert.fail into Jest-native .rejects patterns — no behavioral coverage was dropped.