Skip to content

Commit 2947bcf

Browse files
authored
Merge branch 'main' into defer-cache-dir-creation
2 parents e9cc370 + e61ea77 commit 2947bcf

File tree

119 files changed

+1333
-1042
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+1333
-1042
lines changed

.github/workflows/nodejs.yml

+20-3
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,25 @@ jobs:
112112
with:
113113
os: windows-latest
114114

115+
test-leak:
116+
name: Node LTS on Ubuntu with leak detection
117+
runs-on: ubuntu-latest
118+
needs: prepare-yarn-cache-ubuntu
119+
120+
steps:
121+
- uses: actions/checkout@v3
122+
- name: Use Node.js LTS
123+
uses: actions/setup-node@v3
124+
with:
125+
node-version: lts/*
126+
cache: yarn
127+
- name: install
128+
run: yarn --immutable
129+
- name: build
130+
run: yarn build:js
131+
- name: run tests with leak detection
132+
run: yarn test-leak
133+
115134
test-coverage:
116135
name: Node LTS on Ubuntu with coverage (${{ matrix.shard }})
117136
strategy:
@@ -136,9 +155,7 @@ jobs:
136155
id: cpu-cores
137156
uses: SimenB/github-actions-cpu-cores@v1
138157
- name: run tests with coverage
139-
run: |
140-
yarn jest-coverage --color --config jest.config.ci.mjs --max-workers ${{ steps.cpu-cores.outputs.count }} --shard=${{ matrix.shard }}
141-
yarn test-leak
158+
run: yarn jest-coverage --color --config jest.config.ci.mjs --max-workers ${{ steps.cpu-cores.outputs.count }} --shard=${{ matrix.shard }}
142159
- name: map coverage
143160
run: node ./scripts/mapCoverage.mjs
144161
if: always()

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22

33
### Features
44

5+
- `[@jest/globals, jest-mock]` Add `jest.Spied*` utility types ([#13440](https://github.com/facebook/jest/pull/13440))
6+
57
### Fixes
68

9+
- `[jest-environment-node]` make `globalThis.performance` writable for Node 19 and fake timers ([#13467](https://github.com/facebook/jest/pull/13467))
10+
711
### Chore & Maintenance
812

913
### Performance
1014

15+
- `[*]` Use sha1 instead of sha256 for hashing [#13421](https://github.com/facebook/jest/pull/13421)
1116
- `[jest-transform]` Defer creation of cache directory [#13420](https://github.com/facebook/jest/pull/13420)
1217

1318
## 29.2.0

docs/JestObjectAPI.md

+4
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,10 @@ test('plays audio', () => {
699699
});
700700
```
701701

702+
### `jest.Spied<Source>`
703+
704+
See [TypeScript Usage](MockFunctionAPI.md#jestspiedsource) chapter of Mock Functions page for documentation.
705+
702706
### `jest.clearAllMocks()`
703707

704708
Clears the `mock.calls`, `mock.instances`, `mock.contexts` and `mock.results` properties of all mocks. Equivalent to calling [`.mockClear()`](MockFunctionAPI.md#mockfnmockclear) on every mocked function.

docs/MockFunctionAPI.md

+34
Original file line numberDiff line numberDiff line change
@@ -644,3 +644,37 @@ test('direct usage', () => {
644644
expect(jest.mocked(console.log).mock.calls).toHaveLength(1);
645645
});
646646
```
647+
648+
### `jest.Spied<Source>`
649+
650+
Constructs the type of a spied class or function (i.e. the return type of `jest.spyOn()`).
651+
652+
```ts title="__utils__/setDateNow.ts"
653+
import {jest} from '@jest/globals';
654+
655+
export function setDateNow(now: number): jest.Spied<typeof Date.now> {
656+
return jest.spyOn(Date, 'now').mockReturnValue(now);
657+
}
658+
```
659+
660+
```ts
661+
import {afterEach, expect, jest, test} from '@jest/globals';
662+
import {setDateNow} from './__utils__/setDateNow';
663+
664+
let spiedDateNow: jest.Spied<typeof Date.now> | undefined = undefined;
665+
666+
afterEach(() => {
667+
spiedDateNow?.mockReset();
668+
});
669+
670+
test('renders correctly with a given date', () => {
671+
spiedDateNow = setDateNow(1482363367071);
672+
// ...
673+
674+
expect(spiedDateNow).toHaveBeenCalledTimes(1);
675+
});
676+
```
677+
678+
Types of a class or function can be passed as type argument to `jest.Spied<Source>`. If you prefer to constrain the input type, use: `jest.SpiedClass<Source>` or `jest.SpiedFunction<Source>`.
679+
680+
Use `jest.SpiedGetter<Source>` or `jest.SpiedSetter<Source>` to create the type of a spied getter or setter respectively.

jest.config.mjs

-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ export default {
6363
'/packages/jest-runtime/src/__tests__/NODE_PATH_dir',
6464
'/packages/jest-snapshot/src/__tests__/plugins',
6565
'/packages/jest-snapshot/src/__tests__/fixtures/',
66-
'/packages/jest-validate/src/__tests__/fixtures/',
6766
'/e2e/__tests__/iterator-to-null-test.ts',
6867
'/e2e/__tests__/tsIntegration.test.ts', // this test needs types to be build, it runs in a separate CI job through `jest.config.ts.mjs`
6968
],

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@
113113
"test": "yarn lint && yarn jest",
114114
"typecheck": "yarn typecheck:examples && yarn typecheck:tests",
115115
"typecheck:examples": "tsc -p examples/angular --noEmit && tsc -p examples/expect-extend --noEmit && tsc -p examples/typescript --noEmit",
116-
"typecheck:tests": "tsc -b packages/{babel-jest,babel-plugin-jest-hoist,diff-sequences,expect,expect-utils,jest-circus,jest-cli,jest-config,jest-console,jest-snapshot,pretty-format}/**/__tests__",
116+
"typecheck:tests": "tsc -b packages/{babel-jest,babel-plugin-jest-hoist,diff-sequences,expect,expect-utils,jest-circus,jest-cli,jest-config,jest-console,jest-snapshot,jest-util,jest-worker,pretty-format}/**/__tests__",
117117
"verify-old-ts": "node ./scripts/verifyOldTs.mjs",
118118
"verify-pnp": "node ./scripts/verifyPnP.mjs",
119119
"watch": "yarn build:js && node ./scripts/watch.mjs",

