feat(auth-server): migrate 15 Mocha test files to co-located Jest specs PART 7#20161
feat(auth-server): migrate 15 Mocha test files to co-located Jest specs PART 7#20161
Conversation
a690a58 to
e7dddc3
Compare
dschom
left a comment
There was a problem hiding this comment.
Leaving partial review comments. Currently I have looked at
packages/fxa-auth-server/lib/routes/oauth/index.spec.tspackages/fxa-auth-server/lib/routes/subscriptions/support.spec.tspackages/fxa-auth-server/lib/routes/account.spec.ts
I think there's a few things we should address in this PR, so as not make more work for ourselves later. Part of switching over to jest is using jest mocks and assertions, which is noted in the ticket, so:
- Let's juse jest mock and stop using sinon. Worth noting seems like we've been doing a good job removing proxyquire.
- Let's use
.rejectsinstead oftry/catches - Let's use
.toBeCalledWithinstead of.args[][] - Let's be consistent with use of
afterEach&afterAllfor mock resets & restores - We can take care of types in later reviews, so
anyare okay for now, but let's clean up low hanging things like getting rid of unused args and what not.
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
|
||
| export {}; |
There was a problem hiding this comment.
What's up with these export empty objects...?
|
|
||
| import sinon from 'sinon'; | ||
|
|
||
| const mocks = require('../../../test/mocks'); |
There was a problem hiding this comment.
Why are we requiring in a .ts file?
There was a problem hiding this comment.
After side barring, I see what's going here... I am leaving this comment for historical record, so people know this is intended to be temporary and intentional so as to limit the number of changes that could affect parity. I'm not going to call out any stuff like this going forward.
|
|
||
| sinon.assert.calledOnce(mockVerify); | ||
| expect(resp).toEqual(MOCK_ID_TOKEN_CLAIMS); | ||
| mockVerify.restore(); |
There was a problem hiding this comment.
This should be done in an afterEach
| export {}; | ||
|
|
||
| import sinon from 'sinon'; | ||
| import nock from 'nock'; |
There was a problem hiding this comment.
We should use jest for 'nocking'.
|
|
||
| sinon.assert.calledOnce(mockVerify); | ||
| expect(resp).toEqual(MOCK_ID_TOKEN_CLAIMS); | ||
| mockVerify.restore(); |
There was a problem hiding this comment.
This isn't needed. Already in afterEach... Clean up all occurrences.
| Promise.reject(new Error('Database connection failed')) | ||
| ); | ||
|
|
||
| return runTest(route, mockRequest, (response: any) => { |
| }, | ||
| ]); | ||
| }); | ||
| return runTest(route, mockRequest, (response: any) => { |
| expect(securityQuery.uid).toBe(uid); | ||
| expect(securityQuery.ipAddr).toBe(clientAddress); | ||
|
|
||
| expect(!!record).toBe(true); |
There was a problem hiding this comment.
Let's be consistent. Other places we've been doing it like this: expect(record).toBeTruty()
| expect(record).toBeUndefined(); | ||
| }); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Move the test 'it records security event' here. Some how it got hoisted up to the top of the file.
| allowedRegions: ['US'], | ||
| }); | ||
| // Set after route creation — handler reads from Container at call time | ||
| Container.set(RecoveryPhoneService, mockService); |
There was a problem hiding this comment.
Why does it matter if it's done before or after?
The sinion removal was noted in this PR description. Keeping sinion assertions allow us to have near direct parity to verify no gaps in testing coverage and logic, whereas jest we have to do more thinking to verify they match since it can simpfly assertions. There is a ticket filed to track this update https://mozilla-hub.atlassian.net/browse/FXA-13263. I can update the PR to include your other comments though. |
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
|
||
| export {}; |
| expect(err.errno).toBe(error.ERRNO.INVALID_PARAMETER); | ||
| } | ||
|
|
||
| expect(devices.destroy.calledOnceWith(request, deviceId)).toBe(true); |
There was a problem hiding this comment.
Should be expect(devices.destroy).toHaveBeenCalledWith(request, deviceId)
| } | ||
|
|
||
| expect(devices.destroy.calledOnceWith(request, deviceId)).toBe(true); | ||
| expect(db.deleteSessionToken.notCalled).toBe(true); |
There was a problem hiding this comment.
Ditto, pattern exists throughout file.
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
|
||
| export {}; |
| }; | ||
|
|
||
| mockCmsManager = { | ||
| fetchCMSData: sinon.stub(), |
There was a problem hiding this comment.
Why don't we use the sinon sandbox? If we are worried about tests drifting in behavior, seems like keeping the original sandbox approach is better?
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
|
||
| export {}; |
There was a problem hiding this comment.
I don't see why this is needed.
| uid: uid, | ||
| }, | ||
| payload: { | ||
| id: deviceId, |
There was a problem hiding this comment.
I think it's fine, but previously this was deviceId.toString('hex')
| }, | ||
| }; | ||
| return runTest(route, mockRequest, () => { | ||
| expect(false).toBeTruthy(); |
There was a problem hiding this comment.
In other tests we've just been throwing an error. Let's be consistent throw new Error('should have thrown').
| userAgent: 'test user-agent', | ||
| sigsciRequestId: 'test-sigsci-id', | ||
| clientJa4: 'test-ja4', | ||
| uid: uid, |
There was a problem hiding this comment.
Same comment as above. For some reason old tests were calling uid.toString('hex'). I'm guessing it's not necessary though...
| mockCustoms = mocks.mockCustoms(); | ||
| }); | ||
|
|
||
| it('retrieves messages using the pushbox service', () => { |
There was a problem hiding this comment.
Not there's a pending change on this one, https://github.com/mozilla/fxa/pull/20183/changes
There was a problem hiding this comment.
There will be some drift, I think its ok if we can address that in follow ups. My goal (in theory) was to get the tests landed, then locked, then update/refactor more before deleting the mocha ones.
| '/linked_account/login' | ||
| ); | ||
|
|
||
| await expect(runTest(route, mockRequest)).rejects.toMatchObject({ |
There was a problem hiding this comment.
In other places in this PR, we did not use rejects. I still feel like this the right thing to do, but can we be consistent with changes?
There was a problem hiding this comment.
Sigh, this was addressed as part of your original feedback but I suppose there were some missing parts. I'll do another pass and see what it finds.
| sinon.stub(ScopeSet, 'fromArray').returns({ contains: () => true }); | ||
| }); | ||
|
|
||
| afterEach(() => { |
There was a problem hiding this comment.
Calling this out for future cleanup, but this seems like a much more typical way to write at test. Either way, it'd be nice to be consistent between test suites in the future.
| passwordRoutes, | ||
| '/password/forgot/send_otp', | ||
| mockRequest | ||
| ).then((response: any) => { |
There was a problem hiding this comment.
In other test conversions we moved away from promise changes and switched to async/await, which is better. Just calling this out for future improvement / consistency.
| expect(err.output.headers['retry-after']).toBe('10001'); | ||
| } | ||
|
|
||
| // flag() is now a noop |
There was a problem hiding this comment.
Looks like dropped an assertion... See 'Nothing is returned when flag() is called (now a noop)' in original file. Maybe it's fine not to check this... it's just not one to one with the previous test suite.
There was a problem hiding this comment.
The assertion is below, verifies the same as mocha.
| let accessToken2: any; | ||
|
|
||
| beforeEach(async () => { | ||
| await redis.redis.flushall(); |
There was a problem hiding this comment.
There's a note about why we don't use flush all due to concerns with parallel test workers. Jest actually runs in parallel by default. Are we sure we ant to switch to flush all?
There was a problem hiding this comment.
Also why are these tests being altered? Isn't this PR just for unit tests?
There was a problem hiding this comment.
This change is technically unrelated but I thought necessary since its current form introduces flaky behavior in the remote tests (it failed in one of the PR runs while working on this). In mocha, our integration tests run serially so the flushAll is fine, however, with jest we are running multiple tests at same time and the flushAll could break unrelated tests.
| let oldMeta: any; | ||
|
|
||
| beforeEach(async () => { | ||
| await redis.redis.flushall(); |
…ix l10n test brittleness
|
@dschom Thanks for the reviews, I've made the non sinion updates (I think). We got a few more iterations so will also be able to address if anything is missing. |
Because
test/local/are legacy and being migrated to co-located Jest specs inlib/This pull request
.spec.tsfiles co-located next to their source modules inlib/assert.*assertions to Jestexpect()matchers while retainingsinonfor mockingbefore/after→beforeAll/afterAll,beforeEach/afterEachunchangedjest.config.jsto includejest.setup-proxyquire.jssetup fileTest Parity
Test count per file (382/382 — 100% parity)
test/local/customs.jslib/customs.spec.tstest/local/routes/account.jslib/routes/account.spec.tstest/local/routes/attached-clients.jslib/routes/attached-clients.spec.tstest/local/routes/cms.jslib/routes/cms.spec.tstest/local/routes/devices-and-sessions.jslib/routes/devices-and-sessions.spec.tstest/local/routes/emails.jslib/routes/emails.spec.tstest/local/routes/geo-location.jslib/routes/geo-location.spec.tstest/local/routes/linked-accounts.jslib/routes/linked-accounts.spec.tstest/local/routes/newsletters.jslib/routes/newsletters.spec.tstest/local/routes/oauth.jslib/routes/oauth/index.spec.tstest/local/routes/password.jslib/routes/password.spec.tstest/local/routes/security-events.jslib/routes/security-events.spec.tstest/local/routes/session.jslib/routes/session.spec.tstest/local/routes/support.jslib/routes/subscriptions/support.spec.tstest/local/routes/unblock-codes.jslib/routes/unblock-codes.spec.tsAssertion count comparison
assert.*+sinon.assert.*)expect()+sinon.assert.*)Issue
Closes: https://mozilla-hub.atlassian.net/browse/FXA-12611
Checklist
How to test
Notes
jest.fn()) to minimize behavioral risk during migrationtest/local/are not removed in this PR — deletion is a separate step after CI validationverification-reminders.spec.ts(44 tests) is excluded fromnx test-unitsince it requires Redis (treated as integration)