diff --git a/packages/jest-regex-util/src/__tests__/index.test.ts b/packages/jest-regex-util/src/__tests__/index.test.ts index ecfa008fd662..d690106beeeb 100644 --- a/packages/jest-regex-util/src/__tests__/index.test.ts +++ b/packages/jest-regex-util/src/__tests__/index.test.ts @@ -11,7 +11,7 @@ describe('replacePathSepForRegex()', () => { describe('posix', () => { beforeAll(() => { jest.mock('path', () => ({ - ...jest.createMockFromModule('path'), + ...jest.createMockFromModule('path'), sep: '/', })); jest.isolateModules(() => { @@ -21,14 +21,14 @@ describe('replacePathSepForRegex()', () => { it('should return the path', () => { const expected = {}; - expect(replacePathSepForRegex(expected as any)).toBe(expected); + expect(replacePathSepForRegex(expected as string)).toBe(expected); }); }); describe('win32', () => { beforeAll(() => { jest.mock('path', () => ({ - ...jest.createMockFromModule('path'), + ...jest.createMockFromModule('path'), sep: '\\', })); jest.isolateModules(() => { diff --git a/packages/jest-test-sequencer/src/__tests__/test_sequencer.test.ts b/packages/jest-test-sequencer/src/__tests__/test_sequencer.test.ts index 52a48762e22c..88b5bb4b9c17 100644 --- a/packages/jest-test-sequencer/src/__tests__/test_sequencer.test.ts +++ b/packages/jest-test-sequencer/src/__tests__/test_sequencer.test.ts @@ -7,12 +7,12 @@ import * as path from 'path'; import * as mockedFs from 'graceful-fs'; -import type {Test, TestContext} from '@jest/test-result'; +import type {AggregatedResult, Test, TestContext} from '@jest/test-result'; import {makeProjectConfig} from '@jest/test-utils'; import TestSequencer from '../index'; jest.mock('graceful-fs', () => ({ - ...jest.createMockFromModule('fs'), + ...jest.createMockFromModule('fs'), existsSync: jest.fn(() => true), readFileSync: jest.fn(() => '{}'), })); @@ -161,7 +161,9 @@ test('writes the cache based on results without existing cache', async () => { }, ], }); - const fileData = JSON.parse(fs.writeFileSync.mock.calls[0][1]); + const fileData = JSON.parse( + fs.writeFileSync.mock.calls[0][1], + ) as AggregatedResult; expect(fileData).toEqual({ '/test-a.js': [SUCCESS, 1], '/test-c.js': [FAIL, 3], @@ -219,7 +221,9 @@ test('writes the cache based on the results', async () => { }, ], }); - const fileData = JSON.parse(fs.writeFileSync.mock.calls[0][1]); + const fileData = JSON.parse( + fs.writeFileSync.mock.calls[0][1], + ) as AggregatedResult; expect(fileData).toEqual({ '/test-a.js': [SUCCESS, 1], '/test-b.js': [FAIL, 1], @@ -228,16 +232,20 @@ test('writes the cache based on the results', async () => { }); test('works with multiple contexts', async () => { - fs.readFileSync.mockImplementationOnce(cacheName => - cacheName.startsWith(`${path.sep}cache${path.sep}`) + fs.readFileSync.mockImplementationOnce(cacheName => { + if (typeof cacheName !== 'string') { + throw new Error('Must be called with a string'); + } + + return cacheName.startsWith(`${path.sep}cache${path.sep}`) ? JSON.stringify({ '/test-a.js': [SUCCESS, 5], '/test-b.js': [FAIL, 1], }) : JSON.stringify({ '/test-c.js': [FAIL], - }), - ); + }); + }); const testPaths = [ {context, duration: null, path: '/test-a.js'}, @@ -270,12 +278,16 @@ test('works with multiple contexts', async () => { }, ], }); - const fileDataA = JSON.parse(fs.writeFileSync.mock.calls[0][1]); + const fileDataA = JSON.parse( + fs.writeFileSync.mock.calls[0][1], + ) as AggregatedResult; expect(fileDataA).toEqual({ '/test-a.js': [SUCCESS, 1], '/test-b.js': [FAIL, 1], }); - const fileDataB = JSON.parse(fs.writeFileSync.mock.calls[1][1]); + const fileDataB = JSON.parse( + fs.writeFileSync.mock.calls[1][1], + ) as AggregatedResult; expect(fileDataB).toEqual({ '/test-c.js': [SUCCESS, 3], }); diff --git a/packages/jest-test-sequencer/src/index.ts b/packages/jest-test-sequencer/src/index.ts index e21dc2028ef1..f55b5ea4c1f2 100644 --- a/packages/jest-test-sequencer/src/index.ts +++ b/packages/jest-test-sequencer/src/index.ts @@ -16,7 +16,7 @@ const FAIL = 0; const SUCCESS = 1; type Cache = { - [key: string]: [0 | 1, number]; + [key: string]: [0 | 1, number] | undefined; }; export type ShardOptions = { @@ -57,7 +57,7 @@ export default class TestSequencer { try { this._cache.set( context, - JSON.parse(fs.readFileSync(cachePath, 'utf8')), + JSON.parse(fs.readFileSync(cachePath, 'utf8')) as Cache, ); } catch {} } @@ -156,21 +156,17 @@ export default class TestSequencer { */ const stats: {[path: string]: number} = {}; const fileSize = ({path, context: {hasteFS}}: Test) => - stats[path] || (stats[path] = hasteFS.getSize(path) || 0); - const hasFailed = (cache: Cache, test: Test) => - cache[test.path] && cache[test.path][0] === FAIL; - const time = (cache: Cache, test: Test) => - cache[test.path] && cache[test.path][1]; + stats[path] || (stats[path] = hasteFS.getSize(path) ?? 0); - tests.forEach(test => (test.duration = time(this._getCache(test), test))); + tests.forEach(test => { + test.duration = this.time(test); + }); return tests.sort((testA, testB) => { - const cacheA = this._getCache(testA); - const cacheB = this._getCache(testB); - const failedA = hasFailed(cacheA, testA); - const failedB = hasFailed(cacheB, testB); + const failedA = this.hasFailed(testA); + const failedB = this.hasFailed(testB); const hasTimeA = testA.duration != null; if (failedA !== failedB) { - return failedA ? -1 : 1; + return failedA === true ? -1 : 1; } else if (hasTimeA != (testB.duration != null)) { // If only one of two tests has timing information, run it last return hasTimeA ? 1 : -1; @@ -191,11 +187,12 @@ export default class TestSequencer { } cacheResults(tests: Array, results: AggregatedResult): void { - const map = Object.create(null); + const map = Object.create(null) as Record; tests.forEach(test => (map[test.path] = test)); results.testResults.forEach(testResult => { - if (testResult && map[testResult.testFilePath] && !testResult.skipped) { - const cache = this._getCache(map[testResult.testFilePath]); + const test = map[testResult.testFilePath]; + if (test != null && !testResult.skipped) { + const cache = this._getCache(test); const perf = testResult.perfStats; cache[testResult.testFilePath] = [ testResult.numFailingTests ? FAIL : SUCCESS, @@ -208,4 +205,14 @@ export default class TestSequencer { fs.writeFileSync(this._getCachePath(context), JSON.stringify(cache)), ); } + + private hasFailed(test: Test) { + const cache = this._getCache(test); + return cache[test.path]?.[0] === FAIL; + } + + private time(test: Test) { + const cache = this._getCache(test); + return cache[test.path]?.[1]; + } } diff --git a/scripts/lintTs.mjs b/scripts/lintTs.mjs index cbdfdf79fe6c..760bfb7abdd2 100644 --- a/scripts/lintTs.mjs +++ b/scripts/lintTs.mjs @@ -35,6 +35,7 @@ const packagesToTest = [ 'jest-schemas', 'jest-source-map', 'jest-test-result', + 'jest-test-sequencer', 'jest-transform', 'jest-types', 'test-globals',