Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

act() - s / flushPassiveEffects / Scheduler.unstable_flushWithoutYielding #15591

Merged
merged 17 commits into from May 16, 2019

Conversation

threepointone
Copy link
Contributor

@threepointone threepointone commented May 8, 2019

a first crack at flushing the scheduler manually from inside act().

  • uses unstable_flushWithoutYielding() directly instead of flushAll()
  • for tests to pass, I mostly replaced toFlushAndYield(...) with toHaveYielded().
  • for a few tests that tested the state of the tree before flushing effects (but still after updates), I replaced act() with batchedUpdates().

Open questions -

  • uh, is this right? - edit: yes.
  • unstable_flushWithoutYielding is an odd name, especially when it's followed by toHaveYielded. Or am I doing something wrong here? Or should one of these named differently? edit: yup, the names are confusing. will change in a followup PR

todo

  • add a warning when scheduler isn't mocked (but fallback to a version that works in sync mode)
  • make a umd build of scheduler/unstable_mock
  • more tests for concurrent mode
  • make a docs page/link explaining more

a first crack at flushing the scheduler manually from inside act(). uses unstable_flushWithoutYielding(). The tests that changes, mostly replaced toFlushAndYield(...) with toHaveYielded(). For some tests that tested the state of the tree before flushing effects (but still after updates), I replaced act() with bacthedUpdates().
@threepointone threepointone requested a review from acdlite May 8, 2019 17:12
@threepointone threepointone changed the title act() - s/flushPassiveEffects/Scheduler.unstable_flushWithoutYielding act() - s / flushPassiveEffects / Scheduler.unstable_flushWithoutYielding May 8, 2019
@sizebot
Copy link

sizebot commented May 8, 2019

ReactDOM: size: 0.0%, gzip: 0.0%

Details of bundled changes.

Comparing: bb89b4e...763c03e

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.development.js 0.0% +0.1% 831.52 KB 831.79 KB 189.79 KB 189.89 KB UMD_DEV
react-dom.production.min.js 0.0% 0.0% 104.21 KB 104.21 KB 33.84 KB 33.84 KB UMD_PROD
react-dom.profiling.min.js 0.0% 0.0% 107.36 KB 107.36 KB 34.81 KB 34.81 KB UMD_PROFILING
react-dom.development.js 0.0% 0.0% 825.93 KB 826.11 KB 188.25 KB 188.33 KB NODE_DEV
react-dom.production.min.js 0.0% 0.0% 104.2 KB 104.2 KB 33.28 KB 33.28 KB NODE_PROD
react-dom.profiling.min.js 0.0% 0.0% 107.55 KB 107.55 KB 34.18 KB 34.18 KB NODE_PROFILING
ReactDOM-dev.js 0.0% 0.0% 850.6 KB 850.6 KB 189.79 KB 189.79 KB FB_WWW_DEV
ReactDOM-prod.js 0.0% -0.0% 349.6 KB 349.6 KB 64.8 KB 64.8 KB FB_WWW_PROD
ReactDOM-profiling.js 0.0% -0.0% 354.78 KB 354.78 KB 65.8 KB 65.8 KB FB_WWW_PROFILING
react-dom-unstable-fire.development.js 0.0% +0.1% 831.87 KB 832.14 KB 189.94 KB 190.04 KB UMD_DEV
react-dom-unstable-fire.production.min.js 0.0% 0.0% 104.22 KB 104.22 KB 33.85 KB 33.85 KB UMD_PROD
react-dom-unstable-fire.profiling.min.js 0.0% 0.0% 107.38 KB 107.38 KB 34.82 KB 34.82 KB UMD_PROFILING
react-dom-unstable-fire.development.js 0.0% 0.0% 826.27 KB 826.46 KB 188.39 KB 188.48 KB NODE_DEV
react-dom-unstable-fire.profiling.min.js 0.0% 0.0% 107.56 KB 107.56 KB 34.19 KB 34.19 KB NODE_PROFILING
ReactFire-dev.js 0.0% 0.0% 849.81 KB 849.81 KB 189.72 KB 189.72 KB FB_WWW_DEV
ReactFire-prod.js 0.0% 0.0% 337.57 KB 337.57 KB 62.32 KB 62.32 KB FB_WWW_PROD
ReactFire-profiling.js 0.0% 0.0% 342.73 KB 342.73 KB 63.27 KB 63.27 KB FB_WWW_PROFILING
react-dom-test-utils.development.js +4.3% +4.0% 54.42 KB 56.79 KB 15.06 KB 15.66 KB UMD_DEV
react-dom-test-utils.production.min.js 🔺+1.1% 🔺+0.9% 10.56 KB 10.67 KB 3.89 KB 3.93 KB UMD_PROD
react-dom-test-utils.development.js +1.8% +2.3% 54.14 KB 55.13 KB 14.99 KB 15.34 KB NODE_DEV
react-dom-test-utils.production.min.js 🔺+0.7% 🔺+1.0% 10.35 KB 10.43 KB 3.82 KB 3.86 KB NODE_PROD
ReactTestUtils-dev.js +1.7% +2.0% 51.66 KB 52.56 KB 13.91 KB 14.19 KB FB_WWW_DEV
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 60.76 KB 60.76 KB 15.84 KB 15.85 KB UMD_DEV
react-dom-unstable-native-dependencies.production.min.js 0.0% 🔺+0.1% 10.69 KB 10.69 KB 3.66 KB 3.67 KB UMD_PROD
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 60.43 KB 60.43 KB 15.72 KB 15.72 KB NODE_DEV
react-dom-unstable-native-dependencies.production.min.js 0.0% 0.0% 10.43 KB 10.43 KB 3.56 KB 3.56 KB NODE_PROD
react-dom-server.browser.development.js +0.1% +0.2% 136.88 KB 137.07 KB 36.06 KB 36.15 KB UMD_DEV
react-dom-server.browser.production.min.js 0.0% 0.0% 19.11 KB 19.11 KB 7.21 KB 7.21 KB UMD_PROD
react-dom-server.browser.development.js +0.1% +0.2% 133.01 KB 133.2 KB 35.13 KB 35.21 KB NODE_DEV
react-dom-server.browser.production.min.js 0.0% 0.0% 19.03 KB 19.03 KB 7.2 KB 7.2 KB NODE_PROD
ReactDOMServer-dev.js 0.0% 0.0% 135.39 KB 135.39 KB 34.78 KB 34.78 KB FB_WWW_DEV
ReactDOMServer-prod.js 0.0% 0.0% 47.85 KB 47.85 KB 11.01 KB 11.01 KB FB_WWW_PROD
react-dom-server.node.development.js +0.1% +0.2% 134.96 KB 135.14 KB 35.68 KB 35.76 KB NODE_DEV
react-dom-server.node.production.min.js 0.0% 0.0% 19.9 KB 19.9 KB 7.51 KB 7.51 KB NODE_PROD
react-dom-unstable-fizz.browser.development.js 0.0% +0.1% 3.81 KB 3.81 KB 1.53 KB 1.54 KB UMD_DEV
react-dom-unstable-fizz.browser.development.js 0.0% +0.1% 3.64 KB 3.64 KB 1.49 KB 1.49 KB NODE_DEV
react-dom-unstable-fizz.node.development.js 0.0% +0.1% 3.88 KB 3.88 KB 1.51 KB 1.51 KB NODE_DEV
react-dom-unstable-fizz.node.production.min.js 0.0% 🔺+0.3% 1.1 KB 1.1 KB 665 B 667 B NODE_PROD

react-art

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-art.development.js 0.0% +0.1% 565.83 KB 566.11 KB 124.12 KB 124.24 KB UMD_DEV
react-art.production.min.js 0.0% 0.0% 95.9 KB 95.9 KB 29.47 KB 29.47 KB UMD_PROD
react-art.development.js 0.0% +0.1% 496.79 KB 496.98 KB 106.7 KB 106.79 KB NODE_DEV
react-art.production.min.js 0.0% 0.0% 60.88 KB 60.88 KB 18.75 KB 18.75 KB NODE_PROD
ReactART-dev.js 0.0% 0.0% 506.28 KB 506.28 KB 105.83 KB 105.83 KB FB_WWW_DEV

react-test-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-test-renderer.development.js +0.2% +0.2% 510.27 KB 511.04 KB 109.4 KB 109.66 KB UMD_DEV
react-test-renderer.production.min.js 🔺+0.1% 🔺+0.1% 62.12 KB 62.17 KB 19.09 KB 19.12 KB UMD_PROD
react-test-renderer.development.js +0.2% +0.2% 505.82 KB 506.58 KB 108.3 KB 108.56 KB NODE_DEV
react-test-renderer.production.min.js 🔺+0.1% 🔺+0.1% 61.81 KB 61.86 KB 18.95 KB 18.98 KB NODE_PROD
ReactTestRenderer-dev.js +0.2% +0.3% 517.11 KB 517.98 KB 108.13 KB 108.4 KB FB_WWW_DEV
react-test-renderer-shallow.development.js +0.4% +0.8% 41.62 KB 41.8 KB 10.72 KB 10.81 KB UMD_DEV
react-test-renderer-shallow.production.min.js 0.0% 🔺+0.1% 11.51 KB 11.51 KB 3.53 KB 3.53 KB UMD_PROD
react-test-renderer-shallow.development.js +0.5% +1.0% 35.75 KB 35.94 KB 9.35 KB 9.44 KB NODE_DEV
react-test-renderer-shallow.production.min.js 0.0% 0.0% 11.66 KB 11.66 KB 3.65 KB 3.65 KB NODE_PROD

