Conversation
There was a problem hiding this comment.
Pull request overview
Refactors several fxa-auth-server Jest unit specs to avoid per-test jest.resetModules() / jest.doMock() patterns that repeatedly reload heavy dependency graphs and can trigger Jest worker OOMs.
Changes:
- Convert test suites to file-scope
jest.mock(...)and single modulerequire(...), resetting mock implementations per-test instead of resetting the module registry. - Rework tests to create fresh instances via factories (or fresh config objects) while reusing the already-loaded module graph.
- Update assertions to use shared mock functions and, where needed, snapshot module-load side-effect call arguments to accommodate
clearMocks: true.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/fxa-auth-server/lib/serverJWT.spec.ts | Mock jsonwebtoken once and reset sign/verify mocks per test. |
| packages/fxa-auth-server/lib/push.spec.ts | Mock web-push.sendNotification at file scope and reuse the push factory. |
| packages/fxa-auth-server/lib/oauth/jwt_access_token.spec.ts | Mock ./jwt once and switch tests to reconfigure sign/verify mocks instead of re-requiring. |
| packages/fxa-auth-server/lib/oauth/jwt.spec.ts | Mock ./keys.publicPEM via a delegating jest fn to allow per-test overrides without resetModules. |
| packages/fxa-auth-server/lib/oauth/grant.spec.ts | Move config/db/jwt mocks to file scope and reuse the already-required ./grant module. |
| packages/fxa-auth-server/lib/monitoring.spec.ts | Mock dependencies at file scope and snapshot one-shot module-load calls for assertions. |
| packages/fxa-auth-server/lib/metrics/context.spec.ts | Mock ../metricsCache once and create fresh contexts via the factory per test. |
| packages/fxa-auth-server/lib/log.spec.ts | Mock config and dependencies at file scope; avoid logger name collisions without resetting modules. |
| packages/fxa-auth-server/lib/geodb.spec.ts | Mock config once and mutate captured config object per test instead of reloading the module. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const grantModule = require('./grant'); | ||
| const { validateRequestedGrant, generateTokens, setStripeHelper } = grantModule; | ||
| // eslint-disable-next-line @typescript-eslint/no-require-imports | ||
| const Container = require('typedi').default; |
There was a problem hiding this comment.
grant.js imports Typedi via const { Container } = require('typedi'), but this spec is using require('typedi').default. In CommonJS this is often undefined (or a different value than the named Container export), which would make Container.set(...) fail or target a different container than grant.js uses (so setStripeHelper() would not pick up the mock). Use the same import shape as production code (e.g. const { Container } = require('typedi')).
| const Container = require('typedi').default; | |
| const { Container } = require('typedi'); |
| })); | ||
|
|
||
| // eslint-disable-next-line @typescript-eslint/no-require-imports | ||
| const { MetricsRedis } = require('../metricsCache'); |
There was a problem hiding this comment.
Is there a reason for using require vs plain import? Switching would avoid the eslint-disable comments (same comment for all require in these files)
There was a problem hiding this comment.
I originally thought this was ok since other tests used require but looks like can they can use import, updating.
| // Get ScopeSet from the same module registry as the freshly-required grant | ||
| // module, so that instanceof checks inside grant.js work correctly. | ||
| FreshScopeSet = require('fxa-shared').oauth.scopes; | ||
| mockDB.getScope.mockReset(); |
There was a problem hiding this comment.
Should we also reset the Container to avoid leaks between test blocks?
…XA-13473) Because: `lib/metrics/context.spec.ts` was reloading the ./context -> validators -> fxa-shared -> joi module graph in every `beforeEach` via `jest.resetModules()` + `jest.doMock('../metricsCache', ...)` + `require('./context')`. With ts-jest, --coverage, and 4 workers, the retained heap from ~94 reloads per file SIGKILL'd a Jest worker on the Unit Test (PR) job. Eight sibling specs followed the same anti-pattern. This commit: * Refactors lib/metrics/context.spec.ts to mock ../metricsCache once at file scope, load ./context once, and recreate metricsContext via the factory per-test. The validate tests now call the same factory with per-test config instead of re-requiring the module. 33.5s -> 2.6s. * Applies the same pattern to eight sibling specs that called jest.resetModules() in beforeEach or in helper fns invoked per-test: lib/log.spec.ts (28 tests), lib/monitoring.spec.ts (8), lib/geodb.spec.ts (2), lib/oauth/jwt.spec.ts (11), lib/oauth/jwt_access_token.spec.ts (11), lib/oauth/grant.spec.ts (13), lib/push.spec.ts (28), lib/serverJWT.spec.ts (5). * Captures three non-obvious gotchas surfaced by removing the resets: - log.js keeps a module-level _registered map for logger-name dedup, so each test now uses a unique name (nextLoggerName helper). - clearMocks: true in the global jest config wipes mock.calls between tests; monitoring.spec.ts snapshots the one-shot initMonitoring() args at file scope before clearMocks fires. - geodb.js captures the config object by reference at module load, so the spec mutates properties on a stable object instead of reassigning the variable. Tests: 145 tests across the 9 refactored specs pass; full auth-server suite (150 suites / 3379 tests) clean across 5 consecutive runs.
Because
lib/metrics/context.spec.tswas SIGKILL'ing a Jest workerjest.resetModules()+jest.doMock(...)+require('./context')in a sharedbeforeEach. That reloaded the./context → validators → fxa-shared → joigraph ~94 times per file. Eight sibling specs followed the same anti-pattern.This pull request
lib/metrics/context.spec.tsto mock../metricsCacheonce at file scope, load./contextonce, and recreatemetricsContextvia the factory per-test. 33.5 s → 2.6 s.lib/log.spec.ts(28 tests),lib/monitoring.spec.ts(8),lib/geodb.spec.ts(2),lib/oauth/jwt.spec.ts(11),lib/oauth/jwt_access_token.spec.ts(11),lib/oauth/grant.spec.ts(13),lib/push.spec.ts(28),lib/serverJWT.spec.ts(5).Issue that this pull request solves
Closes: https://mozilla-hub.atlassian.net/browse/FXA-13473
Checklist
Other information
How to test: