ReactNoop.flush methods return an array of yielded values
Allows us to make assertions on the values that are yielded when performing work. In our existing tests, we do this manually by pushing into an array. ReactNoop.flushThrough extends this concept. It accepts an array of expected values and flushes until those values are yielded.
Andrew Clark committed
Jun 14, 2017 at 14:32 UTC
6a0c56cffcaff62b666cdd5fbc1c02d1d3dc6402
5 files changed
+102
-32
package.json
+1
@@ -67,6 +67,7 @@
67
"jest": "^19.0.1",
68
"jest-config": "^19.0.1",
69
"jest-jasmine2": "^19.0.1",
70
+ "jest-matchers": "^20.0.3",
71
"jest-runtime": "^19.0.1",
72
"loose-envify": "^1.1.0",
73
"merge-stream": "^1.0.0",
scripts/rollup/bundles.js
+1
-1
@@ -338,7 +338,7 @@ const bundles = [
338
sourceMap: false,
339
},
340
entry: 'src/renderers/noop/ReactNoopEntry',
341
- externals: ['prop-types/checkPropTypes'],
341
+ externals: ['prop-types/checkPropTypes', 'jest-matchers'],
342
isRenderer: true,
343
label: 'noop-fiber',
344
manglePropertiesOnProd: false,
scripts/rollup/results.json
+2
-2
@@ -145,8 +145,8 @@
145
"gzip": 2234
146
},
147
"react-noop-renderer.development.js (NODE_DEV)": {
148
- "size": 269722,
149
- "gzip": 56481
148
+ "size": 272256,
149
+ "gzip": 56994
150
}
151
}
152
}
\ No newline at end of file
src/renderers/noop/ReactNoopEntry.js
+52
-27
@@ -28,6 +28,8 @@ var ReactInstanceMap = require('ReactInstanceMap');
28
var {AnimationPriority} = require('ReactPriorityLevel');
29
var emptyObject = require('fbjs/lib/emptyObject');
30
31
+var expect = require('jest-matchers');
32
+
33
const UPDATE_SIGNAL = {};
34
35
var scheduledAnimationCallback = null;
@@ -219,22 +221,20 @@ var rootContainers = new Map();
221
var roots = new Map();
222
var DEFAULT_ROOT_ID = '<default>';
223
222
-let yieldBeforeNextUnitOfWork = false;
223
-let yieldValue = null;
224
+let yieldedValues = null;
225
225
-function* flushUnitsOfWork(n: number): Generator<mixed, void, void> {
226
+function* flushUnitsOfWork(
227
+ n: number = Infinity,
228
+): Generator<Array<mixed>, void, void> {
229
var didStop = false;
230
while (!didStop && scheduledDeferredCallback !== null) {
231
var cb = scheduledDeferredCallback;
232
scheduledDeferredCallback = null;
230
- yieldBeforeNextUnitOfWork = false;
231
- yieldValue = null;
233
+ yieldedValues = null;
234
var unitsRemaining = n;
233
- var didYield = false;
235
cb({
236
timeRemaining() {
236
- if (yieldBeforeNextUnitOfWork) {
237
- didYield = true;
237
+ if (yieldedValues !== null) {
238
return 0;
239
}
240
if (unitsRemaining-- > 0) {
@@ -245,10 +245,10 @@ function* flushUnitsOfWork(n: number): Generator<mixed, void, void> {
245
},
246
});
247
248
- if (didYield) {
249
- const valueToYield = yieldValue;
250
- yieldValue = null;
251
- yield valueToYield;
248
+ if (yieldedValues !== null) {
249
+ const values = yieldedValues;
250
+ yieldedValues = null;
251
+ yield values;
252
}
253
}
254
}
@@ -308,6 +308,7 @@ var ReactNoop = {
308
return inst ? NoopRenderer.findHostInstance(inst) : null;
309
},
310
311
+ // TODO: Remove this method
312
flushAnimationPri() {
313
var cb = scheduledAnimationCallback;
314
if (cb === null) {
@@ -317,47 +318,71 @@ var ReactNoop = {
318
cb();
319
},
320
320
- flushDeferredPri(timeout: number = Infinity) {
321
+ flushDeferredPri(timeout: number = Infinity): Array<mixed> {
322
// The legacy version of this function decremented the timeout before
323
// returning the new time.
324
// TODO: Convert tests to use flushUnitsOfWork or flushAndYield instead.
325
const n = timeout / 5 - 1;
325
- const iterator = flushUnitsOfWork(n);
326
- let value = iterator.next();
327
- while (!value.done) {
328
- value = iterator.next();
326
+
327
+ let values = [];
328
+ for (const value of flushUnitsOfWork(n)) {
329
+ values.push(...value);
330
}
331
// Don't flush animation priority in this legacy function. Some tests may
332
// still rely on this behavior.
333
+ return values;
334
},
335
334
- flush() {
336
+ flush(): Array<mixed> {
337
ReactNoop.flushAnimationPri();
336
- ReactNoop.flushDeferredPri();
338
+ return ReactNoop.flushDeferredPri();
339
},
340
339
- *flushAndYield(unitsOfWork: number = Infinity): Generator<mixed, void, void> {
341
+ *flushAndYield(
342
+ unitsOfWork: number = Infinity,
343
+ ): Generator<Array<mixed>, void, void> {
344
for (const value of flushUnitsOfWork(unitsOfWork)) {
345
yield value;
346
}
347
ReactNoop.flushAnimationPri();
348
},
349
346
- flushUnitsOfWork(n: number) {
347
- const iterator = flushUnitsOfWork(n);
348
- let value = iterator.next();
349
- while (!value.done) {
350
- value = iterator.next();
350
+ flushUnitsOfWork(n: number): Array<mixed> {
351
+ let values = [];
352
+ for (const value of flushUnitsOfWork(n)) {
353
+ values.push(...value);
354
}
355
// TODO: We should always flush animation priority after flushing normal/low
356
// priority. Move this to flushUnitsOfWork generator once tests
357
// are converted.
358
ReactNoop.flushAnimationPri();
359
+ return values;
360
+ },
361
+
362
+ flushThrough(expected: Array<mixed>): void {
363
+ let actual = [];
364
+ if (expected.length !== 0) {
365
+ for (const value of flushUnitsOfWork()) {
366
+ actual.push(...value);
367
+ if (actual.length >= expected.length) {
368
+ break;
369
+ }
370
+ }
371
+ }
372
+ ReactNoop.flushAnimationPri();
373
+ expect(actual).toEqual(expected);
374
},
375
376
yield(value: mixed) {
359
- yieldBeforeNextUnitOfWork = true;
360
- yieldValue = value;
377
+ if (yieldedValues === null) {
378
+ yieldedValues = [value];
379
+ } else {
380
+ yieldedValues.push(value);
381
+ }
382
+ },
383
+
384
+ hasScheduledDeferredCallback() {
385
+ return !!scheduledDeferredCallback;
386
},
387
388
performAnimationWork(fn: Function) {
yarn.lock
+46
-2
@@ -90,7 +90,7 @@ ansi-escapes@^1.1.0, ansi-escapes@^1.4.0:
90
version "1.4.0"
91
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
92
93
-ansi-regex@^2.0.0:
93
+ansi-regex@^2.0.0, ansi-regex@^2.1.1:
94
version "2.1.1"
95
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
96
@@ -1745,7 +1745,7 @@ devtools-timeline-model@1.1.6:
1745
chrome-devtools-frontend "1.0.401423"
1746
resolve "1.1.7"
1747
1748
-diff@^3.0.0:
1748
+diff@^3.0.0, diff@^3.2.0:
1749
version "3.2.0"
1750
resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
1751
@@ -3199,6 +3199,15 @@ jest-diff@^19.0.0:
3199
jest-matcher-utils "^19.0.0"
3200
pretty-format "^19.0.0"
3201
3202
+jest-diff@^20.0.3:
3203
+ version "20.0.3"
3204
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-20.0.3.tgz#81f288fd9e675f0fb23c75f1c2b19445fe586617"
3205
+ dependencies:
3206
+ chalk "^1.1.3"
3207
+ diff "^3.2.0"
3208
+ jest-matcher-utils "^20.0.3"
3209
+ pretty-format "^20.0.3"
3210
+
3211
jest-environment-jsdom@^19.0.2:
3212
version "19.0.2"
3213
resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-19.0.2.tgz#ceda859c4a4b94ab35e4de7dab54b926f293e4a3"
@@ -3245,6 +3254,13 @@ jest-matcher-utils@^19.0.0:
3254
chalk "^1.1.3"
3255
pretty-format "^19.0.0"
3256
3257
+jest-matcher-utils@^20.0.3:
3258
+ version "20.0.3"
3259
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-20.0.3.tgz#b3a6b8e37ca577803b0832a98b164f44b7815612"
3260
+ dependencies:
3261
+ chalk "^1.1.3"
3262
+ pretty-format "^20.0.3"
3263
+
3264
jest-matchers@^19.0.0:
3265
version "19.0.0"
3266
resolved "https://registry.yarnpkg.com/jest-matchers/-/jest-matchers-19.0.0.tgz#c74ecc6ebfec06f384767ba4d6fa4a42d6755754"
@@ -3254,6 +3270,15 @@ jest-matchers@^19.0.0:
3270
jest-message-util "^19.0.0"
3271
jest-regex-util "^19.0.0"
3272
3273
+jest-matchers@^20.0.3:
3274
+ version "20.0.3"
3275
+ resolved "https://registry.yarnpkg.com/jest-matchers/-/jest-matchers-20.0.3.tgz#ca69db1c32db5a6f707fa5e0401abb55700dfd60"
3276
+ dependencies:
3277
+ jest-diff "^20.0.3"
3278
+ jest-matcher-utils "^20.0.3"
3279
+ jest-message-util "^20.0.3"
3280
+ jest-regex-util "^20.0.3"
3281
+
3282
jest-message-util@^19.0.0:
3283
version "19.0.0"
3284
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-19.0.0.tgz#721796b89c0e4d761606f9ba8cb828a3b6246416"
@@ -3261,6 +3286,14 @@ jest-message-util@^19.0.0:
3286
chalk "^1.1.1"
3287
micromatch "^2.3.11"
3288
3289
+jest-message-util@^20.0.3:
3290
+ version "20.0.3"
3291
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-20.0.3.tgz#6aec2844306fcb0e6e74d5796c1006d96fdd831c"
3292
+ dependencies:
3293
+ chalk "^1.1.3"
3294
+ micromatch "^2.3.11"
3295
+ slash "^1.0.0"
3296
+
3297
jest-mock@^19.0.0:
3298
version "19.0.0"
3299
resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-19.0.0.tgz#67038641e9607ab2ce08ec4a8cb83aabbc899d01"
@@ -3269,6 +3302,10 @@ jest-regex-util@^19.0.0:
3302
version "19.0.0"
3303
resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-19.0.0.tgz#b7754587112aede1456510bb1f6afe74ef598691"
3304
3305
+jest-regex-util@^20.0.3:
3306
+ version "20.0.3"
3307
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-20.0.3.tgz#85bbab5d133e44625b19faf8c6aa5122d085d762"
3308
+
3309
jest-resolve-dependencies@^19.0.0:
3310
version "19.0.0"
3311
resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-19.0.0.tgz#a741ad1fa094140e64ecf2642a504f834ece22ee"
@@ -4319,6 +4356,13 @@ pretty-format@^19.0.0:
4356
dependencies:
4357
ansi-styles "^3.0.0"
4358
4359
+pretty-format@^20.0.3:
4360
+ version "20.0.3"
4361
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-20.0.3.tgz#020e350a560a1fe1a98dc3beb6ccffb386de8b14"
4362
+ dependencies:
4363
+ ansi-regex "^2.1.1"
4364
+ ansi-styles "^3.0.0"
4365
+
4366
private@^0.1.6, private@~0.1.5:
4367
version "0.1.7"
4368
resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1"