react-noop-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-noop-renderer.development.js +3.0% +4.6% 36.59 KB 37.69 KB 9 KB 9.41 KB NODE_DEV
react-noop-renderer.production.min.js 🔺+0.5% 🔺+0.3% 11.03 KB 11.08 KB 3.53 KB 3.54 KB NODE_PROD
react-noop-renderer-persistent.development.js +3.0% +4.5% 36.71 KB 37.8 KB 9.02 KB 9.42 KB NODE_DEV
react-noop-renderer-persistent.production.min.js 🔺+0.5% 🔺+0.3% 11.05 KB 11.1 KB 3.54 KB 3.55 KB NODE_PROD
react-noop-renderer-server.development.js 0.0% +0.1% 1.83 KB 1.83 KB 875 B 876 B NODE_DEV
react-noop-renderer-server.production.min.js 0.0% 🔺+0.2% 813 B 813 B 490 B 491 B NODE_PROD

scheduler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
scheduler.development.js 0.0% 0.0% 23.32 KB 23.32 KB 5.98 KB 5.98 KB NODE_DEV
scheduler.production.min.js 0.0% 🔺+0.1% 5.03 KB 5.03 KB 1.92 KB 1.92 KB NODE_PROD
scheduler-unstable_mock.development.js n/a n/a 0 B 17.66 KB 0 B 4.08 KB UMD_DEV
scheduler-unstable_mock.production.min.js n/a n/a 0 B 4.12 KB 0 B 1.7 KB UMD_PROD
scheduler-unstable_mock.development.js +0.5% +0.3% 17.39 KB 17.47 KB 4.01 KB 4.02 KB NODE_DEV
scheduler-unstable_mock.production.min.js 🔺+0.7% 🔺+0.9% 4.06 KB 4.09 KB 1.6 KB 1.61 KB NODE_PROD
SchedulerMock-dev.js +0.4% +0.3% 17.61 KB 17.69 KB 4.05 KB 4.06 KB FB_WWW_DEV
SchedulerMock-prod.js 🔺+0.5% 🔺+0.6% 11.91 KB 11.97 KB 2.45 KB 2.46 KB FB_WWW_PROD
scheduler-tracing.development.js +1.7% +3.3% 10.84 KB 11.02 KB 2.65 KB 2.73 KB NODE_DEV
scheduler-tracing.production.min.js 0.0% 🔺+0.3% 728 B 728 B 381 B 382 B NODE_PROD

Generated by 🚫 dangerJS

@acdlite
Copy link
Collaborator

acdlite commented May 8, 2019

unstable_flushWithoutYielding is an odd name, especially when it's followed by toHaveYielded. Or am I doing something wrong here? Or should one of these named differently?

I agree the naming sucks. We'll rename them eventually; suggestions welcome.

Need to throw a helpful error when Scheduler is not the mock build.

Sunil Pai added 2 commits May 9, 2019 10:50
of note, unstable_flushWithoutYielding now returns a boolean much like flushPassiveEffects
@acdlite acdlite mentioned this pull request May 9, 2019
9 tasks
Copy link
Contributor

@bvaughn bvaughn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-flushing seems like an improvement!

I'm not sure how this would work with e.g. Jest environment where you have mock timers (which is important for certain types of things- like tests that verify Profiler timings). In those cases I think you would still end up with an awkward loop like this?

https://github.com/bvaughn/react-devtools-experimental/blob/17516b76ae763ec7c4dfa09d826164d6bb2e41c0/src/__tests__/utils.js#L22-L39

Do we have any plans for a way to hook into this to make sure mocked timers are run along with flushes?

@threepointone
Copy link
Contributor Author

@bvaughn my current thinking is to have a advanceTimersByTime helper, that internally would actually call smaller timeouts, flushing between every run. I'm not committing to any specifics on it just yet, but am spending today/tomorrow writing out some tests including that scenario.

@bvaughn
Copy link
Contributor

bvaughn commented May 9, 2019

I guess I'll wait and see what you have in mind then. I assume advanceTimersByTime will only work with the mock scheduler's now function though, and not with e.g. performance.now/Date.now? I guess that's okay, but it will require user code to also avoid using those functions if tests need predictable timing.

For example, DevTools itself currently uses performance.now

@SimenB
Copy link
Contributor

SimenB commented May 9, 2019

I assume advanceTimersByTime will only work with the mock scheduler's now function though, and not with e.g. performance.now/Date.now?

FWIW, I'm working on and off (mostly off...) on landing Lolex in Jest, which will add make sure Date (new Date() & Date.now()) and performance.now() are also mocked and controlled by advanceTimersByTime: jestjs/jest#7776. I'm hopeful we'll land it for Jest 25.

