Skip to content

Commit

Permalink
Merge branch 'main' into defer-cache-dir-creation
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB committed Oct 18, 2022
2 parents e9cc370 + e61ea77 commit 2947bcf
Show file tree
Hide file tree
Showing 119 changed files with 1,333 additions and 1,042 deletions.
23 changes: 20 additions & 3 deletions .github/workflows/nodejs.yml
Expand Up @@ -112,6 +112,25 @@ jobs:
with:
os: windows-latest

test-leak:
name: Node LTS on Ubuntu with leak detection
runs-on: ubuntu-latest
needs: prepare-yarn-cache-ubuntu

steps:
- uses: actions/checkout@v3
- name: Use Node.js LTS
uses: actions/setup-node@v3
with:
node-version: lts/*
cache: yarn
- name: install
run: yarn --immutable
- name: build
run: yarn build:js
- name: run tests with leak detection
run: yarn test-leak

test-coverage:
name: Node LTS on Ubuntu with coverage (${{ matrix.shard }})
strategy:
Expand All @@ -136,9 +155,7 @@ jobs:
id: cpu-cores
uses: SimenB/github-actions-cpu-cores@v1
- name: run tests with coverage
run: |
yarn jest-coverage --color --config jest.config.ci.mjs --max-workers ${{ steps.cpu-cores.outputs.count }} --shard=${{ matrix.shard }}
yarn test-leak
run: yarn jest-coverage --color --config jest.config.ci.mjs --max-workers ${{ steps.cpu-cores.outputs.count }} --shard=${{ matrix.shard }}
- name: map coverage
run: node ./scripts/mapCoverage.mjs
if: always()
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,12 +2,17 @@

### Features

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

### Fixes

- `[jest-environment-node]` make `globalThis.performance` writable for Node 19 and fake timers ([#13467](https://github.com/facebook/jest/pull/13467))

### Chore & Maintenance

### Performance

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

## 29.2.0
Expand Down
4 changes: 4 additions & 0 deletions docs/JestObjectAPI.md
Expand Up @@ -699,6 +699,10 @@ test('plays audio', () => {
});
```

### `jest.Spied<Source>`

See [TypeScript Usage](MockFunctionAPI.md#jestspiedsource) chapter of Mock Functions page for documentation.

### `jest.clearAllMocks()`

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.
Expand Down
34 changes: 34 additions & 0 deletions docs/MockFunctionAPI.md
Expand Up @@ -644,3 +644,37 @@ test('direct usage', () => {
expect(jest.mocked(console.log).mock.calls).toHaveLength(1);
});
```

### `jest.Spied<Source>`

Constructs the type of a spied class or function (i.e. the return type of `jest.spyOn()`).

```ts title="__utils__/setDateNow.ts"
import {jest} from '@jest/globals';

export function setDateNow(now: number): jest.Spied<typeof Date.now> {
return jest.spyOn(Date, 'now').mockReturnValue(now);
}
```

```ts
import {afterEach, expect, jest, test} from '@jest/globals';
import {setDateNow} from './__utils__/setDateNow';

let spiedDateNow: jest.Spied<typeof Date.now> | undefined = undefined;

afterEach(() => {
spiedDateNow?.mockReset();
});

test('renders correctly with a given date', () => {
spiedDateNow = setDateNow(1482363367071);
// ...

expect(spiedDateNow).toHaveBeenCalledTimes(1);
});
```

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>`.

Use `jest.SpiedGetter<Source>` or `jest.SpiedSetter<Source>` to create the type of a spied getter or setter respectively.
1 change: 0 additions & 1 deletion jest.config.mjs
Expand Up @@ -63,7 +63,6 @@ export default {
'/packages/jest-runtime/src/__tests__/NODE_PATH_dir',
'/packages/jest-snapshot/src/__tests__/plugins',
'/packages/jest-snapshot/src/__tests__/fixtures/',
'/packages/jest-validate/src/__tests__/fixtures/',
'/e2e/__tests__/iterator-to-null-test.ts',
'/e2e/__tests__/tsIntegration.test.ts', // this test needs types to be build, it runs in a separate CI job through `jest.config.ts.mjs`
],
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -113,7 +113,7 @@
"test": "yarn lint && yarn jest",
"typecheck": "yarn typecheck:examples && yarn typecheck:tests",
"typecheck:examples": "tsc -p examples/angular --noEmit && tsc -p examples/expect-extend --noEmit && tsc -p examples/typescript --noEmit",
"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__",
"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__",
"verify-old-ts": "node ./scripts/verifyOldTs.mjs",
"verify-pnp": "node ./scripts/verifyPnP.mjs",
"watch": "yarn build:js && node ./scripts/watch.mjs",
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-jest/src/index.ts
Expand Up @@ -78,7 +78,7 @@ function getCacheKeyFromConfig(

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

return createHash('sha256')
return createHash('sha1')
.update(THIS_FILE)
.update('\0', 'utf8')
.update(JSON.stringify(babelOptions.options))
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-circus/src/__mocks__/testUtils.ts
Expand Up @@ -31,7 +31,7 @@ interface Result extends ExecaSyncReturnValue {
}

export const runTest = (source: string) => {
const filename = createHash('sha256')
const filename = createHash('sha1')
.update(source)
.digest('hex')
.substring(0, 32);
Expand Down
16 changes: 9 additions & 7 deletions packages/jest-config/src/__tests__/normalize.test.ts
Expand Up @@ -72,7 +72,7 @@ afterEach(() => {

it('picks an id based on the rootDir', async () => {
const rootDir = '/root/path/foo';
const expected = createHash('sha256')
const expected = createHash('sha1')
.update('/root/path/foo')
.update(String(Infinity))
.digest('hex')
Expand Down Expand Up @@ -1082,6 +1082,10 @@ describe('preset', () => {
jest.requireActual('./jest-preset.json'),
);

const errorMessage = semver.satisfies(process.versions.node, '<19.0.0')
? /Unexpected token } in JSON at position (104|110)[\s\S]* at /
: 'SyntaxError: Expected double-quoted property name in JSON at position 104';

await expect(
normalize(
{
Expand All @@ -1090,9 +1094,7 @@ describe('preset', () => {
},
{} as Config.Argv,
),
).rejects.toThrow(
/Unexpected token } in JSON at position (104|110)[\s\S]* at /,
);
).rejects.toThrow(errorMessage);
});

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

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

await expect(
normalize(
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-config/src/normalize.ts
Expand Up @@ -301,7 +301,7 @@ const normalizeMissingOptions = (
projectIndex: number,
): Config.InitialOptionsWithRootDir => {
if (!options.id) {
options.id = createHash('sha256')
options.id = createHash('sha1')
.update(options.rootDir)
// In case we load config from some path that has the same root dir
.update(configPath || '')
Expand Down
4 changes: 2 additions & 2 deletions packages/jest-create-cache-key-function/src/index.ts
Expand Up @@ -49,7 +49,7 @@ function getGlobalCacheKey(files: Array<string>, values: Array<string>) {
]
.reduce(
(hash, chunk) => hash.update('\0', 'utf8').update(chunk || ''),
createHash('sha256'),
createHash('sha1'),
)
.digest('hex')
.substring(0, 32);
Expand All @@ -62,7 +62,7 @@ function getCacheKeyFunction(globalCacheKey: string): GetCacheKeyFunction {
const inferredOptions = options || configString;
const {config, instrument} = inferredOptions;

return createHash('sha256')
return createHash('sha1')
.update(globalCacheKey)
.update('\0', 'utf8')
.update(sourceText)
Expand Down
4 changes: 2 additions & 2 deletions packages/jest-diff/src/__tests__/diff.test.ts
Expand Up @@ -20,7 +20,7 @@ const optionsCounts: DiffOptions = {
};

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

// Use in toBe assertions for comparison lines.
const optionsBe: DiffOptions = {
Expand Down Expand Up @@ -62,7 +62,7 @@ describe('different types', () => {
test(`'${String(a)}' and '${String(b)}'`, () => {
expect(stripped(a, b)).toBe(
' Comparing two different types of values. ' +
`Expected ${typeA} but received ${typeB}.`,
`Expected ${String(typeA)} but received ${String(typeB)}.`,
);
});
});
Expand Down
5 changes: 4 additions & 1 deletion packages/jest-environment-node/src/index.ts
Expand Up @@ -90,7 +90,10 @@ export default class NodeEnvironment implements JestEnvironment<Timer> {
configurable: descriptor.configurable,
enumerable: descriptor.enumerable,
value: val,
writable: descriptor.writable,
writable:
descriptor.writable === true ||
// Node 19 makes performance non-readable. This is probably not the correct solution.
nodeGlobalsKey === 'performance',
});
return val;
},
Expand Down
25 changes: 25 additions & 0 deletions packages/jest-globals/src/index.ts
Expand Up @@ -16,6 +16,11 @@ import type {
MockedClass as JestMockedClass,
MockedFunction as JestMockedFunction,
MockedObject as JestMockedObject,
Spied as JestSpied,
SpiedClass as JestSpiedClass,
SpiedFunction as JestSpiedFunction,
SpiedGetter as JestSpiedGetter,
SpiedSetter as JestSpiedSetter,
UnknownFunction,
} from 'jest-mock';

Expand Down Expand Up @@ -58,6 +63,26 @@ declare namespace jest {
* Wraps an object type with Jest mock type definitions.
*/
export type MockedObject<T extends object> = JestMockedObject<T>;
/**
* Constructs the type of a spied class or function.
*/
export type Spied<T extends ClassLike | FunctionLike> = JestSpied<T>;
/**
* Constructs the type of a spied class.
*/
export type SpiedClass<T extends ClassLike> = JestSpiedClass<T>;
/**
* Constructs the type of a spied function.
*/
export type SpiedFunction<T extends FunctionLike> = JestSpiedFunction<T>;
/**
* Constructs the type of a spied getter.
*/
export type SpiedGetter<T> = JestSpiedGetter<T>;
/**
* Constructs the type of a spied setter.
*/
export type SpiedSetter<T> = JestSpiedSetter<T>;
}

export {jest};
Expand Down
4 changes: 2 additions & 2 deletions packages/jest-haste-map/src/index.ts
Expand Up @@ -295,7 +295,7 @@ class HasteMap extends EventEmitter implements IHasteMap {
}

private async setupCachePath(options: Options): Promise<void> {
const rootDirHash = createHash('sha256')
const rootDirHash = createHash('sha1')
.update(options.rootDir)
.digest('hex')
.substring(0, 32);
Expand Down Expand Up @@ -344,7 +344,7 @@ class HasteMap extends EventEmitter implements IHasteMap {
id: string,
...extra: Array<string>
): string {
const hash = createHash('sha256').update(extra.join(''));
const hash = createHash('sha1').update(extra.join(''));
return path.join(
tmpdir,
`${id.replace(/\W/g, '-')}-${hash.digest('hex').substring(0, 32)}`,
Expand Down

0 comments on commit 2947bcf

Please sign in to comment.