Skip to content

Commit a923b06

Browse files
Run tests with React 19 RC.1 and adjust tests accordingly (#12140)
Co-authored-by: Jerel Miller <jerelmiller@gmail.com>
1 parent bc7ca1e commit a923b06

38 files changed

Lines changed: 2213 additions & 1702 deletions

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ workflows:
173173
- "@types/react@16.8 @types/react-dom@16.8"
174174
- "@types/react@17 @types/react-dom@17"
175175
- "@types/react@18 @types/react-dom@18"
176-
- "@types/react@npm:types-react@19.0.0-rc.0 @types/react-dom@npm:types-react-dom@19.0.0-rc.0"
176+
- "@types/react@npm:types-react@19.0.0-rc.1 @types/react-dom@npm:types-react-dom@19.0.0-rc.1"
177177
- "typescript@next"
178178
security-scans:
179179
jobs:

.eslintrc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,10 @@
8989
"rules": {
9090
"testing-library/prefer-user-event": "error",
9191
"testing-library/no-wait-for-multiple-assertions": "off",
92-
"local-rules/require-using-disposable": "error"
92+
"local-rules/require-using-disposable": "error",
93+
"local-rules/require-disable-act-environment": "error",
94+
"local-rules/forbid-act-in-disabled-act-environment": "error",
95+
"@typescript-eslint/no-floating-promises": "warn"
9396
}
9497
}
9598
],

config/jest.config.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ const standardReact17Config = {
8585
"^react-dom$": "react-dom-17",
8686
"^react-dom/server$": "react-dom-17/server",
8787
"^react-dom/test-utils$": "react-dom-17/test-utils",
88-
"^@testing-library/react$": "@testing-library/react-12",
8988
},
9089
};
9190

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { rule } from "./forbid-act-in-disabled-act-environment";
2+
import { ruleTester } from "./testSetup";
3+
4+
ruleTester.run("forbid-act-in-disabled-act-environment", rule, {
5+
valid: [
6+
`
7+
() => {
8+
using _disabledAct = disableActEnvironment();
9+
}
10+
() => {
11+
act(() => {})
12+
}
13+
`,
14+
`
15+
() => {
16+
using _disabledAct = disableActEnvironment();
17+
}
18+
() => {
19+
actAsync(() => {})
20+
}
21+
`,
22+
],
23+
invalid: [
24+
`
25+
() => {
26+
using _disabledAct = disableActEnvironment();
27+
act(() => {})
28+
}
29+
`,
30+
`
31+
() => {
32+
using _disabledAct = disableActEnvironment();
33+
actAsync(() => {})
34+
}
35+
`,
36+
`
37+
() => {
38+
using _disabledAct = disableActEnvironment();
39+
() => {
40+
act(() => {})
41+
}
42+
}
43+
`,
44+
`
45+
() => {
46+
using _disabledAct = disableActEnvironment();
47+
() => {
48+
actAsync(() => {})
49+
}
50+
}
51+
`,
52+
].map((code) => ({
53+
code,
54+
errors: [{ messageId: "forbiddenActInNonActEnvironment" }],
55+
})),
56+
});
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { ESLintUtils } from "@typescript-eslint/utils";
2+
3+
export const rule = ESLintUtils.RuleCreator.withoutDocs({
4+
create(context) {
5+
let depth = 1;
6+
let disabledDepth: number | false = false;
7+
8+
function EnterFn() {
9+
depth++;
10+
}
11+
function ExitFn() {
12+
depth--;
13+
if (disabledDepth !== false && disabledDepth > depth) {
14+
disabledDepth = false;
15+
}
16+
}
17+
18+
return {
19+
CallExpression(node) {
20+
const directCallee =
21+
node.callee.type === "Identifier" ? node.callee
22+
: node.callee.type === "MemberExpression" ? node.callee.property
23+
: null;
24+
25+
if (
26+
directCallee?.type === "Identifier" &&
27+
directCallee.name === "disableActEnvironment"
28+
) {
29+
if (disabledDepth === false) {
30+
disabledDepth = depth;
31+
}
32+
}
33+
34+
if (
35+
directCallee?.type === "Identifier" &&
36+
(directCallee.name === "act" || directCallee.name === "actAsync")
37+
) {
38+
if (disabledDepth !== false) {
39+
context.report({
40+
messageId: "forbiddenActInNonActEnvironment",
41+
node: node,
42+
});
43+
}
44+
}
45+
},
46+
ArrowFunctionExpression: EnterFn,
47+
FunctionExpression: EnterFn,
48+
FunctionDeclaration: EnterFn,
49+
"ArrowFunctionExpression:exit": ExitFn,
50+
"FunctionExpression:exit": ExitFn,
51+
"FunctionDeclaration:exit": ExitFn,
52+
};
53+
},
54+
meta: {
55+
messages: {
56+
forbiddenActInNonActEnvironment:
57+
"`act` should not be called in a `disableActEnvironment`.",
58+
},
59+
type: "problem",
60+
schema: [],
61+
},
62+
defaultOptions: [],
63+
});

