@samitouri / QOS-React-2 / commits / fce15f14d3

don't fire missing act() warnings for react-art (#15975)

* use toWarnDev for dom fixture tests forks toWarnDev from root into fixture/dom, updates tes tests to use it * disable act() warnings for react-art() - For 'secondary' renderers like react-act, we don't want to fire missing act() warnings; the wrapping renderer will fire warnings anyway, and when it flushes, it flushes effects *across* renderers. - I could have used isPrimaryRenderer as the flag, but this is marked as false for react-test-renderer, and we *do* want the warning to fire for it. Hence a new flag. * add missing dependency `art` to fixtures/dom

Sunil Pai committed Jun 24, 2019 at 19:18 UTC fce15f14d38d680f3bdee3a124e9e94e91520e16
12 files changed +509 -39
fixtures/dom/package.json
+2
@@ -7,9 +7,11 @@
7 },
8 "dependencies": {
9 "@babel/standalone": "^7.0.0",
10 + "art": "^0.10.3",
11 "classnames": "^2.2.5",
12 "codemirror": "^5.40.0",
13 "core-js": "^2.4.1",
14 + "jest-diff": "^24.8.0",
15 "prop-types": "^15.6.0",
16 "query-string": "^4.2.3",
17 "react": "^15.4.1",
fixtures/dom/src/index.test.js
+91 -38
@@ -9,22 +9,17 @@
9
10 import React from 'react';
11 import ReactDOM from 'react-dom';
12 +import ReactART from 'react-art';
13 +import ARTSVGMode from 'art/modes/svg';
14 +import ARTCurrentMode from 'art/modes/current';
15 import TestUtils from 'react-dom/test-utils';
16 import TestRenderer from 'react-test-renderer';
17
15 -let spy;
16 -beforeEach(() => {
17 - spy = jest.spyOn(console, 'error').mockImplementation(() => {});
18 -});
18 +ARTCurrentMode.setCurrent(ARTSVGMode);
19
20 -function confirmWarning() {
21 - expect(spy).toHaveBeenCalledWith(
22 - expect.stringContaining(
23 - "It looks like you're using the wrong act() around your test interactions."
24 - ),
25 - ''
26 - );
27 -}
20 +global.__DEV__ = process.env.NODE_ENV !== 'production';
21 +
22 +expect.extend(require('./toWarnDev'));
23
24 function App(props) {
25 return 'hello world';
@@ -34,29 +29,33 @@ it("doesn't warn when you use the right act + renderer: dom", () => {
29 TestUtils.act(() => {
30 TestUtils.renderIntoDocument(<App />);
31 });
37 - expect(spy).not.toHaveBeenCalled();
32 });
33
34 it("doesn't warn when you use the right act + renderer: test", () => {
35 TestRenderer.act(() => {
36 TestRenderer.create(<App />);
37 });
44 - expect(spy).not.toHaveBeenCalled();
38 });
39
47 -it('works with createRoot().render combo', () => {
40 +it('warns when using createRoot() + .render', () => {
41 const root = ReactDOM.unstable_createRoot(document.createElement('div'));
49 - TestRenderer.act(() => {
50 - root.render(<App />);
42 + expect(() => {
43 + TestRenderer.act(() => {
44 + root.render(<App />);
45 + });
46 + }).toWarnDev(["It looks like you're using the wrong act()"], {
47 + withoutStack: true,
48 });
52 - confirmWarning();
49 });
50
51 it('warns when using the wrong act version - test + dom: render', () => {
56 - TestRenderer.act(() => {
57 - TestUtils.renderIntoDocument(<App />);
52 + expect(() => {
53 + TestRenderer.act(() => {
54 + TestUtils.renderIntoDocument(<App />);
55 + });
56 + }).toWarnDev(["It looks like you're using the wrong act()"], {
57 + withoutStack: true,
58 });
59 - confirmWarning();
59 });
60
61 it('warns when using the wrong act version - test + dom: updates', () => {
@@ -67,29 +66,35 @@ it('warns when using the wrong act version - test + dom: updates', () => {
66 return ctr;
67 }
68 TestUtils.renderIntoDocument(<Counter />);
70 - TestRenderer.act(() => {
71 - setCtr(1);
72 - });
73 - confirmWarning();
69 + expect(() => {
70 + TestRenderer.act(() => {
71 + setCtr(1);
72 + });
73 + }).toWarnDev([
74 + 'An update to Counter inside a test was not wrapped in act',
75 + "It looks like you're using the wrong act()",
76 + ]);
77 });
78
79 it('warns when using the wrong act version - dom + test: .create()', () => {
77 - TestUtils.act(() => {
78 - TestRenderer.create(<App />);
80 + expect(() => {
81 + TestUtils.act(() => {
82 + TestRenderer.create(<App />);
83 + });
84 + }).toWarnDev(["It looks like you're using the wrong act()"], {
85 + withoutStack: true,
86 });
80 - confirmWarning();
87 });
88
89 it('warns when using the wrong act version - dom + test: .update()', () => {
84 - let root;
85 - // use the right one here so we don't get the first warning
86 - TestRenderer.act(() => {
87 - root = TestRenderer.create(<App key="one" />);
90 + const root = TestRenderer.create(<App key="one" />);
91 + expect(() => {
92 + TestUtils.act(() => {
93 + root.update(<App key="two" />);
94 + });
95 + }).toWarnDev(["It looks like you're using the wrong act()"], {
96 + withoutStack: true,
97 });
89 - TestUtils.act(() => {
90 - root.update(<App key="two" />);
91 - });
92 - confirmWarning();
98 });
99
100 it('warns when using the wrong act version - dom + test: updates', () => {
@@ -100,8 +105,56 @@ it('warns when using the wrong act version - dom + test: updates', () => {
105 return ctr;
106 }
107 const root = TestRenderer.create(<Counter />);
108 + expect(() => {
109 + TestUtils.act(() => {
110 + setCtr(1);
111 + });
112 + }).toWarnDev([
113 + 'An update to Counter inside a test was not wrapped in act',
114 + "It looks like you're using the wrong act()",
115 + ]);
116 +});
117 +
118 +const {Surface, Group, Shape} = ReactART;
119 +function ARTTest(props) {
120 + return (
121 + <Surface width={150} height={200}>
122 + <Group>
123 + <Shape
124 + d="M0,0l50,0l0,50l-50,0z"
125 + fill={new ReactART.LinearGradient(['black', 'white'])}
126 + key="a"
127 + width={50}
128 + height={50}
129 + x={50}
130 + y={50}
131 + opacity={0.1}
132 + />
133 + <Shape
134 + fill="#3C5A99"
135 + key="b"
136 + scale={0.5}
137 + x={50}
138 + y={50}
139 + title="This is an F"
140 + cursor="pointer">
141 + M64.564,38.583H54l0.008-5.834c0-3.035,0.293-4.666,4.657-4.666
142 + h5.833V16.429h-9.33c-11.213,0-15.159,5.654-15.159,15.16v6.994
143 + h-6.99v11.652h6.99v33.815H54V50.235h9.331L64.564,38.583z
144 + </Shape>
145 + </Group>
146 + </Surface>
147 + );
148 +}
149 +
150 +it('does not warn when nesting react-act inside react-dom', () => {
151 TestUtils.act(() => {
104 - setCtr(1);
152 + TestUtils.renderIntoDocument(<ARTTest />);
153 + });
154 +});
155 +
156 +it('does not warn when nesting react-act inside react-test-renderer', () => {
157 + TestRenderer.act(() => {
158 + TestRenderer.create(<ARTTest />);
159 });
106 - confirmWarning();
160 });
fixtures/dom/src/toWarnDev.js new
+291
@@ -0,0 +1,291 @@
1 +// copied from scripts/jest/matchers/toWarnDev.js
2 +'use strict';
3 +
4 +const jestDiff = require('jest-diff');
5 +const util = require('util');
6 +
7 +function shouldIgnoreConsoleError(format, args) {
8 + if (__DEV__) {
9 + if (typeof format === 'string') {
10 + if (format.indexOf('Error: Uncaught [') === 0) {
11 + // This looks like an uncaught error from invokeGuardedCallback() wrapper
12 + // in development that is reported by jsdom. Ignore because it's noisy.
13 + return true;
14 + }
15 + if (format.indexOf('The above error occurred') === 0) {
16 + // This looks like an error addendum from ReactFiberErrorLogger.
17 + // Ignore it too.
18 + return true;
19 + }
20 + }
21 + } else {
22 + if (
23 + format != null &&
24 + typeof format.message === 'string' &&
25 + typeof format.stack === 'string' &&
26 + args.length === 0
27 + ) {
28 + // In production, ReactFiberErrorLogger logs error objects directly.
29 + // They are noisy too so we'll try to ignore them.
30 + return true;
31 + }
32 + }
33 + // Looks legit
34 + return false;
35 +}
36 +
37 +function normalizeCodeLocInfo(str) {
38 + return str && str.replace(/at .+?:\d+/g, 'at **');
39 +}
40 +
41 +const createMatcherFor = consoleMethod =>
42 + function matcher(callback, expectedMessages, options = {}) {
43 + if (__DEV__) {
44 + // Warn about incorrect usage of matcher.
45 + if (typeof expectedMessages === 'string') {
46 + expectedMessages = [expectedMessages];
47 + } else if (!Array.isArray(expectedMessages)) {
48 + throw Error(
49 + `toWarnDev() requires a parameter of type string or an array of strings ` +
50 + `but was given ${typeof expectedMessages}.`
51 + );
52 + }
53 + if (
54 + options != null &&
55 + (typeof options !== 'object' || Array.isArray(options))
56 + ) {
57 + throw new Error(
58 + 'toWarnDev() second argument, when present, should be an object. ' +
59 + 'Did you forget to wrap the messages into an array?'
60 + );
61 + }
62 + if (arguments.length > 3) {
63 + // `matcher` comes from Jest, so it's more than 2 in practice
64 + throw new Error(
65 + 'toWarnDev() received more than two arguments. ' +
66 + 'Did you forget to wrap the messages into an array?'
67 + );
68 + }
69 +
70 + const withoutStack = options.withoutStack;
71 + const warningsWithoutComponentStack = [];
72 + const warningsWithComponentStack = [];
73 + const unexpectedWarnings = [];
74 +
75 + let lastWarningWithMismatchingFormat = null;
76 + let lastWarningWithExtraComponentStack = null;
77 +
78 + // Catch errors thrown by the callback,
79 + // But only rethrow them if all test expectations have been satisfied.
80 + // Otherwise an Error in the callback can mask a failed expectation,
81 + // and result in a test that passes when it shouldn't.
82 + let caughtError;
83 +
84 + const isLikelyAComponentStack = message =>
85 + typeof message === 'string' && message.includes('\n in ');
86 +
87 + const consoleSpy = (format, ...args) => {
88 + // Ignore uncaught errors reported by jsdom
89 + // and React addendums because they're too noisy.
90 + if (
91 + consoleMethod === 'error' &&
92 + shouldIgnoreConsoleError(format, args)
93 + ) {
94 + return;
95 + }
96 +
97 + const message = util.format(format, ...args);
98 + const normalizedMessage = normalizeCodeLocInfo(message);
99 +
100 + // Remember if the number of %s interpolations
101 + // doesn't match the number of arguments.
102 + // We'll fail the test if it happens.
103 + let argIndex = 0;
104 + format.replace(/%s/g, () => argIndex++);
105 + if (argIndex !== args.length) {
106 + lastWarningWithMismatchingFormat = {
107 + format,
108 + args,
109 + expectedArgCount: argIndex,
110 + };
111 + }
112 +
113 + // Protect against accidentally passing a component stack
114 + // to warning() which already injects the component stack.
115 + if (
116 + args.length >= 2 &&
117 + isLikelyAComponentStack(args[args.length - 1]) &&
118 + isLikelyAComponentStack(args[args.length - 2])
119 + ) {
120 + lastWarningWithExtraComponentStack = {
121 + format,
122 + };
123 + }
124 +
125 + for (let index = 0; index < expectedMessages.length; index++) {
126 + const expectedMessage = expectedMessages[index];
127 + if (
128 + normalizedMessage === expectedMessage ||
129 + normalizedMessage.includes(expectedMessage)
130 + ) {
131 + if (isLikelyAComponentStack(normalizedMessage)) {
132 + warningsWithComponentStack.push(normalizedMessage);
133 + } else {
134 + warningsWithoutComponentStack.push(normalizedMessage);
135 + }
136 + expectedMessages.splice(index, 1);
137 + return;
138 + }
139 + }
140 +
141 + let errorMessage;
142 + if (expectedMessages.length === 0) {
143 + errorMessage =
144 + 'Unexpected warning recorded: ' +
145 + this.utils.printReceived(normalizedMessage);
146 + } else if (expectedMessages.length === 1) {
147 + errorMessage =
148 + 'Unexpected warning recorded: ' +
149 + jestDiff(expectedMessages[0], normalizedMessage);
150 + } else {
151 + errorMessage =
152 + 'Unexpected warning recorded: ' +
153 + jestDiff(expectedMessages, [normalizedMessage]);
154 + }
155 +
156 + // Record the call stack for unexpected warnings.
157 + // We don't throw an Error here though,
158 + // Because it might be suppressed by ReactFiberScheduler.
159 + unexpectedWarnings.push(new Error(errorMessage));
160 + };
161 +
162 + // TODO Decide whether we need to support nested toWarn* expectations.
163 + // If we don't need it, add a check here to see if this is already our spy,
164 + // And throw an error.
165 + const originalMethod = console[consoleMethod];
166 +
167 + // Avoid using Jest's built-in spy since it can't be removed.
168 + console[consoleMethod] = consoleSpy;
169 +
170 + try {
171 + callback();
172 + } catch (error) {
173 + caughtError = error;
174 + } finally {
175 + // Restore the unspied method so that unexpected errors fail tests.
176 + console[consoleMethod] = originalMethod;
177 +
178 + // Any unexpected Errors thrown by the callback should fail the test.
179 + // This should take precedence since unexpected errors could block warnings.
180 + if (caughtError) {
181 + throw caughtError;
182 + }
183 +
184 + // Any unexpected warnings should be treated as a failure.
185 + if (unexpectedWarnings.length > 0) {
186 + return {
187 + message: () => unexpectedWarnings[0].stack,
188 + pass: false,
189 + };
190 + }
191 +
192 + // Any remaining messages indicate a failed expectations.
193 + if (expectedMessages.length > 0) {
194 + return {
195 + message: () =>
196 + `Expected warning was not recorded:\n ${this.utils.printReceived(
197 + expectedMessages[0]
198 + )}`,
199 + pass: false,
200 + };
201 + }
202 +
203 + if (typeof withoutStack === 'number') {
204 + // We're expecting a particular number of warnings without stacks.
205 + if (withoutStack !== warningsWithoutComponentStack.length) {
206 + return {
207 + message: () =>
208 + `Expected ${withoutStack} warnings without a component stack but received ${
209 + warningsWithoutComponentStack.length
210 + }:\n` +
211 + warningsWithoutComponentStack.map(warning =>
212 + this.utils.printReceived(warning)
213 + ),
214 + pass: false,
215 + };
216 + }
217 + } else if (withoutStack === true) {
218 + // We're expecting that all warnings won't have the stack.
219 + // If some warnings have it, it's an error.
220 + if (warningsWithComponentStack.length > 0) {
221 + return {
222 + message: () =>
223 + `Received warning unexpectedly includes a component stack:\n ${this.utils.printReceived(
224 + warningsWithComponentStack[0]
225 + )}\nIf this warning intentionally includes the component stack, remove ` +
226 + `{withoutStack: true} from the toWarnDev() call. If you have a mix of ` +
227 + `warnings with and without stack in one toWarnDev() call, pass ` +
228 + `{withoutStack: N} where N is the number of warnings without stacks.`,
229 + pass: false,
230 + };
231 + }
232 + } else if (withoutStack === false || withoutStack === undefined) {
233 + // We're expecting that all warnings *do* have the stack (default).
234 + // If some warnings don't have it, it's an error.
235 + if (warningsWithoutComponentStack.length > 0) {
236 + return {
237 + message: () =>
238 + `Received warning unexpectedly does not include a component stack:\n ${this.utils.printReceived(
239 + warningsWithoutComponentStack[0]
240 + )}\nIf this warning intentionally omits the component stack, add ` +
241 + `{withoutStack: true} to the toWarnDev() call.`,
242 + pass: false,
243 + };
244 + }
245 + } else {
246 + throw Error(
247 + `The second argument for toWarnDev(), when specified, must be an object. It may have a ` +
248 + `property called "withoutStack" whose value may be undefined, boolean, or a number. ` +
249 + `Instead received ${typeof withoutStack}.`
250 + );
251 + }
252 +
253 + if (lastWarningWithMismatchingFormat !== null) {
254 + return {
255 + message: () =>
256 + `Received ${
257 + lastWarningWithMismatchingFormat.args.length
258 + } arguments for a message with ${
259 + lastWarningWithMismatchingFormat.expectedArgCount
260 + } placeholders:\n ${this.utils.printReceived(
261 + lastWarningWithMismatchingFormat.format
262 + )}`,
263 + pass: false,
264 + };
265 + }
266 +
267 + if (lastWarningWithExtraComponentStack !== null) {
268 + return {
269 + message: () =>
270 + `Received more than one component stack for a warning:\n ${this.utils.printReceived(
271 + lastWarningWithExtraComponentStack.format
272 + )}\nDid you accidentally pass a stack to warning() as the last argument? ` +
273 + `Don't forget warning() already injects the component stack automatically.`,
274 + pass: false,
275 + };
276 + }
277 +
278 + return {pass: true};
279 + }
280 + } else {
281 + // Any uncaught errors or warnings should fail tests in production mode.
282 + callback();
283 +
284 + return {pass: true};
285 + }
286 + };
287 +
288 +module.exports = {
289 + toLowPriorityWarnDev: createMatcherFor('warn'),
290 + toWarnDev: createMatcherFor('error'),
291 +};
fixtures/dom/yarn.lock
+107
@@ -6,6 +6,40 @@
6 version "7.0.0"
7 resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.0.0.tgz#856446641620c1c5f0ca775621d478324ebd1f52"
8
9 +"@jest/types@^24.8.0":
10 + version "24.8.0"
11 + resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.8.0.tgz#f31e25948c58f0abd8c845ae26fcea1491dea7ad"
12 + integrity sha512-g17UxVr2YfBtaMUxn9u/4+siG1ptg9IGYAYwvpwn61nBg779RXnjE/m7CxYcIzEt0AbHZZAHSEZNhkE2WxURVg==
13 + dependencies:
14 + "@types/istanbul-lib-coverage" "^2.0.0"
15 + "@types/istanbul-reports" "^1.1.1"
16 + "@types/yargs" "^12.0.9"
17 +
18 +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
19 + version "2.0.1"
20 + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
21 + integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==
22 +
23 +"@types/istanbul-lib-report@*":
24 + version "1.1.1"
25 + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c"
26 + integrity sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==
27 + dependencies:
28 + "@types/istanbul-lib-coverage" "*"
29 +
30 +"@types/istanbul-reports@^1.1.1":
31 + version "1.1.1"
32 + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a"
33 + integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==
34 + dependencies:
35 + "@types/istanbul-lib-coverage" "*"
36 + "@types/istanbul-lib-report" "*"
37 +
38 +"@types/yargs@^12.0.9":
39 + version "12.0.12"
40 + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.12.tgz#45dd1d0638e8c8f153e87d296907659296873916"
41 + integrity sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==
42 +
43 abab@^1.0.3:
44 version "1.0.3"
45 resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d"
@@ -140,6 +174,11 @@ ansi-regex@^3.0.0:
174 version "3.0.0"
175 resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
176
177 +ansi-regex@^4.0.0:
178 + version "4.1.0"
179 + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
180 + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
181 +
182 ansi-styles@^2.2.1:
183 version "2.2.1"
184 resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
@@ -150,6 +189,13 @@ ansi-styles@^3.0.0, ansi-styles@^3.1.0:
189 dependencies:
190 color-convert "^1.9.0"
191
192 +ansi-styles@^3.2.0, ansi-styles@^3.2.1:
193 + version "3.2.1"
194 + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
195 + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
196 + dependencies:
197 + color-convert "^1.9.0"
198 +
199 anymatch@^1.3.0:
200 version "1.3.0"
201 resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507"
@@ -249,6 +295,11 @@ arrify@^1.0.0, arrify@^1.0.1:
295 version "1.0.1"
296 resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
297
298 +art@^0.10.3:
299 + version "0.10.3"
300 + resolved "https://registry.yarnpkg.com/art/-/art-0.10.3.tgz#b01d84a968ccce6208df55a733838c96caeeaea2"
301 + integrity sha512-HXwbdofRTiJT6qZX/FnchtldzJjS3vkLJxQilc3Xj+ma2MXjY4UAyQ0ls1XZYVnDvVIBiFZbC6QsvtW86TD6tQ==
302 +
303 asap@~2.0.3:
304 version "2.0.5"
305 resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f"
@@ -1466,6 +1517,15 @@ chalk@^2.0.0, chalk@^2.1.0:
1517 escape-string-regexp "^1.0.5"
1518 supports-color "^4.0.0"
1519
1520 +chalk@^2.0.1:
1521 + version "2.4.2"
1522 + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
1523 + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
1524 + dependencies:
1525 + ansi-styles "^3.2.1"
1526 + escape-string-regexp "^1.0.5"
1527 + supports-color "^5.3.0"
1528 +
1529 chokidar@^1.6.0, chokidar@^1.7.0:
1530 version "1.7.0"
1531 resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
@@ -2058,6 +2118,11 @@ detect-port-alt@1.1.3:
2118 address "^1.0.1"
2119 debug "^2.6.0"
2120
2121 +diff-sequences@^24.3.0:
2122 + version "24.3.0"
2123 + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.3.0.tgz#0f20e8a1df1abddaf4d9c226680952e64118b975"
2124 + integrity sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==
2125 +
2126 diff@^3.2.0:
2127 version "3.3.0"
2128 resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.0.tgz#056695150d7aa93237ca7e378ac3b1682b7963b9"
@@ -3119,6 +3184,11 @@ has-flag@^2.0.0:
3184 version "2.0.0"
3185 resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
3186
3187 +has-flag@^3.0.0:
3188 + version "3.0.0"
3189 + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
3190 + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
3191 +
3192 has-unicode@^2.0.0:
3193 version "2.0.1"
3194 resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
@@ -3770,6 +3840,16 @@ jest-diff@^20.0.3:
3840 jest-matcher-utils "^20.0.3"
3841 pretty-format "^20.0.3"
3842
3843 +jest-diff@^24.8.0:
3844 + version "24.8.0"
3845 + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.8.0.tgz#146435e7d1e3ffdf293d53ff97e193f1d1546172"
3846 + integrity sha512-wxetCEl49zUpJ/bvUmIFjd/o52J+yWcoc5ZyPq4/W1LUKGEhRYDIbP1KcF6t+PvqNrGAFk4/JhtxDq/Nnzs66g==
3847 + dependencies:
3848 + chalk "^2.0.1"
3849 + diff-sequences "^24.3.0"
3850 + jest-get-type "^24.8.0"
3851 + pretty-format "^24.8.0"
3852 +
3853 jest-docblock@^20.0.3:
3854 version "20.0.3"
3855 resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.0.3.tgz#17bea984342cc33d83c50fbe1545ea0efaa44712"
@@ -3789,6 +3869,11 @@ jest-environment-node@^20.0.3:
3869 jest-mock "^20.0.3"
3870 jest-util "^20.0.3"
3871
3872 +jest-get-type@^24.8.0:
3873 + version "24.8.0"
3874 + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.8.0.tgz#a7440de30b651f5a70ea3ed7ff073a32dfe646fc"
3875 + integrity sha512-RR4fo8jEmMD9zSz2nLbs2j0zvPpk/KCEz3a62jJWbd2ayNo0cb+KFRxPHVhE4ZmgGJEQp0fosmNz84IfqM8cMQ==
3876 +
3877 jest-haste-map@^20.0.4:
3878 version "20.0.5"
3879 resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-20.0.5.tgz#abad74efb1a005974a7b6517e11010709cab9112"
@@ -5243,6 +5328,16 @@ pretty-format@^20.0.3:
5328 ansi-regex "^2.1.1"
5329 ansi-styles "^3.0.0"
5330
5331 +pretty-format@^24.8.0:
5332 + version "24.8.0"
5333 + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.8.0.tgz#8dae7044f58db7cb8be245383b565a963e3c27f2"
5334 + integrity sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw==
5335 + dependencies:
5336 + "@jest/types" "^24.8.0"
5337 + ansi-regex "^4.0.0"
5338 + ansi-styles "^3.2.0"
5339 + react-is "^16.8.4"
5340 +
5341 private@^0.1.6:
5342 version "0.1.6"
5343 resolved "https://registry.yarnpkg.com/private/-/private-0.1.6.tgz#55c6a976d0f9bafb9924851350fe47b9b5fbb7c1"
@@ -5429,6 +5524,11 @@ react-error-overlay@^1.0.10:
5524 settle-promise "1.0.0"
5525 source-map "0.5.6"
5526
5527 +react-is@^16.8.4:
5528 + version "16.8.6"
5529 + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
5530 + integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
5531 +
5532 react-scripts@^1.0.11:
5533 version "1.0.11"
5534 resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-1.0.11.tgz#483d49e27f417ec981ae415a4456120a2a2bc8c1"
@@ -6248,6 +6348,13 @@ supports-color@^4.0.0, supports-color@^4.2.1:
6348 dependencies:
6349 has-flag "^2.0.0"
6350
6351 +supports-color@^5.3.0:
6352 + version "5.5.0"
6353 + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
6354 + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
6355 + dependencies:
6356 + has-flag "^3.0.0"
6357 +
6358 svgo@^0.7.0:
6359 version "0.7.1"
6360 resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.1.tgz#287320fed972cb097e72c2bb1685f96fe08f8034"
packages/react-art/src/ReactARTHostConfig.js
+3
@@ -350,6 +350,9 @@ export function shouldSetTextContent(type, props) {
350 // The ART renderer is secondary to the React DOM renderer.
351 export const isPrimaryRenderer = false;
352
353 +// The ART renderer shouldn't trigger missing act() warnings
354 +export const shouldWarnUnactedUpdates = false;
355 +
356 export const supportsMutation = true;
357
358 export function appendChild(parentInstance, child) {
packages/react-dom/src/client/ReactDOMHostConfig.js
+1
@@ -390,6 +390,7 @@ export function createTextInstance(
390 }
391
392 export const isPrimaryRenderer = true;
393 +export const shouldWarnUnactedUpdates = true;
394 // This initialization code may run even on server environments
395 // if a component just imports ReactDOM (e.g. for findDOMNode).
396 // Some environments might not have setTimeout or clearTimeout.
packages/react-native-renderer/src/ReactFabricHostConfig.js
+3
@@ -345,6 +345,9 @@ export function shouldSetTextContent(type: string, props: Props): boolean {
345 // The Fabric renderer is secondary to the existing React Native renderer.
346 export const isPrimaryRenderer = false;
347
348 +// The Fabric renderer shouldn't trigger missing act() warnings
349 +export const shouldWarnUnactedUpdates = false;
350 +
351 export const scheduleTimeout = setTimeout;
352 export const cancelTimeout = clearTimeout;
353 export const noTimeout = -1;
packages/react-native-renderer/src/ReactNativeHostConfig.js
+1
@@ -248,6 +248,7 @@ export function resetAfterCommit(containerInfo: Container): void {
248 }
249
250 export const isPrimaryRenderer = true;
251 +export const shouldWarnUnactedUpdates = true;
252
253 export const scheduleTimeout = setTimeout;
254 export const cancelTimeout = clearTimeout;
packages/react-noop-renderer/src/createReactNoop.js
+1
@@ -434,6 +434,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
434 now: Scheduler.unstable_now,
435
436 isPrimaryRenderer: true,
437 + shouldWarnUnactedUpdates: true,
438 supportsHydration: false,
439
440 mountEventComponent(): void {
packages/react-reconciler/src/ReactFiberWorkLoop.js
+7 -1
@@ -55,6 +55,7 @@ import {
55 scheduleTimeout,
56 cancelTimeout,
57 noTimeout,
58 + shouldWarnUnactedUpdates,
59 } from './ReactFiberHostConfig';
60
61 import {createWorkInProgress, assignFiberPropertiesInDEV} from './ReactFiber';
@@ -2420,6 +2421,7 @@ export const ReactActingRendererSigil = {};
2421 export function warnIfNotScopedWithMatchingAct(fiber: Fiber): void {
2422 if (__DEV__) {
2423 if (
2424 + shouldWarnUnactedUpdates === true &&
2425 ReactCurrentActingRendererSigil.current !== null &&
2426 ReactCurrentActingRendererSigil.current !== ReactActingRendererSigil
2427 ) {
@@ -2445,7 +2447,10 @@ export function warnIfNotScopedWithMatchingAct(fiber: Fiber): void {
2447
2448 export function warnIfNotCurrentlyActingEffectsInDEV(fiber: Fiber): void {
2449 if (__DEV__) {
2448 - if (ReactCurrentActingRendererSigil.current !== ReactActingRendererSigil) {
2450 + if (
2451 + shouldWarnUnactedUpdates === true &&
2452 + ReactCurrentActingRendererSigil.current !== ReactActingRendererSigil
2453 + ) {
2454 warningWithoutStack(
2455 false,
2456 'An update to %s ran an effect, but was not wrapped in act(...).\n\n' +
@@ -2469,6 +2474,7 @@ export function warnIfNotCurrentlyActingEffectsInDEV(fiber: Fiber): void {
2474 function warnIfNotCurrentlyActingUpdatesInDEV(fiber: Fiber): void {
2475 if (__DEV__) {
2476 if (
2477 + shouldWarnUnactedUpdates === true &&
2478 executionContext === NoContext &&
2479 ReactCurrentActingRendererSigil.current !== ReactActingRendererSigil
2480 ) {
packages/react-reconciler/src/forks/ReactFiberHostConfig.custom.js
+1
@@ -61,6 +61,7 @@ export const cancelTimeout = $$$hostConfig.clearTimeout;
61 export const noTimeout = $$$hostConfig.noTimeout;
62 export const now = $$$hostConfig.now;
63 export const isPrimaryRenderer = $$$hostConfig.isPrimaryRenderer;
64 +export const shouldWarnUnactedUpdates = $$$hostConfig.shouldWarnUnactedUpdates;
65 export const supportsMutation = $$$hostConfig.supportsMutation;
66 export const supportsPersistence = $$$hostConfig.supportsPersistence;
67 export const supportsHydration = $$$hostConfig.supportsHydration;
packages/react-test-renderer/src/ReactTestHostConfig.js
+1
@@ -261,6 +261,7 @@ export function createTextInstance(
261 }
262
263 export const isPrimaryRenderer = false;
264 +export const shouldWarnUnactedUpdates = true;
265
266 export const scheduleTimeout = setTimeout;
267 export const cancelTimeout = clearTimeout;