Skip to content

Commit 06038a2

Browse files
committed
Merge branch 'main' into webpack-bundle-jest
2 parents 70e26d2 + e2326fa commit 06038a2

File tree

10 files changed

+91
-56
lines changed

10 files changed

+91
-56
lines changed

.eslintrc.cjs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,7 @@ module.exports = {
4040
},
4141
overrides: [
4242
{
43-
extends: [
44-
'plugin:@typescript-eslint/recommended',
45-
'plugin:import/typescript',
46-
],
43+
extends: ['plugin:@typescript-eslint/strict', 'plugin:import/typescript'],
4744
files: ['*.ts', '*.tsx'],
4845
plugins: ['@typescript-eslint/eslint-plugin', 'local'],
4946
rules: {
@@ -60,9 +57,11 @@ module.exports = {
6057
'consistent-return': 'off',
6158
'no-dupe-class-members': 'off',
6259
'no-unused-vars': 'off',
60+
'@typescript-eslint/no-dynamic-delete': 'off',
6361
// TODO: enable at some point
6462
'@typescript-eslint/no-explicit-any': 'off',
6563
'@typescript-eslint/no-non-null-assertion': 'off',
64+
'@typescript-eslint/no-invalid-void-type': 'off',
6665

6766
// TODO: part of "stylistic" rules, remove explicit activation when that lands
6867
'@typescript-eslint/no-empty-function': 'error',
@@ -350,6 +349,8 @@ module.exports = {
350349
files: ['**/__typetests__/**'],
351350
rules: {
352351
'@typescript-eslint/no-empty-function': 'off',
352+
'@typescript-eslint/no-invalid-void-type': 'off',
353+
'@typescript-eslint/no-useless-constructor': 'off',
353354
},
354355
},
355356
{
@@ -377,6 +378,7 @@ module.exports = {
377378
'**/__typetests__/**',
378379
],
379380
rules: {
381+
'@typescript-eslint/no-extraneous-class': 'off',
380382
'@typescript-eslint/no-unused-vars': 'off',
381383
'import/no-unresolved': 'off',
382384
'no-console': 'off',

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
### Features
44

5+
- `[@jest/core]` [**BREAKING**] Group together open handles with the same stack trace ([#13417](https://github.com/jestjs/jest/pull/13417), & [#14543](https://github.com/jestjs/jest/pull/14543))
56
- `[@jest/core, @jest/test-sequencer]` [**BREAKING**] Exposes `globalConfig` & `contexts` to `TestSequencer` ([#14535](https://github.com/jestjs/jest/pull/14535), & [#14543](https://github.com/jestjs/jest/pull/14543))
67
- `[jest-environment-jsdom]` [**BREAKING**] Upgrade JSDOM to v22 ([#13825](https://github.com/jestjs/jest/pull/13825))
78
- `[@jest/fake-timers]` [**BREAKING**] Upgrade `@sinonjs/fake-timers` to v11 ([#14544](https://github.com/jestjs/jest/pull/14544))
9+
- `[@jest/schemas]` Upgrade `@sinclair/typebox` to v0.31 ([#14072](https://github.com/jestjs/jest/pull/14072))
810
- `[pretty-format]` [**BREAKING**] Do not render empty string children (`''`) in React plugin ([#14470](https://github.com/facebook/jest/pull/14470))
911

1012
### Fixes

e2e/__tests__/__snapshots__/detectOpenHandles.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ exports[`prints message about flag on slow tests with a custom timeout 1`] = `
1919
exports[`prints out info about open handlers 1`] = `
2020
"Jest has detected the following 1 open handle potentially keeping Jest from exiting:
2121
22-
● TCPSERVERWRAP
22+
DNSCHANNEL,TCPSERVERWRAP
2323
2424
12 | const app = new Server();
2525
13 |

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
"typescript": "^5.0.4",
8484
"webpack": "^5.68.0",
8585
"webpack-node-externals": "^3.0.0",
86-
"which": "^3.0.0"
86+
"which": "^4.0.0"
8787
},
8888
"scripts": {
8989
"build-clean": "rimraf --glob './packages/*/build' './packages/*/dist' './packages/*/tsconfig.tsbuildinfo' './packages/*/api-extractor.json' './api-extractor.json'",

packages/jest-core/src/__tests__/collectHandles.test.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,28 @@ describe('collectHandles', () => {
3131

3232
it('should not collect the PerformanceObserver open handle', async () => {
3333
const handleCollector = collectHandles();
34-
const obs = new PerformanceObserver((list, observer) => {});
34+
35+
let obs = new PerformanceObserver((list, observer) => {});
3536
obs.observe({entryTypes: ['mark']});
37+
obs.disconnect();
38+
obs = null;
3639

3740
const openHandles = await handleCollector();
3841

3942
expect(openHandles).not.toContainEqual(
4043
expect.objectContaining({message: 'PerformanceObserver'}),
4144
);
42-
obs.disconnect();
4345
});
4446

4547
it('should not collect the DNSCHANNEL open handle', async () => {
4648
const handleCollector = collectHandles();
4749

48-
const resolver = new dns.Resolver();
50+
let resolver = new dns.Resolver();
4951
resolver.getServers();
5052

53+
// We must drop references to it
54+
resolver = null;
55+
5156
const openHandles = await handleCollector();
5257

5358
expect(openHandles).not.toContainEqual(

packages/jest-core/src/collectHandles.ts

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,7 @@ export default function collectHandles(): HandleCollectionResult {
8383
// Skip resources that should not generally prevent the process from
8484
// exiting, not last a meaningfully long time, or otherwise shouldn't be
8585
// tracked.
86-
if (
87-
type === 'PROMISE' ||
88-
type === 'TIMERWRAP' ||
89-
type === 'ELDHISTOGRAM' ||
90-
type === 'PerformanceObserver' ||
91-
type === 'RANDOMBYTESREQUEST' ||
92-
type === 'DNSCHANNEL' ||
93-
type === 'ZLIB' ||
94-
type === 'SIGNREQUEST'
95-
) {
86+
if (type === 'PROMISE') {
9687
return;
9788
}
9889
const error = new ErrorWithStack(type, initHook, 100);
@@ -141,14 +132,18 @@ export default function collectHandles(): HandleCollectionResult {
141132
// For example, Node.js TCP Servers are not destroyed until *after* their
142133
// `close` callback runs. If someone finishes a test from the `close`
143134
// callback, we will not yet have seen the resource be destroyed here.
144-
await asyncSleep(100);
135+
await asyncSleep(0);
145136

146137
if (activeHandles.size > 0) {
147-
// For some special objects such as `TLSWRAP`.
148-
// Ref: https://github.com/jestjs/jest/issues/11665
149-
runGC();
138+
await asyncSleep(30);
150139

151-
await asyncSleep(0);
140+
if (activeHandles.size > 0) {
141+
// For some special objects such as `TLSWRAP`.
142+
// Ref: https://github.com/jestjs/jest/issues/11665
143+
runGC();
144+
145+
await asyncSleep(0);
146+
}
152147
}
153148

154149
hook.disable();
@@ -167,33 +162,44 @@ export function formatHandleErrors(
167162
errors: Array<Error>,
168163
config: Config.ProjectConfig,
169164
): Array<string> {
170-
const stacks = new Set();
171-
172-
return (
173-
errors
174-
.map(err =>
175-
formatExecError(err, config, {noStackTrace: false}, undefined, true),
176-
)
177-
// E.g. timeouts might give multiple traces to the same line of code
178-
// This hairy filtering tries to remove entries with duplicate stack traces
179-
.filter(handle => {
180-
const ansiFree: string = stripAnsi(handle);
181-
182-
const match = ansiFree.match(/\s+at(.*)/);
183-
184-
if (!match || match.length < 2) {
185-
return true;
186-
}
165+
const stacks = new Map<string, {stack: string; names: Set<string>}>();
166+
167+
for (const err of errors) {
168+
const formatted = formatExecError(
169+
err,
170+
config,
171+
{noStackTrace: false},
172+
undefined,
173+
true,
174+
);
187175

188-
const stack = ansiFree.substr(ansiFree.indexOf(match[1])).trim();
176+
// E.g. timeouts might give multiple traces to the same line of code
177+
// This hairy filtering tries to remove entries with duplicate stack traces
189178

190-
if (stacks.has(stack)) {
191-
return false;
192-
}
179+
const ansiFree: string = stripAnsi(formatted);
180+
const match = ansiFree.match(/\s+at(.*)/);
181+
if (!match || match.length < 2) {
182+
continue;
183+
}
193184

194-
stacks.add(stack);
185+
const stackText = ansiFree.slice(ansiFree.indexOf(match[1])).trim();
186+
187+
const name = ansiFree.match(/(?<= {2}).*$/m);
188+
if (name == null || name.length === 0) {
189+
continue;
190+
}
191+
192+
const stack = stacks.get(stackText) || {
193+
names: new Set(),
194+
stack: formatted.replace(name[0], '%%OBJECT_NAME%%'),
195+
};
196+
197+
stack.names.add(name[0]);
198+
199+
stacks.set(stackText, stack);
200+
}
195201

196-
return true;
197-
})
202+
return Array.from(stacks.values()).map(({stack, names}) =>
203+
stack.replace('%%OBJECT_NAME%%', Array.from(names).join(',')),
198204
);
199205
}

packages/jest-mock/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,7 @@ export class ModuleMocker {
605605
};
606606
}
607607

608+
/* eslint-disable @typescript-eslint/unified-signatures */
608609
private _makeComponent<T extends Record<string, any>>(
609610
metadata: MockMetadata<T, 'object'>,
610611
restore?: () => void,
@@ -625,6 +626,7 @@ export class ModuleMocker {
625626
metadata: MockMetadata<T, 'function'>,
626627
restore?: () => void,
627628
): Mock<T>;
629+
/* eslint-enable @typescript-eslint/unified-signatures */
628630
private _makeComponent<T extends UnknownFunction>(
629631
metadata: MockMetadata<T>,
630632
restore?: () => void,

packages/jest-schemas/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"./package.json": "./package.json"
1818
},
1919
"dependencies": {
20-
"@sinclair/typebox": "^0.27.8"
20+
"@sinclair/typebox": "^0.31.0"
2121
},
2222
"engines": {
2323
"node": "^16.10.0 || ^18.12.0 || >=20.0.0"

packages/jest-test-sequencer/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ type ShardPositionOptions = ShardOptions & {
5252
export default class TestSequencer {
5353
private readonly _cache = new Map<TestContext, Cache>();
5454

55-
// eslint-disable-next-line @typescript-eslint/no-empty-function
55+
// eslint-disable-next-line @typescript-eslint/no-empty-function,@typescript-eslint/no-useless-constructor
5656
constructor(_options: TestSequencerOptions) {}
5757

5858
_getCachePath(testContext: TestContext): string {

yarn.lock

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3002,7 +3002,7 @@ __metadata:
30023002
typescript: ^5.0.4
30033003
webpack: ^5.68.0
30043004
webpack-node-externals: ^3.0.0
3005-
which: ^3.0.0
3005+
which: ^4.0.0
30063006
languageName: unknown
30073007
linkType: soft
30083008

@@ -3061,7 +3061,7 @@ __metadata:
30613061
version: 0.0.0-use.local
30623062
resolution: "@jest/schemas@workspace:packages/jest-schemas"
30633063
dependencies:
3064-
"@sinclair/typebox": ^0.27.8
3064+
"@sinclair/typebox": ^0.31.0
30653065
languageName: unknown
30663066
linkType: soft
30673067

@@ -4322,10 +4322,10 @@ __metadata:
43224322
languageName: node
43234323
linkType: hard
43244324

4325-
"@sinclair/typebox@npm:^0.27.8":
4326-
version: 0.27.8
4327-
resolution: "@sinclair/typebox@npm:0.27.8"
4328-
checksum: 00bd7362a3439021aa1ea51b0e0d0a0e8ca1351a3d54c606b115fdcc49b51b16db6e5f43b4fe7a28c38688523e22a94d49dd31168868b655f0d4d50f032d07a1
4325+
"@sinclair/typebox@npm:^0.31.0":
4326+
version: 0.31.15
4327+
resolution: "@sinclair/typebox@npm:0.31.15"
4328+
checksum: 5dea8975a5a7b124252baf61c5a6871b1efc28f61550427335b0a3d522ff80db350fbda21c5a0dc69d5620ddfb9f38ccf492f0ec83b7478898f08b97d46ed387
43294329
languageName: node
43304330
linkType: hard
43314331

@@ -12359,6 +12359,13 @@ __metadata:
1235912359
languageName: node
1236012360
linkType: hard
1236112361

12362+
"isexe@npm:^3.1.1":
12363+
version: 3.1.1
12364+
resolution: "isexe@npm:3.1.1"
12365+
checksum: 7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e
12366+
languageName: node
12367+
linkType: hard
12368+
1236212369
"isobject@npm:^3.0.1":
1236312370
version: 3.0.1
1236412371
resolution: "isobject@npm:3.0.1"
@@ -21261,6 +21268,17 @@ __metadata:
2126121268
languageName: node
2126221269
linkType: hard
2126321270

21271+
"which@npm:^4.0.0":
21272+
version: 4.0.0
21273+
resolution: "which@npm:4.0.0"
21274+
dependencies:
21275+
isexe: ^3.1.1
21276+
bin:
21277+
node-which: bin/which.js
21278+
checksum: f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651
21279+
languageName: node
21280+
linkType: hard
21281+
2126421282
"wide-align@npm:^1.1.5":
2126521283
version: 1.1.5
2126621284
resolution: "wide-align@npm:1.1.5"

0 commit comments

Comments
 (0)