Not that this affects you at all now, but possibly something to keep in mind. If you do want real timings while faking time you'd have to get a reference to the original performance.now before installing fake timers. Alternatively, it might make sense for Jest to expose some way of timing things that's unaffected by fake timers being installed? Not sure

@threepointone
Copy link
Contributor Author

I updated the PR to run the TestUtilsAct-test tests in both heritage/concurrent mode. I recommend turning off whitespace changes when reading.

Sunil Pai added 2 commits May 11, 2019 11:57
I also tried writing a test for it, but couldn't get the scheduler to unmock. included the failing test.
threepointone pushed a commit to threepointone/react that referenced this pull request May 12, 2019
based on facebook#15591. of note, we don't modify our own tests to satisfy this warning, instead using a feature flag to disable the warning for some tests. this is because we're testing the actual sequencing of work in these tests, and don't want to flush everything with act().
@threepointone
Copy link
Contributor Author

opening this up for review, but still unsure how to get the scheduler to unmock. will keep poking at it.

@threepointone threepointone marked this pull request as ready for review May 14, 2019 16:20
Copy link
Collaborator

@acdlite acdlite left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this mostly looks good. Left some testing comments.

Sunil Pai added 3 commits May 16, 2019 00:21
- pass the mock scheduler warning test,
- rewrite some tests to use Scheduler.yieldValue
- structure concurrent/legacy suites neatly
@threepointone
Copy link
Contributor Author

alright, I updated the PR

  • pass the mock scheduler warning test,
  • rewrite some tests to use Scheduler.yieldValue
  • structure concurrent/legacy suites neatly
  • I also merged from master, and rewrote some failing tests. of note, I had to swap a couple of act calls out with batchedUpdates for a couple of tests that tested in between state.

@@ -347,14 +348,17 @@ describe('ReactHooks', () => {
});
return <Child text={text} />;
}
let root;
act(() => {
root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: If you move the ReactTestRenderer.create call outside act, does it warn? Maybe we can special case null? (I don't like how test renderer's create also updates at the same time, and I'm accustomed to passing null as a workaround.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not warn when you pass null, we only warn on update calls. It will warn if you try to render something with an effect ofc (once #15631 lands) To clarify, this is the behaviour you want, yeah? I'll move it out in this test.

@threepointone
Copy link
Contributor Author

alright, I'm going to land this. there are 2 major todos -

  • docs, which I'm working on
  • discussed with @gaearon, and it was apparent that the missing mock scheduler warning only makes sense in concurrent mode (and the messaging is a but off). maybe this is something we should sovle with the testing build. in any case, am landing the messaging as is, but with the feature flag turned off for oss. will reach out to discuss next steps separately.

@threepointone threepointone merged commit d278a3f into facebook:master May 16, 2019
bvaughn pushed a commit to bvaughn/react that referenced this pull request Aug 13, 2019
This simplifies your test helpers to loop until all timers are flushed (including the ones that get queued after updates), and works in concurrent mode. I also renamed actSuspense to actAsync to be clearer.
"to the top of your tests, or in your framework's global config file -\n\n" +
'As an example, for jest - \n' +
"jest.mock('scheduler', () => require.requireActual('scheduler/unstable_mock'));\n\n" +
'For more info, visit https://fb.me/react-mock-scheduler',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, this short URL was never created 😅 I get redirected to facebook.com

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NMinhNguyen referenced this pull request in enzymejs/react-shallow-renderer Jan 29, 2020
…elding (#15591)

* s/flushPassiveEffects/unstable_flushWithoutYielding

a first crack at flushing the scheduler manually from inside act(). uses unstable_flushWithoutYielding(). The tests that changed, mostly replaced toFlushAndYield(...) with toHaveYielded(). For some tests that tested the state of the tree before flushing effects (but still after updates), I replaced act() with bacthedUpdates().

* ugh lint

* pass build, flushPassiveEffects returns nothing now

* pass test-fire

* flush all work (not just effects), add a compatibility mode

of note, unstable_flushWithoutYielding now returns a boolean much like flushPassiveEffects

* umd build for scheduler/unstable_mock, pass the fixture with it

* add a comment to Shcduler.umd.js for why we're exporting unstable_flushWithoutYielding

* run testsutilsact tests in both sync/concurrent modes

* augh lint

* use a feature flag for the missing mock scheduler warning

I also tried writing a test for it, but couldn't get the scheduler to unmock. included the failing test.

* Update ReactTestUtilsAct-test.js

- pass the mock scheduler warning test,
- rewrite some tests to use Scheduler.yieldValue
- structure concurrent/legacy suites neatly

* pass failing tests in batchedmode-test

* fix pretty/lint/import errors

* pass test-build

* nit: pull .create(null) out of the act() call
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants