From 3175af53f95565ba6f47e5038dbd07dfa186f457 Mon Sep 17 00:00:00 2001 From: cartogram Date: Thu, 9 May 2019 00:21:53 -0400 Subject: [PATCH] Upgrade React 16.9 --- package.json | 4 +- packages/enzyme-utilities/src/index.ts | 26 ++++- packages/react-form/src/hooks/list/list.ts | 3 + .../react-form/src/hooks/test/form.test.tsx | 109 ++++++++++-------- .../src/hooks/tests/mutation.test.tsx | 14 +-- .../src/hooks/tests/query.test.tsx | 29 +++-- .../src/test/ImportRemote.test.tsx | 84 ++++++++++---- packages/react-testing/src/element.ts | 4 +- packages/react-testing/src/errors.ts | 63 ---------- packages/react-testing/src/mount.ts | 1 - packages/react-testing/src/root.tsx | 45 +++++--- yarn.lock | 48 ++++---- 12 files changed, 231 insertions(+), 199 deletions(-) delete mode 100644 packages/react-testing/src/errors.ts diff --git a/package.json b/package.json index 83e82ea386..c416218b6a 100644 --- a/package.json +++ b/package.json @@ -56,9 +56,9 @@ "lerna": "^2.9.0", "plop": "^2.0.0", "prettier": "^1.14.0", - "react": "^16.8.5", + "react": "16.9.0-alpha.0", "react-apollo": "^2.2.3", - "react-dom": "^16.8.5", + "react-dom": "16.9.0-alpha.0", "react-helmet": "^5.2.0", "rimraf": "^2.6.2", "ts-jest": "^23.10.4", diff --git a/packages/enzyme-utilities/src/index.ts b/packages/enzyme-utilities/src/index.ts index 1d1dbf6873..9143479a3f 100644 --- a/packages/enzyme-utilities/src/index.ts +++ b/packages/enzyme-utilities/src/index.ts @@ -1,4 +1,4 @@ -import {act} from 'react-dom/test-utils'; +import {act as reactAct} from 'react-dom/test-utils'; import {ReactWrapper, CommonWrapper} from 'enzyme'; import {get} from 'lodash'; @@ -8,6 +8,8 @@ export type AnyWrapper = | CommonWrapper | CommonWrapper; +const act = reactAct as (func: () => void | Promise) => Promise; + export function trigger(wrapper: AnyWrapper, keypath: string, ...args: any[]) { if (wrapper.length === 0) { throw new Error( @@ -33,19 +35,23 @@ export function trigger(wrapper: AnyWrapper, keypath: string, ...args: any[]) { let returnValue: any; - act(() => { + const promise = act(() => { returnValue = callback(...args); - }); - updateRoot(wrapper); + if (isPromise(returnValue)) { + return (returnValue as unknown) as Promise; + } + }); - if (returnValue instanceof Promise) { - return returnValue.then(ret => { + if (isPromise(returnValue)) { + return Promise.resolve(promise as Promise).then(ret => { updateRoot(wrapper); return ret; }); } + updateRoot(wrapper); + return returnValue; } @@ -56,3 +62,11 @@ function updateRoot(wrapper: AnyWrapper) { export function findById(wrapper: ReactWrapper, id: string) { return wrapper.find({id}).first(); } + +function isPromise(promise: T | Promise): promise is Promise { + return ( + promise != null && + typeof promise === 'object' && + (promise as any).then != null + ); +} diff --git a/packages/react-form/src/hooks/list/list.ts b/packages/react-form/src/hooks/list/list.ts index 5f850877ff..3570a704b9 100755 --- a/packages/react-form/src/hooks/list/list.ts +++ b/packages/react-form/src/hooks/list/list.ts @@ -216,6 +216,9 @@ export function useList( } validate(); }, + setError(error: string) { + dispatch(updateErrorAction({target, error})); + }, }; }, ); diff --git a/packages/react-form/src/hooks/test/form.test.tsx b/packages/react-form/src/hooks/test/form.test.tsx index a7195f4f92..d68ceb30b2 100644 --- a/packages/react-form/src/hooks/test/form.test.tsx +++ b/packages/react-form/src/hooks/test/form.test.tsx @@ -59,7 +59,9 @@ describe('useForm', () => { return (
{submitting &&

loading...

} - {submitErrors.length > 0 &&

{submitErrors.join(', ')}

} + {submitErrors.length > 0 && + submitErrors.map(({message}) =>

{message}

)} +
@@ -69,13 +71,15 @@ describe('useForm', () => {
- {variants.map(({price, optionName, optionValue, id}) => ( -
- - - -
- ))} + {variants.map(({price, optionName, optionValue, id}) => { + return ( +
+ + + +
+ ); + })} @@ -144,7 +148,7 @@ describe('useForm', () => { }); describe('submit', () => { - it('sets submitting to true during submission', () => { + it('sets submitting to true during submission', async () => { const wrapper = mount( { .find(TextField, {label: 'title'})! .trigger('onChange', 'tortoritos, the chip for turtles!'); - wrapper - .find('button', {type: 'submit'})! - .trigger('onClick', clickEvent()); + await wrapper.act(() => { + wrapper + .find('button', {type: 'submit'})! + .trigger('onClick', clickEvent()); + }); expect(wrapper).toContainReactComponent('p', { children: 'loading...', }); }); - // Async act() issues block this test https://github.com/facebook/react/issues/15379 - // eslint-disable-next-line jest/no-disabled-tests - it.skip('sets submitting to false when submission ends', async () => { + it('sets submitting to false when submission ends', async () => { const promise = Promise.resolve(submitSuccess()); const wrapper = mount( promise} />, @@ -177,18 +181,19 @@ describe('useForm', () => { .find(TextField, {label: 'title'})! .trigger('onChange', 'tortoritos, the chip for turtles!'); - wrapper - .find('button', {type: 'submit'})! - .trigger('onClick', clickEvent()); - - await promise; + await wrapper.act(async () => { + await wrapper + .find('button', {type: 'submit'})! + .trigger('onClick', clickEvent()); + await promise; + }); expect(wrapper).not.toContainReactComponent('p', { children: 'loading...', }); }); - it('validates all fields with their latest values before submitting and bails out if any fail', () => { + it('validates all fields with their latest values before submitting and bails out if any fail', async () => { const submitSpy = jest.fn(() => Promise.resolve(submitSuccess())); const product = { ...fakeProduct(), @@ -200,9 +205,11 @@ describe('useForm', () => { wrapper.find(TextField, {label: 'title'})!.trigger('onChange', ''); - wrapper - .find('button', {type: 'submit'})! - .trigger('onClick', clickEvent()); + await wrapper.act(() => { + wrapper + .find('button', {type: 'submit'})! + .trigger('onClick', clickEvent()); + }); expect(submitSpy).not.toHaveBeenCalled(); expect(wrapper).toContainReactComponent('p', { @@ -210,25 +217,26 @@ describe('useForm', () => { }); }); - // Async act() issues block this test https://github.com/facebook/react/issues/15379 - // eslint-disable-next-line jest/no-disabled-tests - it.skip('returns remote submission errors', async () => { + it('returns remote submission errors', async () => { const error = {message: 'The server hates it'}; - const submitSpy = jest.fn(() => Promise.resolve(submitFail([error]))); + const promise = Promise.resolve(submitFail([error])); + const wrapper = mount( - , + promise} />, ); - await wrapper - .find('button', {type: 'submit'})! - .trigger('onClick', clickEvent()); + await wrapper.act(async () => { + await wrapper + .find('button', {type: 'submit'})! + .trigger('onClick', clickEvent()); + }); expect(wrapper).toContainReactComponent('p', { children: error.message, }); }); - // Async act() issues block this test https://github.com/facebook/react/issues/15379 + // This test goes into an infinite render loop // eslint-disable-next-line jest/no-disabled-tests it.skip('propagates remote submission errors to matching fields', async () => { const errors = [ @@ -237,14 +245,20 @@ describe('useForm', () => { message: 'The server hates your price', }, ]; - const submitSpy = jest.fn(() => Promise.resolve(submitFail(errors))); + + const promise = Promise.resolve(submitFail(errors)); + const wrapper = mount( - , + promise} />, ); - await wrapper - .find('button', {type: 'submit'})! - .trigger('onClick', clickEvent()); + await wrapper.act(async () => { + wrapper + .find('button', {type: 'submit'})! + .trigger('onClick', clickEvent()); + + await promise; + }); expect(wrapper).toContainReactComponent(TextField, { error: errors[0].message, @@ -277,27 +291,30 @@ describe('useForm', () => { }); }); - // Async act() issues block this test https://github.com/facebook/react/issues/15379 - // eslint-disable-next-line jest/no-disabled-tests - it.skip('resets errors from previous submissions', async () => { + it('resets errors from previous submissions', async () => { const errors = [ { field: ['variants', '0', 'price'], message: 'The server hates your price', }, ]; - const submitSpy = jest.fn(() => Promise.resolve(submitFail(errors))); + + const promise = Promise.resolve(submitFail(errors)); + const wrapper = mount( - , + promise} />, ); await wrapper .find('button', {type: 'submit'})! .trigger('onClick', clickEvent()); - await wrapper - .find('button', {type: 'reset'})! - .trigger('onClick', clickEvent()); + await wrapper.act(async () => { + await wrapper + .find('button', {type: 'button'})! + .trigger('onClick', clickEvent()); + await promise; + }); expect(wrapper).not.toContainReactComponent(TextField, { error: errors[0].message, diff --git a/packages/react-graphql/src/hooks/tests/mutation.test.tsx b/packages/react-graphql/src/hooks/tests/mutation.test.tsx index b296ae9136..5ef6f46ffb 100644 --- a/packages/react-graphql/src/hooks/tests/mutation.test.tsx +++ b/packages/react-graphql/src/hooks/tests/mutation.test.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import {act} from 'react-dom/test-utils'; import gql from 'graphql-tag'; import {createGraphQLFactory} from '@shopify/graphql-testing'; @@ -40,12 +41,7 @@ const mockMutationData = { updatePet: {id: 'new-pet-id-123', __typename: 'Cat'}, }; -// This is skip because current `act` wrapper does not support async operation -// The test will pass if we update to `react-dom` v16.9.0-alpha.0 -// and wrap `graphQL.resolveAll()` in an `act` -// https://github.com/facebook/react/issues/14769#issuecomment-481251431 -// eslint-disable-next-line jest/no-disabled-tests -describe.skip('useMutation', () => { +describe('useMutation', () => { beforeEach(() => { prepareAsyncReactTasks(); }); @@ -63,7 +59,11 @@ describe.skip('useMutation', () => { ); mockMutation.find('button')!.trigger('onClick', undefined as any); - await graphQL.resolveAll(); + + // @ts-ignore + await act(async () => { + await graphQL.resolveAll(); + }); expect(renderPropSpy).toHaveBeenLastCalledWith( expect.objectContaining({data: mockMutationData}), diff --git a/packages/react-graphql/src/hooks/tests/query.test.tsx b/packages/react-graphql/src/hooks/tests/query.test.tsx index 8dbb91fe8e..ffd77d0f7e 100644 --- a/packages/react-graphql/src/hooks/tests/query.test.tsx +++ b/packages/react-graphql/src/hooks/tests/query.test.tsx @@ -125,11 +125,16 @@ describe('useQuery', () => { const graphQL = createGraphQL({PetQuery: mockData}); const renderPropSpy = jest.fn(() => null); - // below line should be wrapped in act once we update to `react-dom` v16.9.0-alpha.0 - await MockQueryComponent.resolve(); - await mountWithGraphQL({renderPropSpy}, { - graphQL, - skipInitialGraphQL: true, + const wrapper = await mountWithGraphQL( + {renderPropSpy}, + { + graphQL, + skipInitialGraphQL: true, + }, + ); + + await wrapper.act(async () => { + await MockQueryComponent.resolve(); }); expect(renderPropSpy).toHaveBeenLastCalledWith( @@ -152,10 +157,16 @@ describe('useQuery', () => { const graphQL = createGraphQL({PetQuery: mockData}); const renderPropSpy = jest.fn(() => null); - // below line should be wrapped in act once we update to `react-dom` v16.9.0-alpha.0 - await MockQueryComponent.resolve(); - await mountWithGraphQL({renderPropSpy}, { - graphQL, + const wrapper = await mountWithGraphQL( + {renderPropSpy}, + { + graphQL, + }, + ); + + await wrapper.act(async () => { + await MockQueryComponent.resolve(); + await graphQL.resolveAll(); }); expect(renderPropSpy).toHaveBeenLastCalledWith( diff --git a/packages/react-import-remote/src/test/ImportRemote.test.tsx b/packages/react-import-remote/src/test/ImportRemote.test.tsx index f14ce3f55c..fe9d3549a0 100644 --- a/packages/react-import-remote/src/test/ImportRemote.test.tsx +++ b/packages/react-import-remote/src/test/ImportRemote.test.tsx @@ -45,10 +45,23 @@ describe('', () => { onImported: noop, }; + function createResolvableLoad(value?: any) { + const promise = Promise.resolve(value); + load.mockImplementationOnce(() => promise); + + return () => promise; + } + describe('source and getImport()', () => { - it('uses the props as arguments for load()', () => { + it('uses the props as arguments for load()', async () => { + const resolve = createResolvableLoad(); const nonce = ''; - mount(); + const importRemote = mount(); + + await importRemote.act(async () => { + await resolve(); + }); + expect(load).toHaveBeenCalledWith( mockProps.source, mockProps.getImport, @@ -56,9 +69,15 @@ describe('', () => { ); }); - it('uses the nonce prop as argument for load()', () => { + it('uses the nonce prop as argument for load()', async () => { + const resolve = createResolvableLoad(); const nonce = '1a2b3c'; - mount(); + const importRemote = mount(); + + await importRemote.act(async () => { + await resolve(); + }); + expect(load).toHaveBeenCalledWith( mockProps.source, mockProps.getImport, @@ -66,9 +85,10 @@ describe('', () => { ); }); - it('imports a new global if the source changes', () => { + it('imports a new global if the source changes', async () => { const nonce = ''; const importRemote = mount(); + expect(load).toHaveBeenCalledWith( mockProps.source, mockProps.getImport, @@ -77,27 +97,31 @@ describe('', () => { const newSource = 'https://bar.com/foo.js'; - importRemote.setProps({source: newSource}); + // we need to have the async here otherwise we will get + // a console error an `act(...)` here + // eslint-disable-next-line require-await + await importRemote.act(async () => { + importRemote.setProps({source: newSource}); + }); + expect(load).toHaveBeenCalledWith(newSource, mockProps.getImport, nonce); }); }); - // async act is available in React 16.9.0, when we have upgraded the following - // tests can be enabled. https://github.com/Shopify/quilt/pull/688 - // eslint-disable-next-line jest/no-disabled-tests - describe.skip('onImported()', () => { + + describe('onImported()', () => { it('is called with the result of loading the script when successful', async () => { const result = 'foo'; - const promise = Promise.resolve(result); const spy = jest.fn(); - load.mockImplementation(() => promise); + const resolve = createResolvableLoad(result); - const importRemote = await mount( + const importRemote = mount( , ); - importRemote.act(async () => { - await promise; + await importRemote.act(async () => { + await resolve; }); + expect(spy).toHaveBeenCalledWith(result); }); @@ -107,11 +131,11 @@ describe('', () => { const spy = jest.fn(); load.mockImplementation(() => promise); - const importRemote = await mount( + const importRemote = mount( , ); - importRemote.act(async () => { + await importRemote.act(async () => { try { await promise; // eslint-disable-next-line no-empty @@ -123,15 +147,25 @@ describe('', () => { }); describe('preconnect', () => { - it('does not render any preconnect link by default', () => { + it('does not render any preconnect link by default', async () => { + const resolve = createResolvableLoad(); const importRemote = mount(); + await importRemote.act(async () => { + await resolve(); + }); + expect(importRemote).not.toContainReactComponent(Preconnect); }); - it('creates a preconnect link with the source’s origin when preconnecting is requested', () => { + it('creates a preconnect link with the source’s origin when preconnecting is requested', async () => { + const resolve = createResolvableLoad(); const importRemote = mount(); + await importRemote.act(async () => { + await resolve(); + }); + expect(importRemote).toContainReactComponent(Preconnect, { source: new URL(mockProps.source).origin, }); @@ -139,21 +173,21 @@ describe('', () => { }); describe('defer', () => { - it('does not call load until idle when defer is DeferTiming.Idle', () => { + it('does not call load until idle when defer is DeferTiming.Idle', async () => { const importRemote = mount( , ); expect(load).not.toHaveBeenCalled(); - importRemote.act(() => { - requestIdleCallback.runIdleCallbacks(); + await importRemote.act(async () => { + await requestIdleCallback.runIdleCallbacks(); }); expect(load).toHaveBeenCalled(); }); - it('does not call load until the IntersectionObserver’s onIntersecting when defer is DeferTiming.InViewport', () => { + it('does not call load until the IntersectionObserver’s onIntersecting when defer is DeferTiming.InViewport', async () => { intersectionObserver.simulate({ isIntersecting: false, }); @@ -164,8 +198,8 @@ describe('', () => { expect(load).not.toHaveBeenCalled(); - importRemote.act(() => { - intersectionObserver.simulate({ + await importRemote.act(async () => { + await intersectionObserver.simulate({ isIntersecting: true, }); }); diff --git a/packages/react-testing/src/element.ts b/packages/react-testing/src/element.ts index bd12d39ab7..4b7580fb70 100644 --- a/packages/react-testing/src/element.ts +++ b/packages/react-testing/src/element.ts @@ -173,7 +173,7 @@ export class Element { trigger>( prop: K, ...args: DeepPartialArguments> - ): ReturnType> { + ): Promise>> { return this.root.act(() => { const propValue = this.props[prop]; @@ -187,7 +187,7 @@ export class Element { }); } - triggerKeypath(keypath: string, ...args: unknown[]): T { + triggerKeypath(keypath: string, ...args: unknown[]): Promise { return this.root.act(() => { const {props} = this; const parts = keypath.split(/[.[\]]/g).filter(Boolean); diff --git a/packages/react-testing/src/errors.ts b/packages/react-testing/src/errors.ts deleted file mode 100644 index c1dcb6dc6c..0000000000 --- a/packages/react-testing/src/errors.ts +++ /dev/null @@ -1,63 +0,0 @@ -const IGNORABLE_ERROR_EVENT_MESSAGES = [ - // This is part of the window.onError error object when a React - // update errors out - /at renderRoot/, -]; - -const IGNORABLE_TEST_ERRORS = [ - // This is the log for the actual error that got thrown - /at mountIndeterminateComponent/, - // This line follows any error thrown by a component - /The above error occurred in (the <.*>|one of your React) components?:/, - // This line comes up whenever an error happens as the result of something - // that was being done within an `act` callback - /was not wrapped in act\(\.\.\.\)/, -]; - -export function withIgnoredReactLogs(run: () => T) { - /* eslint-disable no-console */ - const originalConsoleError = console.error; - - const consoleError = (...args: any[]) => { - const [firstArgument] = args; - if ( - (typeof firstArgument === 'string' && - IGNORABLE_TEST_ERRORS.some(regex => regex.test(firstArgument))) || - (firstArgument instanceof Error && - firstArgument.stack != null && - IGNORABLE_TEST_ERRORS.some(regex => - regex.test(firstArgument.stack || ''), - )) - ) { - return; - } - - originalConsoleError.call(console, ...args); - }; - - function handleErrorEvent(event: ErrorEvent) { - const {error} = event; - - // I want to silence all errors and know what I'm doing - if ( - error != null && - IGNORABLE_ERROR_EVENT_MESSAGES.some( - ignore => typeof error.stack === 'string' && ignore.test(error.stack), - ) - ) { - event.preventDefault(); - } - } - - window.addEventListener('error', handleErrorEvent); - - console.error = consoleError; - - try { - return run(); - } finally { - console.error = originalConsoleError; - window.removeEventListener('error', handleErrorEvent); - } - /* eslint-enable no-console */ -} diff --git a/packages/react-testing/src/mount.ts b/packages/react-testing/src/mount.ts index c67f852541..963d546d99 100644 --- a/packages/react-testing/src/mount.ts +++ b/packages/react-testing/src/mount.ts @@ -1,6 +1,5 @@ import * as React from 'react'; import {IfAllOptionalKeys} from '@shopify/useful-types'; - import {Root} from './root'; import {Element} from './element'; diff --git a/packages/react-testing/src/root.tsx b/packages/react-testing/src/root.tsx index 31efd84dfa..2dea422092 100644 --- a/packages/react-testing/src/root.tsx +++ b/packages/react-testing/src/root.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import {render, unmountComponentAtNode} from 'react-dom'; -import {act} from 'react-dom/test-utils'; +import {act as reactAct} from 'react-dom/test-utils'; import { Arguments, Props as PropsForComponent, @@ -16,7 +16,8 @@ import { FunctionKeys, DeepPartialArguments, } from './types'; -import {withIgnoredReactLogs} from './errors'; + +const act = reactAct as (func: () => void | Promise) => Promise; // eslint-disable-next-line typescript/no-var-requires const {findCurrentFiberUsingSlowPath} = require('react-reconciler/reflection'); @@ -76,26 +77,34 @@ export class Root { act(action: () => T, {update = true} = {}): T { let result!: T; - if (this.acting) { return action(); } this.acting = true; - withIgnoredReactLogs(() => - act(() => { - result = action(); - }), - ); + const afterResolve = () => { + if (update) { + this.update(); + } + this.acting = false; - if (update) { - this.update(); - } + return result; + }; - this.acting = false; + const promise = act(() => { + result = action(); + + if (isPromise(result)) { + return (result as unknown) as Promise; + } + }); - return result; + if (isPromise(result)) { + return Promise.resolve(promise).then(afterResolve) as any; + } + + return afterResolve(); } html() { @@ -141,7 +150,7 @@ export class Root { trigger>( prop: K, ...args: DeepPartialArguments> - ): ReturnType> { + ): Promise>> { return this.withRoot(root => root.trigger(prop, ...(args as any))); } @@ -287,3 +296,11 @@ function childrenToTree(fiber: Fiber | null, root: Root) { return {children, descendants}; } + +function isPromise(promise: T | Promise): promise is Promise { + return ( + promise != null && + typeof promise === 'object' && + (promise as any).then != null + ); +} diff --git a/yarn.lock b/yarn.lock index 6af2c5b47b..259675e4f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7222,25 +7222,25 @@ react-apollo@^2.2.3: ts-invariant "^0.3.0" tslib "^1.9.3" -react-dom@^16.8.1: - version "16.8.1" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.1.tgz#ec860f98853d09d39bafd3a6f1e12389d283dbb4" - integrity sha512-N74IZUrPt6UiDjXaO7UbDDFXeUXnVhZzeRLy/6iqqN1ipfjrhR60Bp5NuBK+rv3GMdqdIuwIl22u1SYwf330bg== +react-dom@16.9.0-alpha.0: + version "16.9.0-alpha.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.9.0-alpha.0.tgz#9dfaec18ac1a500fa72cab7b70f2ae29d0cd7716" + integrity sha512-BQ5gN42yIPuTnBvE6K9vSjNfDRpSNcYCs2sUx9XR5VaWKwlHTt3G6qIWK6zdXy8TYKb1+IxpsAI0RtbRdXQZ2A== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.13.1" + scheduler "^0.14.0-alpha.0" -react-dom@^16.8.5: - version "16.8.5" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.5.tgz#b3e37d152b49e07faaa8de41fdf562be3463335e" - integrity sha512-VIEIvZLpFafsfu4kgmftP5L8j7P1f0YThfVTrANMhZUFMDOsA6e0kfR6wxw/8xxKs4NB59TZYbxNdPCDW34x4w== +react-dom@^16.8.1: + version "16.8.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.1.tgz#ec860f98853d09d39bafd3a6f1e12389d283dbb4" + integrity sha512-N74IZUrPt6UiDjXaO7UbDDFXeUXnVhZzeRLy/6iqqN1ipfjrhR60Bp5NuBK+rv3GMdqdIuwIl22u1SYwf330bg== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.13.5" + scheduler "^0.13.1" react-helmet@^5.2.0: version "5.2.0" @@ -7318,25 +7318,25 @@ react-test-renderer@^16.0.0-0: prop-types "^15.6.0" react-is "^16.3.0" -react@^16.8.1: - version "16.8.1" - resolved "https://registry.yarnpkg.com/react/-/react-16.8.1.tgz#ae11831f6cb2a05d58603a976afc8a558e852c4a" - integrity sha512-wLw5CFGPdo7p/AgteFz7GblI2JPOos0+biSoxf1FPsGxWQZdN/pj6oToJs1crn61DL3Ln7mN86uZ4j74p31ELQ== +react@16.9.0-alpha.0: + version "16.9.0-alpha.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.9.0-alpha.0.tgz#e350f3d8af36e3251079cbc90d304620e2f78ccb" + integrity sha512-y4bu7rJvtnPPsIwOj7sp5Y2SqlOb0jFupfkdjWxxn8ZeqzUARgpR9wJBUVwW1/QosVdOblmApjo/j6iiAXnebA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.13.1" + scheduler "^0.14.0-alpha.0" -react@^16.8.5: - version "16.8.5" - resolved "https://registry.yarnpkg.com/react/-/react-16.8.5.tgz#49be3b655489d74504ad994016407e8a0445de66" - integrity sha512-daCb9TD6FZGvJ3sg8da1tRAtIuw29PbKZW++NN4wqkbEvxL+bZpaaYb4xuftW/SpXmgacf1skXl/ddX6CdOlDw== +react@^16.8.1: + version "16.8.1" + resolved "https://registry.yarnpkg.com/react/-/react-16.8.1.tgz#ae11831f6cb2a05d58603a976afc8a558e852c4a" + integrity sha512-wLw5CFGPdo7p/AgteFz7GblI2JPOos0+biSoxf1FPsGxWQZdN/pj6oToJs1crn61DL3Ln7mN86uZ4j74p31ELQ== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.13.5" + scheduler "^0.13.1" read-cmd-shim@^1.0.1: version "1.0.1" @@ -7822,10 +7822,10 @@ scheduler@^0.13.4: loose-envify "^1.1.0" object-assign "^4.1.1" -scheduler@^0.13.5: - version "0.13.5" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.5.tgz#b7226625167041298af3b98088a9dbbf6d7733a8" - integrity sha512-K98vjkQX9OIt/riLhp6F+XtDPtMQhqNcf045vsh+pcuvHq+PHy1xCrH3pq1P40m6yR46lpVvVhKdEOtnimuUJw== +scheduler@^0.14.0-alpha.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.14.0.tgz#b392c23c9c14bfa2933d4740ad5603cc0d59ea5b" + integrity sha512-9CgbS06Kki2f4R9FjLSITjZo5BZxPsryiRNyL3LpvrM9WxcVmhlqAOc9E+KQbeI2nqej4JIIbOsfdL51cNb4Iw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1"