Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,10 @@ export default {
// Run tests from one or more projects
// projects: null,

// Use this configuration option to add custom reporters to Jest
// reporters: undefined,
// Custom reporters — default reporter kept for human-readable output; gcReporter
// calls global.gc() after each test suite when --expose-gc is in NODE_OPTIONS
// (active for test:coverage only). No-op when gc() is unavailable.
Comment thread
PierreBrisorgueil marked this conversation as resolved.
reporters: ['default', './scripts/jest.gcReporter.cjs'],
Comment thread
PierreBrisorgueil marked this conversation as resolved.

// Automatically reset mock state between every test
// resetMocks: false,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"test:integration": "cross-env NODE_ENV=test NODE_OPTIONS=--experimental-vm-modules jest --runInBand --testPathPatterns='integration'",
"test:e2e": "cross-env NODE_ENV=test NODE_OPTIONS=--experimental-vm-modules jest --runInBand --testPathPatterns='e2e'",
"test:watch": "cross-env NODE_ENV=test NODE_OPTIONS=--experimental-vm-modules jest --watchAll",
"test:coverage": "cross-env NODE_ENV=test NODE_OPTIONS=--experimental-vm-modules jest --coverage --runInBand",
"test:coverage": "cross-env NODE_ENV=test NODE_OPTIONS=\"--experimental-vm-modules --expose-gc\" jest --coverage --runInBand",
"test:parallel-smoke": "cross-env NODE_ENV=test node scripts/parallel-integration.smoke.js",
"lint": "eslint ./modules ./lib ./config ./scripts",
"seed:dev": "cross-env NODE_ENV=development node scripts/seed.js seed",
Expand Down
34 changes: 34 additions & 0 deletions scripts/jest.gcReporter.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Jest reporter that calls global.gc() after each test suite when available.
*
* Registered in jest.config.js reporters array alongside the default reporter.
* Requires --expose-gc in NODE_OPTIONS (already set in test:coverage script).
*
* Why: jest --runInBand accumulates module registry snapshots, mock closures, and
* Mongoose schema objects across 99 suites in a single process. V8's heuristic GC
* trigger is based on heap growth rate; calling gc() explicitly after each suite
* ensures the old generation is collected before the next suite loads its modules.
* This reduces peak RSS by releasing memory that V8 would otherwise hold until
* it reached the old-space limit.
*
* When --expose-gc is absent (test:all, test:unit, test:integration), global.gc
* is undefined and this reporter is a no-op, so it is safe to leave enabled for
* all test runs.
*/

class GcReporter {
/**
* Called by Jest after each test file completes.
* Triggers an explicit GC cycle when --expose-gc is active (test:coverage only).
* @param {object} _test - Jest test descriptor (unused).
* @param {object} _testResult - Aggregated results for this file (unused).
* @returns {void}
*/
onTestFileResult() {
if (typeof global.gc === 'function') {
global.gc();
}
}
Comment thread
PierreBrisorgueil marked this conversation as resolved.
}

module.exports = GcReporter;
Loading