eslint-local-rules/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,8 @@ require("ts-node").register({
1111

1212
module.exports = {
1313
"require-using-disposable": require("./require-using-disposable").rule,
14+
"require-disable-act-environment":
15+
require("./require-disable-act-environment").rule,
16+
"forbid-act-in-disabled-act-environment":
17+
require("./forbid-act-in-disabled-act-environment").rule,
1418
};
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import { rule } from "./require-disable-act-environment";
2+
import { ruleTester } from "./testSetup";
3+
4+
ruleTester.run("require-disable-act-environment", rule, {
5+
valid: [
6+
`
7+
() => {
8+
using _disabledAct = disableActEnvironment();
9+
const { takeRender } = someCall()
10+
const {} = takeRender()
11+
}
12+
`,
13+
`
14+
() => {
15+
using _disabledAct = disableActEnvironment();
16+
const {} = renderStream.takeRender()
17+
}
18+
`,
19+
`
20+
() => {
21+
using _disabledAct = disableActEnvironment();
22+
const { takeSnapshot } = someCall()
23+
const {} = takeSnapshot()
24+
}
25+
`,
26+
`
27+
() => {
28+
using _disabledAct = disableActEnvironment();
29+
const {} = renderStream.takeSnapshot()
30+
}
31+
`,
32+
`
33+
using _disabledAct = disableActEnvironment();
34+
() => {
35+
const { takeRender } = someCall()
36+
const {} = takeRender()
37+
}
38+
`,
39+
`
40+
using _disabledAct = disableActEnvironment();
41+
() => {
42+
const {} = renderStream.takeRender()
43+
}
44+
`,
45+
`
46+
using _disabledAct = disableActEnvironment();
47+
() => {
48+
const { takeSnapshot } = someCall()
49+
const {} = takeSnapshot()
50+
}
51+
`,
52+
`
53+
using _disabledAct = disableActEnvironment();
54+
() => {
55+
const {} = renderStream.takeSnapshot()
56+
}
57+
`,
58+
],
59+
invalid: [
60+
`
61+
() => {
62+
using _disabledAct = disableActEnvironment();
63+
}
64+
() => {
65+
const { takeRender } = someCall()
66+
takeRender()
67+
}
68+
`,
69+
`
70+
() => {
71+
using _disabledAct = disableActEnvironment();
72+
}
73+
() => {
74+
renderStream.takeRender()
75+
}
76+
`,
77+
`
78+
() => {
79+
using _disabledAct = disableActEnvironment();
80+
}
81+
() => {
82+
const { takeSnapshot } = someCall()
83+
takeSnapshot()
84+
}
85+
`,
86+
`
87+
() => {
88+
using _disabledAct = disableActEnvironment();
89+
}
90+
() => {
91+
renderStream.takeSnapshot()
92+
}
93+
`,
94+
`
95+
() => {
96+
const { takeRender } = someCall()
97+
takeRender()
98+
}
99+
`,
100+
`
101+
() => {
102+
renderStream.takeRender()
103+
}
104+
`,
105+
`
106+
() => {
107+
const { takeSnapshot } = someCall()
108+
takeSnapshot()
109+
}
110+
`,
111+
`
112+
() => {
113+
renderStream.takeSnapshot()
114+
}
115+
`,
116+
].map((code) => ({
117+
code,
118+
errors: [{ messageId: "missingDisableActEnvironment" }],
119+
})),
120+
});
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { ESLintUtils, ASTUtils } from "@typescript-eslint/utils";
2+
import type { TSESTree as AST } from "@typescript-eslint/types";
3+
4+
type Fn =
5+
| AST.FunctionDeclaration
6+
| AST.ArrowFunctionExpression
7+
| AST.FunctionExpression;
8+
9+
export const rule = ESLintUtils.RuleCreator.withoutDocs({
10+
create(context) {
11+
let depth = 1;
12+
let disabledDepth: number | false = false;
13+
14+
function EnterFn() {
15+
depth++;
16+
}
17+
function ExitFn() {
18+
depth--;
19+
if (disabledDepth !== false && disabledDepth > depth) {
20+
disabledDepth = false;
21+
}
22+
}
23+
24+
return {
25+
CallExpression(node) {
26+
const directCallee =
27+
node.callee.type === "Identifier" ? node.callee
28+
: node.callee.type === "MemberExpression" ? node.callee.property
29+
: null;
30+
31+
if (
32+
directCallee?.type === "Identifier" &&
33+
directCallee.name === "disableActEnvironment"
34+
) {
35+
if (disabledDepth === false) {
36+
disabledDepth = depth;
37+
}
38+
}
39+
40+
if (
41+
directCallee?.type === "Identifier" &&
42+
(directCallee.name === "takeRender" ||
43+
directCallee.name === "takeSnapshot")
44+
) {
45+
if (disabledDepth === false) {
46+
context.report({
47+
messageId: "missingDisableActEnvironment",
48+
node: node,
49+
});
50+
}
51+
}
52+
},
53+
ArrowFunctionExpression: EnterFn,
54+
FunctionExpression: EnterFn,
55+
FunctionDeclaration: EnterFn,
56+
"ArrowFunctionExpression:exit": ExitFn,
57+
"FunctionExpression:exit": ExitFn,
58+
"FunctionDeclaration:exit": ExitFn,
59+
};
60+
},
61+
meta: {
62+
messages: {
63+
missingDisableActEnvironment:
64+
"Tests using a render stream should call `disableActEnvironment`.",
65+
},
66+
type: "problem",
67+
schema: [],
68+
},
69+
defaultOptions: [],
70+
});
71+
72+
function findParentFunction(node: AST.Node): Fn | undefined {
73+
let parentFunction: AST.Node | undefined = node;
74+
while (
75+
parentFunction != null &&
76+
parentFunction.type !== "FunctionDeclaration" &&
77+
parentFunction.type !== "FunctionExpression" &&
78+
parentFunction.type !== "ArrowFunctionExpression"
79+
) {
80+
parentFunction = parentFunction.parent;
81+
}
82+
return parentFunction;
83+
}

0 commit comments

Comments
 (0)