File tree Expand file tree Collapse file tree 3 files changed +65
-0
lines changed Expand file tree Collapse file tree 3 files changed +65
-0
lines changed Original file line number Diff line number Diff line change @@ -43,6 +43,10 @@ interface ApolloCustomMatchers<R = void, T = {}> {
43
43
| ProfiledHook < any , any >
44
44
? ( count : number , options ?: NextRenderOptions ) => Promise < R >
45
45
: { error : "matcher needs to be called on a ProfiledComponent instance" } ;
46
+
47
+ toBeGarbageCollected : T extends WeakRef < any >
48
+ ? ( ) => Promise < R >
49
+ : { error : "matcher needs to be called on a WeakRef instance" } ;
46
50
}
47
51
48
52
declare global {
Original file line number Diff line number Diff line change @@ -2,10 +2,12 @@ import { expect } from "@jest/globals";
2
2
import { toMatchDocument } from "./toMatchDocument.js" ;
3
3
import { toHaveSuspenseCacheEntryUsing } from "./toHaveSuspenseCacheEntryUsing.js" ;
4
4
import { toRerender , toRenderExactlyTimes } from "./ProfiledComponent.js" ;
5
+ import { toBeGarbageCollected } from "./toBeGarbageCollected.js" ;
5
6
6
7
expect . extend ( {
7
8
toHaveSuspenseCacheEntryUsing,
8
9
toMatchDocument,
9
10
toRerender,
10
11
toRenderExactlyTimes,
12
+ toBeGarbageCollected,
11
13
} ) ;
Original file line number Diff line number Diff line change
1
+ import type { MatcherFunction } from "expect" ;
2
+
3
+ // this is necessary because this file is picked up by `tsc` (it's not a test),
4
+ // but our main `tsconfig.json` doesn't include `"ES2021.WeakRef"` on purpose
5
+ declare class WeakRef < T extends WeakKey > {
6
+ constructor ( target : T ) ;
7
+ deref ( ) : T | undefined ;
8
+ }
9
+
10
+ export const toBeGarbageCollected : MatcherFunction < [ weakRef : WeakRef < any > ] > =
11
+ async function ( actual ) {
12
+ const hint = this . utils . matcherHint ( "toBeGarbageCollected" ) ;
13
+
14
+ if ( ! ( actual instanceof WeakRef ) ) {
15
+ throw new Error (
16
+ hint +
17
+ "\n\n" +
18
+ `Expected value to be a WeakRef, but it was a ${ typeof actual } .`
19
+ ) ;
20
+ }
21
+
22
+ let pass = false ;
23
+ let interval : NodeJS . Timeout | undefined ;
24
+ let timeout : NodeJS . Timeout | undefined ;
25
+ await Promise . race ( [
26
+ new Promise < void > ( ( resolve ) => {
27
+ timeout = setTimeout ( resolve , 1000 ) ;
28
+ } ) ,
29
+ new Promise < void > ( ( resolve ) => {
30
+ interval = setInterval ( ( ) => {
31
+ global . gc ! ( ) ;
32
+ pass = actual . deref ( ) === undefined ;
33
+ if ( pass ) {
34
+ resolve ( ) ;
35
+ }
36
+ } , 1 ) ;
37
+ } ) ,
38
+ ] ) ;
39
+
40
+ clearInterval ( interval ) ;
41
+ clearTimeout ( timeout ) ;
42
+
43
+ return {
44
+ pass,
45
+ message : ( ) => {
46
+ if ( pass ) {
47
+ return (
48
+ hint +
49
+ "\n\n" +
50
+ "Expected value to not be cache-collected, but it was."
51
+ ) ;
52
+ }
53
+
54
+ return (
55
+ hint + "\n\n Expected value to be cache-collected, but it was not."
56
+ ) ;
57
+ } ,
58
+ } ;
59
+ } ;
You can’t perform that action at this time.
0 commit comments