packages/babel-jest/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ function getCacheKeyFromConfig(
7878

7979
const configPath = [babelOptions.config ?? '', babelOptions.babelrc ?? ''];
8080

81-
return createHash('sha256')
81+
return createHash('sha1')
8282
.update(THIS_FILE)
8383
.update('\0', 'utf8')
8484
.update(JSON.stringify(babelOptions.options))

packages/jest-circus/src/__mocks__/testUtils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ interface Result extends ExecaSyncReturnValue {
3131
}
3232

3333
export const runTest = (source: string) => {
34-
const filename = createHash('sha256')
34+
const filename = createHash('sha1')
3535
.update(source)
3636
.digest('hex')
3737
.substring(0, 32);

packages/jest-config/src/__tests__/normalize.test.ts

+9-7
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ afterEach(() => {
7272

7373
it('picks an id based on the rootDir', async () => {
7474
const rootDir = '/root/path/foo';
75-
const expected = createHash('sha256')
75+
const expected = createHash('sha1')
7676
.update('/root/path/foo')
7777
.update(String(Infinity))
7878
.digest('hex')
@@ -1082,6 +1082,10 @@ describe('preset', () => {
10821082
jest.requireActual('./jest-preset.json'),
10831083
);
10841084

1085+
const errorMessage = semver.satisfies(process.versions.node, '<19.0.0')
1086+
? /Unexpected token } in JSON at position (104|110)[\s\S]* at /
1087+
: 'SyntaxError: Expected double-quoted property name in JSON at position 104';
1088+
10851089
await expect(
10861090
normalize(
10871091
{
@@ -1090,9 +1094,7 @@ describe('preset', () => {
10901094
},
10911095
{} as Config.Argv,
10921096
),
1093-
).rejects.toThrow(
1094-
/Unexpected token } in JSON at position (104|110)[\s\S]* at /,
1095-
);
1097+
).rejects.toThrow(errorMessage);
10961098
});
10971099

10981100
test('throws when preset evaluation throws type error', async () => {
@@ -1105,9 +1107,9 @@ describe('preset', () => {
11051107
{virtual: true},
11061108
);
11071109

1108-
const errorMessage = semver.satisfies(process.versions.node, '>=16.9.1')
1109-
? "TypeError: Cannot read properties of undefined (reading 'call')"
1110-
: /TypeError: Cannot read property 'call' of undefined[\s\S]* at /;
1110+
const errorMessage = semver.satisfies(process.versions.node, '<16.9.1')
1111+
? /TypeError: Cannot read property 'call' of undefined[\s\S]* at /
1112+
: "TypeError: Cannot read properties of undefined (reading 'call')";
11111113

11121114
await expect(
11131115
normalize(

packages/jest-config/src/normalize.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ const normalizeMissingOptions = (
301301
projectIndex: number,
302302
): Config.InitialOptionsWithRootDir => {
303303
if (!options.id) {
304-
options.id = createHash('sha256')
304+
options.id = createHash('sha1')
305305
.update(options.rootDir)
306306
// In case we load config from some path that has the same root dir
307307
.update(configPath || '')

packages/jest-create-cache-key-function/src/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ function getGlobalCacheKey(files: Array<string>, values: Array<string>) {
4949
]
5050
.reduce(
5151
(hash, chunk) => hash.update('\0', 'utf8').update(chunk || ''),
52-
createHash('sha256'),
52+
createHash('sha1'),
5353
)
5454
.digest('hex')
5555
.substring(0, 32);
@@ -62,7 +62,7 @@ function getCacheKeyFunction(globalCacheKey: string): GetCacheKeyFunction {
6262
const inferredOptions = options || configString;
6363
const {config, instrument} = inferredOptions;
6464

65-
return createHash('sha256')
65+
return createHash('sha1')
6666
.update(globalCacheKey)
6767
.update('\0', 'utf8')
6868
.update(sourceText)

packages/jest-diff/src/__tests__/diff.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const optionsCounts: DiffOptions = {
2020
};
2121

2222
// Use only in toBe assertions for edge case messages.
23-
const stripped = (a: unknown, b: unknown) => stripAnsi(diff(a, b) || '');
23+
const stripped = (a: unknown, b: unknown) => stripAnsi(diff(a, b) ?? '');
2424

2525
// Use in toBe assertions for comparison lines.
2626
const optionsBe: DiffOptions = {
@@ -62,7 +62,7 @@ describe('different types', () => {
6262
test(`'${String(a)}' and '${String(b)}'`, () => {
6363
expect(stripped(a, b)).toBe(
6464
' Comparing two different types of values. ' +
65-
`Expected ${typeA} but received ${typeB}.`,
65+
`Expected ${String(typeA)} but received ${String(typeB)}.`,
6666
);
6767
});
6868
});

packages/jest-environment-node/src/index.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ export default class NodeEnvironment implements JestEnvironment<Timer> {
9090
configurable: descriptor.configurable,
9191
enumerable: descriptor.enumerable,
9292
value: val,
93-
writable: descriptor.writable,
93+
writable:
94+
descriptor.writable === true ||
95+
// Node 19 makes performance non-readable. This is probably not the correct solution.
96+
nodeGlobalsKey === 'performance',
9497
});
9598
return val;
9699
},

packages/jest-globals/src/index.ts

+25
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ import type {
1616
MockedClass as JestMockedClass,
1717
MockedFunction as JestMockedFunction,
1818
MockedObject as JestMockedObject,
19+
Spied as JestSpied,
20+
SpiedClass as JestSpiedClass,
21+
SpiedFunction as JestSpiedFunction,
22+
SpiedGetter as JestSpiedGetter,
23+
SpiedSetter as JestSpiedSetter,
1924
UnknownFunction,
2025
} from 'jest-mock';
2126

@@ -58,6 +63,26 @@ declare namespace jest {
5863
* Wraps an object type with Jest mock type definitions.
5964
*/
6065
export type MockedObject<T extends object> = JestMockedObject<T>;
66+
/**
67+
* Constructs the type of a spied class or function.
68+
*/
69+
export type Spied<T extends ClassLike | FunctionLike> = JestSpied<T>;
70+
/**
71+
* Constructs the type of a spied class.
72+
*/
73+
export type SpiedClass<T extends ClassLike> = JestSpiedClass<T>;
74+
/**
75+
* Constructs the type of a spied function.
76+
*/
77+
export type SpiedFunction<T extends FunctionLike> = JestSpiedFunction<T>;
78+
/**
79+
* Constructs the type of a spied getter.
80+
*/
81+
export type SpiedGetter<T> = JestSpiedGetter<T>;
82+
/**
83+
* Constructs the type of a spied setter.
84+
*/
85+
export type SpiedSetter<T> = JestSpiedSetter<T>;
6186
}
6287

6388
export {jest};

packages/jest-haste-map/src/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ class HasteMap extends EventEmitter implements IHasteMap {
295295
}
296296

297297
private async setupCachePath(options: Options): Promise<void> {
298-
const rootDirHash = createHash('sha256')
298+
const rootDirHash = createHash('sha1')
299299
.update(options.rootDir)
300300
.digest('hex')
301301
.substring(0, 32);
@@ -344,7 +344,7 @@ class HasteMap extends EventEmitter implements IHasteMap {
344344
id: string,
345345
...extra: Array<string>
346346
): string {
347-
const hash = createHash('sha256').update(extra.join(''));
347+
const hash = createHash('sha1').update(extra.join(''));
348348
return path.join(
349349
tmpdir,
350350
`${id.replace(/\W/g, '-')}-${hash.digest('hex').substring(0, 32)}`,

0 commit comments

Comments
 (0)