diff --git a/README.md b/README.md index 2bf662c11..882c2a7a0 100644 --- a/README.md +++ b/README.md @@ -118,11 +118,12 @@ The [public API](https://callstack.github.io/react-native-testing-library/docs/a - [`render`](https://callstack.github.io/react-native-testing-library/docs/api#render) – deeply renders given React element and returns helpers to query the output components. - [`fireEvent`](https://callstack.github.io/react-native-testing-library/docs/api#fireevent) - invokes named event handler on the element. -- [`waitForElement`](https://callstack.github.io/react-native-testing-library/docs/api#waitforelement) - waits for non-deterministic periods of time until your element appears or times out. +- [`waitFor`](https://callstack.github.io/react-native-testing-library/docs/api#waitfor) - waits for non-deterministic periods of time until your element appears or times out. - [`within`](https://callstack.github.io/react-native-testing-library/docs/api#within) - creates a queries object scoped for given element. -- [`flushMicrotasksQueue`](https://callstack.github.io/react-native-testing-library/docs/api#flushmicrotasksqueue) - waits for microtasks queue to flush. -**Note to users who are more familiar with `react-testing-library`:** This API does not expose `cleanup` because it doesn't interact with the DOM. There's nothing to clean up. +## Migration Guides + +- [Migration to 2.0](https://callstack.github.io/react-native-testing-library/docs/migration-v2) ## Made with ❤️ at Callstack diff --git a/babel.config.js b/babel.config.js index f842b77fc..1d7a6bcf8 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,3 +1,16 @@ module.exports = { - presets: ['module:metro-react-native-babel-preset'], + presets: [ + '@babel/preset-flow', + '@babel/preset-react', + [ + '@babel/preset-env', + { + targets: { + node: '10', + }, + bugfixes: true, + }, + ], + ], + plugins: ['@babel/plugin-proposal-class-properties'], }; diff --git a/dont-cleanup-after-each.js b/dont-cleanup-after-each.js new file mode 100644 index 000000000..d9a79f173 --- /dev/null +++ b/dont-cleanup-after-each.js @@ -0,0 +1 @@ +process.env.RNTL_SKIP_AUTO_CLEANUP = true; diff --git a/examples/reactnavigation/src/__tests__/AppNavigator.test.js b/examples/reactnavigation/src/__tests__/AppNavigator.test.js index b2f4a85c1..f9731215b 100644 --- a/examples/reactnavigation/src/__tests__/AppNavigator.test.js +++ b/examples/reactnavigation/src/__tests__/AppNavigator.test.js @@ -1,6 +1,6 @@ import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; -import { render, fireEvent, cleanup } from 'react-native-testing-library'; +import { render, fireEvent } from 'react-native-testing-library'; import AppNavigator from '../AppNavigator'; @@ -8,8 +8,6 @@ import AppNavigator from '../AppNavigator'; jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper'); describe('Testing react navigation', () => { - afterEach(cleanup); - test('page contains the header and 10 items', () => { const component = ( diff --git a/examples/redux/components/AddTodo.test.js b/examples/redux/components/AddTodo.test.js index c90344cf2..edbbcc163 100644 --- a/examples/redux/components/AddTodo.test.js +++ b/examples/redux/components/AddTodo.test.js @@ -1,12 +1,10 @@ import React from 'react'; import { Provider } from 'react-redux'; -import { cleanup, fireEvent, render } from 'react-native-testing-library'; +import { fireEvent, render } from 'react-native-testing-library'; import configureStore from '../store'; import AddTodo from './AddTodo'; describe('Application test', () => { - afterEach(cleanup); - test('adds a new test when entry has been included', () => { const store = configureStore(); diff --git a/examples/redux/components/TodoList.test.js b/examples/redux/components/TodoList.test.js index 80b27f05f..595fcea27 100644 --- a/examples/redux/components/TodoList.test.js +++ b/examples/redux/components/TodoList.test.js @@ -1,12 +1,10 @@ import React from 'react'; import { Provider } from 'react-redux'; -import { cleanup, fireEvent, render } from 'react-native-testing-library'; +import { fireEvent, render } from 'react-native-testing-library'; import configureStore from '../store'; import TodoList from './TodoList'; describe('Application test', () => { - afterEach(cleanup); - test('it should execute with a store with 4 elements', () => { const initialState = { todos: [ diff --git a/examples/redux/reducers/todoReducer.js b/examples/redux/reducers/todoReducer.js index f55d4c3e6..f1e20731c 100644 --- a/examples/redux/reducers/todoReducer.js +++ b/examples/redux/reducers/todoReducer.js @@ -6,7 +6,6 @@ export default function todoReducer(state = [], action) { return state.concat(action.payload); case actions.REMOVE: - console.log(action); return state.filter((todo) => todo.id !== action.payload.id); case actions.MODIFY: diff --git a/package.json b/package.json index 9bb055202..a7f2844bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-testing-library", - "version": "1.14.0", + "version": "2.0.0-rc.1", "description": "Simple React Native testing utilities helping you write better tests with less effort", "main": "build/index.js", "typings": "./typings/index.d.ts", @@ -21,6 +21,10 @@ "devDependencies": { "@babel/cli": "^7.8.4", "@babel/core": "^7.9.0", + "@babel/plugin-proposal-class-properties": "^7.8.3", + "@babel/preset-env": "^7.9.6", + "@babel/preset-flow": "^7.9.0", + "@babel/preset-react": "^7.9.4", "@callstack/eslint-config": "^10.0.0", "@release-it/conventional-changelog": "^1.1.0", "@testing-library/jest-native": "~3.1.0", @@ -34,7 +38,6 @@ "flow-bin": "^0.122.0", "flow-copy-source": "^2.0.9", "jest": "^26.0.1", - "metro-react-native-babel-preset": "^0.58.0", "react": "^16.13.1", "react-native": "^0.63.0-rc.1", "react-test-renderer": "^16.13.1", diff --git a/pure.js b/pure.js new file mode 100644 index 000000000..bced0b756 --- /dev/null +++ b/pure.js @@ -0,0 +1,2 @@ +// makes it so people can import from 'react-native-testing-library/pure' +module.exports = require('./build/pure'); diff --git a/src/__tests__/__snapshots__/debug.test.js.snap b/src/__tests__/__snapshots__/debug.test.js.snap deleted file mode 100644 index b1732ecc6..000000000 --- a/src/__tests__/__snapshots__/debug.test.js.snap +++ /dev/null @@ -1,57 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`debug 1`] = ` -" - -" -`; - -exports[`debug.deep 1`] = ` -" - - Press me 0 - -" -`; - -exports[`debug.deep async test 1`] = ` -" - - Press me 1 - -" -`; diff --git a/src/__tests__/__snapshots__/render.test.js.snap b/src/__tests__/__snapshots__/render.test.js.snap index d3c4b4d93..55a88ffb7 100644 --- a/src/__tests__/__snapshots__/render.test.js.snap +++ b/src/__tests__/__snapshots__/render.test.js.snap @@ -150,12 +150,12 @@ exports[`debug: shallow 1`] = ` underlineColorAndroid=\\"transparent\\" value=\\"I inspected freshie\\" /> - + @@ -200,12 +200,12 @@ exports[`debug: shallow with message 1`] = ` underlineColorAndroid=\\"transparent\\" value=\\"I inspected freshie\\" /> - + diff --git a/src/__tests__/__snapshots__/shallow.test.js.snap b/src/__tests__/__snapshots__/shallow.test.js.snap deleted file mode 100644 index ac70b9743..000000000 --- a/src/__tests__/__snapshots__/shallow.test.js.snap +++ /dev/null @@ -1,21 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`shallow rendering React Test Instance 1`] = ` - - Press me - -`; - -exports[`shallow rendering React elements 1`] = ` - - - Press me - - -`; diff --git a/src/__tests__/auto-cleanup-skip.js b/src/__tests__/auto-cleanup-skip.js new file mode 100644 index 000000000..eece886ab --- /dev/null +++ b/src/__tests__/auto-cleanup-skip.js @@ -0,0 +1,39 @@ +import React from 'react'; +import { View } from 'react-native'; + +let render; +beforeAll(() => { + process.env.RNTL_SKIP_AUTO_CLEANUP = 'true'; + const rtl = require('../'); + render = rtl.render; +}); + +let isMounted = false; + +class Test extends React.Component<*> { + componentDidMount() { + isMounted = true; + } + + componentWillUnmount() { + isMounted = false; + if (this.props.onUnmount) { + this.props.onUnmount(); + } + } + render() { + return ; + } +} + +// This just verifies that by importing RNTL in pure mode in an environment which supports +// afterEach (like jest) we won't get automatic cleanup between tests. +test('component is mounted, but not umounted before test ends', () => { + const fn = jest.fn(); + render(); + expect(fn).not.toHaveBeenCalled(); +}); + +test('component is NOT automatically umounted after first test ends', () => { + expect(isMounted).toEqual(true); +}); diff --git a/src/__tests__/auto-cleanup.js b/src/__tests__/auto-cleanup.js new file mode 100644 index 000000000..5a26d7c8f --- /dev/null +++ b/src/__tests__/auto-cleanup.js @@ -0,0 +1,33 @@ +import React from 'react'; +import { View } from 'react-native'; +import { render } from '..'; + +let isMounted = false; + +class Test extends React.Component<*> { + componentDidMount() { + isMounted = true; + } + + componentWillUnmount() { + isMounted = false; + if (this.props.onUnmount) { + this.props.onUnmount(); + } + } + render() { + return ; + } +} + +// This just verifies that by importing RNTL in an environment which supports afterEach (like jest) +// we'll get automatic cleanup between tests. +test('component is mounted, but not umounted before test ends', () => { + const fn = jest.fn(); + render(); + expect(fn).not.toHaveBeenCalled(); +}); + +test('component is automatically umounted after first test ends', () => { + expect(isMounted).toEqual(false); +}); diff --git a/src/__tests__/cleanup.test.js b/src/__tests__/cleanup.test.js index 7ce5bfc46..1ccb752b6 100644 --- a/src/__tests__/cleanup.test.js +++ b/src/__tests__/cleanup.test.js @@ -2,7 +2,7 @@ /* eslint-disable react/no-multi-comp */ import React from 'react'; import { View } from 'react-native'; -import { cleanup, render } from '..'; +import { cleanup, render } from '../pure'; class Test extends React.Component<*> { componentWillUnmount() { diff --git a/src/__tests__/debug.test.js b/src/__tests__/debug.test.js deleted file mode 100644 index baf350275..000000000 --- a/src/__tests__/debug.test.js +++ /dev/null @@ -1,88 +0,0 @@ -// @flow -/* eslint-disable no-console */ -import React from 'react'; -import { TouchableOpacity, Text } from 'react-native'; -import stripAnsi from 'strip-ansi'; -import { debug, render, fireEvent, flushMicrotasksQueue } from '..'; -import debugShallow from '../helpers/debugShallow'; - -type ConsoleLogMock = JestMockFn, void>; - -function TextComponent({ text }) { - return {text}; -} - -class Button extends React.Component { - state = { counter: 0 }; - - onPress = async () => { - await Promise.resolve(); - - this.setState({ counter: 1 }); - this.props.onPress(); - }; - - render() { - return ( - - - - ); - } -} - -test('debug', () => { - jest.spyOn(console, 'log').mockImplementation((x) => x); - const component = + First Text Second Text {test} @@ -109,51 +109,18 @@ test('getAllByTestId, queryAllByTestId', () => { expect(queryAllByTestId('nonExistentTestId')).toHaveLength(0); }); -test('getByName, queryByName', () => { - const { getByText, getByName, queryByName } = render(); - const bananaFresh = getByText('not fresh'); - const button = getByName('Button'); - - button.props.onPress(); - - expect(bananaFresh.props.children).toBe('fresh'); - - const sameButton = getByName(Button); - sameButton.props.onPress(); - - expect(bananaFresh.props.children).toBe('not fresh'); - expect(() => getByName('InExistent')).toThrow('No instances found'); - expect(() => getByName(Text)).toThrow('Expected 1 but found 6'); - - expect(queryByName('Button')).toBe(button); - expect(queryByName('InExistent')).toBeNull(); -}); - -test('getAllByName, queryAllByName', () => { - const { getAllByName, queryAllByName } = render(); - const [text, status, button] = getAllByName('Text'); - - expect(text.props.children).toBe('Is the banana fresh?'); - expect(status.props.children).toBe('not fresh'); - expect(button.props.children).toBe('Change freshness!'); - expect(() => getAllByName('InExistent')).toThrow('No instances found'); - - expect(queryAllByName('Text')[1]).toBe(status); - expect(queryAllByName('InExistent')).toHaveLength(0); -}); - -test('getAllByType, queryAllByType', () => { - const { getAllByType, queryAllByType } = render(); - const [text, status, button] = getAllByType(Text); +test('UNSAFE_getAllByType, UNSAFE_queryAllByType', () => { + const { UNSAFE_getAllByType, UNSAFE_queryAllByType } = render(); + const [text, status, button] = UNSAFE_getAllByType(Text); const InExistent = () => null; expect(text.props.children).toBe('Is the banana fresh?'); expect(status.props.children).toBe('not fresh'); expect(button.props.children).toBe('Change freshness!'); - expect(() => getAllByType(InExistent)).toThrow('No instances found'); + expect(() => UNSAFE_getAllByType(InExistent)).toThrow('No instances found'); - expect(queryAllByType(Text)[1]).toBe(status); - expect(queryAllByType(InExistent)).toHaveLength(0); + expect(UNSAFE_queryAllByType(Text)[1]).toBe(status); + expect(UNSAFE_queryAllByType(InExistent)).toHaveLength(0); }); test('getByText, queryByText', () => { @@ -267,38 +234,37 @@ test('getAllByDisplayValue, queryAllByDisplayValue', () => { expect(queryAllByDisplayValue('no value')).toHaveLength(0); }); -test('getByProps, queryByProps', () => { - const { getByProps, queryByProps } = render(); - const primaryType = getByProps({ type: 'primary' }); +test('UNSAFE_getByProps, UNSAFE_queryByProps', () => { + const { UNSAFE_getByProps, UNSAFE_queryByProps } = render(); + const primaryType = UNSAFE_getByProps({ type: 'primary' }); expect(primaryType.props.children).toBe('Change freshness!'); - expect(() => getByProps({ type: 'inexistent' })).toThrow( + expect(() => UNSAFE_getByProps({ type: 'inexistent' })).toThrow( 'No instances found' ); - expect(queryByProps({ type: 'primary' })).toBe(primaryType); - expect(queryByProps({ type: 'inexistent' })).toBeNull(); + expect(UNSAFE_queryByProps({ type: 'primary' })).toBe(primaryType); + expect(UNSAFE_queryByProps({ type: 'inexistent' })).toBeNull(); }); -test('getAllByProp, queryAllByProps', () => { - const { getAllByProps, queryAllByProps } = render(); - const primaryTypes = getAllByProps({ type: 'primary' }); +test('UNSAFE_getAllByProp, UNSAFE_queryAllByProps', () => { + const { UNSAFE_getAllByProps, UNSAFE_queryAllByProps } = render(); + const primaryTypes = UNSAFE_getAllByProps({ type: 'primary' }); expect(primaryTypes).toHaveLength(1); - expect(() => getAllByProps({ type: 'inexistent' })).toThrow( + expect(() => UNSAFE_getAllByProps({ type: 'inexistent' })).toThrow( 'No instances found' ); - expect(queryAllByProps({ type: 'primary' })).toEqual(primaryTypes); - expect(queryAllByProps({ type: 'inexistent' })).toHaveLength(0); + expect(UNSAFE_queryAllByProps({ type: 'primary' })).toEqual(primaryTypes); + expect(UNSAFE_queryAllByProps({ type: 'inexistent' })).toHaveLength(0); }); test('update', () => { const fn = jest.fn(); - const { getByName, update, rerender } = render(); - const button = getByName('Button'); + const { getByText, update, rerender } = render(); - button.props.onPress(); + fireEvent.press(getByText('Change freshness!')); update(); rerender(); @@ -314,7 +280,7 @@ test('unmount', () => { }); test('toJSON', () => { - const { toJSON } = render(); + const { toJSON } = render(press me); expect(toJSON()).toMatchSnapshot(); }); @@ -345,9 +311,9 @@ test('debug', () => { test('debug changing component', () => { jest.spyOn(console, 'log').mockImplementation((x) => x); - const { getByProps, debug } = render(); + const { UNSAFE_getByProps, debug } = render(); - fireEvent.press(getByProps({ type: 'primary' })); + fireEvent.press(UNSAFE_getByProps({ type: 'primary' })); debug(); diff --git a/src/__tests__/shallow.test.js b/src/__tests__/shallow.test.js deleted file mode 100644 index a31af6c12..000000000 --- a/src/__tests__/shallow.test.js +++ /dev/null @@ -1,27 +0,0 @@ -// @flow -import React from 'react'; -import { View, Text } from 'react-native'; -import { shallow, render } from '..'; - -type Props = {| - +dummyID?: string, -|}; - -const TextPress = ({ dummyID }: Props) => ( - - Press me - -); - -test('shallow rendering React elements', () => { - const { output } = shallow(); - - expect(output).toMatchSnapshot(); -}); - -test('shallow rendering React Test Instance', () => { - const { getByText } = render(); - const { output } = shallow(getByText('Press me')); - - expect(output).toMatchSnapshot(); -}); diff --git a/src/__tests__/waitForElement.test.js b/src/__tests__/waitFor.test.js similarity index 67% rename from src/__tests__/waitForElement.test.js rename to src/__tests__/waitFor.test.js index 8867a4a5e..e38f05c44 100644 --- a/src/__tests__/waitForElement.test.js +++ b/src/__tests__/waitFor.test.js @@ -1,7 +1,7 @@ // @flow import React from 'react'; import { View, Text, TouchableOpacity } from 'react-native'; -import { render, fireEvent, waitForElement } from '..'; +import { render, fireEvent, waitFor } from '..'; class Banana extends React.Component { changeFresh = () => { @@ -36,23 +36,29 @@ class BananaContainer extends React.Component<{}, any> { } test('waits for element until it stops throwing', async () => { - const { getByText, getByName, queryByText } = render(); + const { getByText, queryByText } = render(); - fireEvent.press(getByName('TouchableOpacity')); + fireEvent.press(getByText('Change freshness!')); expect(queryByText('Fresh')).toBeNull(); - const freshBananaText = await waitForElement(() => getByText('Fresh')); + const freshBananaText = await waitFor(() => getByText('Fresh')); expect(freshBananaText.props.children).toBe('Fresh'); }); test('waits for element until timeout is met', async () => { - const { getByText, getByName } = render(); + const { getByText } = render(); - fireEvent.press(getByName('TouchableOpacity')); + fireEvent.press(getByText('Change freshness!')); - await expect(waitForElement(() => getByText('Fresh'), 100)).rejects.toThrow(); + await expect( + waitFor(() => getByText('Fresh'), { timeout: 100 }) + ).rejects.toThrow(); + + // Async action ends after 300ms and we only waited 100ms, so we need to wait + // for the remaining async actions to finish + await waitFor(() => getByText('Fresh')); }); test('waits for element with custom interval', async () => { @@ -61,7 +67,7 @@ test('waits for element with custom interval', async () => { }); try { - await waitForElement(() => mockFn(), 400, 200); + await waitFor(() => mockFn(), { timeout: 400, interval: 200 }); } catch (e) { // suppress } @@ -77,7 +83,7 @@ test('works with fake timers', async () => { }); try { - waitForElement(() => mockFn(), 400, 200); + waitFor(() => mockFn(), { timeout: 400, interval: 200 }); } catch (e) { // suppress } diff --git a/src/debug.js b/src/debug.js deleted file mode 100644 index 807eaa571..000000000 --- a/src/debug.js +++ /dev/null @@ -1,42 +0,0 @@ -// @flow -/* eslint-disable no-console */ -import * as React from 'react'; -import render from './render'; -import debugShallow from './helpers/debugShallow'; -import debugDeep from './helpers/debugDeep'; -import format from './helpers/format'; - -/** - * Log pretty-printed deep test component instance - */ -function debugDeepElementOrInstance( - instance: React.Element | ?ReactTestRendererJSON, - message?: any = '' -) { - try { - // We're assuming React.Element here and fallback to - // rendering ?ReactTestRendererJSON - // $FlowFixMe - const { toJSON } = render(instance); - if (message) { - console.log(`${message}\n\n`, format(toJSON())); - } else { - console.log(format(toJSON())); - } - } catch (e) { - // $FlowFixMe - debugDeep(instance); - } -} - -function debug( - instance: ReactTestInstance | React.Element, - message?: any -) { - return debugShallow(instance, message); -} - -debug.shallow = debugShallow; -debug.deep = debugDeepElementOrInstance; - -export default debug; diff --git a/src/flushMicroTasks.js b/src/flushMicroTasks.js new file mode 100644 index 000000000..c4bb67903 --- /dev/null +++ b/src/flushMicroTasks.js @@ -0,0 +1,15 @@ +// @flow + +import { printDeprecationWarning } from './helpers/errors'; + +/** + * Wait for microtasks queue to flush + */ +export default function flushMicrotasksQueue(): Promise { + printDeprecationWarning('flushMicrotasksQueue'); + return flushMicroTasks(); +} + +export function flushMicroTasks(): Promise { + return new Promise((resolve) => setImmediate(resolve)); +} diff --git a/src/flushMicrotasksQueue.js b/src/flushMicrotasksQueue.js deleted file mode 100644 index caab8614b..000000000 --- a/src/flushMicrotasksQueue.js +++ /dev/null @@ -1,7 +0,0 @@ -// @flow -/** - * Wait for microtasks queue to flush - */ -export default function flushMicrotasksQueue(): Promise { - return new Promise((resolve) => setImmediate(resolve)); -} diff --git a/src/helpers/a11yAPI.js b/src/helpers/a11yAPI.js index 40598b9b5..77f1b063e 100644 --- a/src/helpers/a11yAPI.js +++ b/src/helpers/a11yAPI.js @@ -1,6 +1,6 @@ // @flow import type { A11yRole, A11yStates, A11yState, A11yValue } from '../types.flow'; -import type { WaitForOptions } from './findByAPI'; +import type { WaitForOptions } from '../waitFor'; import makeQuery from './makeQuery'; type GetReturn = ReactTestInstance; diff --git a/src/helpers/errors.js b/src/helpers/errors.js index edf108cbc..ce089b873 100644 --- a/src/helpers/errors.js +++ b/src/helpers/errors.js @@ -24,22 +24,7 @@ export const createQueryByError = (error: Error, callsite: Function) => { throw new ErrorWithStack(error.message, callsite); }; -const warned = { - getByName: false, - getAllByName: false, - queryByName: false, - queryAllByName: false, - - getByProps: false, - getAllByProps: false, - queryByProps: false, - queryAllByProps: false, - - getByType: false, - getAllByType: false, - queryByType: false, - queryAllByType: false, -}; +const warned = {}; export function printDeprecationWarning(functionName: string) { if (warned[functionName]) { @@ -48,22 +33,17 @@ export function printDeprecationWarning(functionName: string) { console.warn(` Deprecation Warning: - ${functionName} is not recommended for use and will be deleted in react-native-testing-library 2.x. + Use of ${functionName} is not recommended and will be deleted in future versions of react-native-testing-library. `); warned[functionName] = true; } -export function printUnsafeWarning(functionName: string) { - if (warned[functionName]) { - return; - } - - console.warn(` - Deprecation Warning: - ${functionName} is not recommended for use and has been renamed to UNSAFE_${functionName}. - In react-native-testing-library 2.x only the UNSAFE_${functionName} name will work. - `); - - warned[functionName] = true; +export function throwRemovedFunctionError( + functionName: string, + docsRef: string +) { + throw new Error( + `${functionName} has been removed in version 2.0.\n\nPlease consult: https://callstack.github.io/react-native-testing-library/docs/${docsRef}` + ); } diff --git a/src/helpers/findByAPI.js b/src/helpers/findByAPI.js index 7b773979b..058f51fda 100644 --- a/src/helpers/findByAPI.js +++ b/src/helpers/findByAPI.js @@ -1,7 +1,8 @@ // @flow -import waitForElement from '../waitForElement'; +import waitFor from '../waitFor'; +import type { WaitForOptions } from '../waitFor'; import { - fixedGetByTestId, + getByTestId, getAllByTestId, getByText, getAllByText, @@ -11,27 +12,17 @@ import { getAllByDisplayValue, } from './getByAPI'; -export type WaitForOptions = { - timeout?: number, - interval?: number, -}; - const makeFindQuery = ( instance: ReactTestInstance, getQuery: (instance: ReactTestInstance) => (text: Text) => Result, text: Text, waitForOptions: WaitForOptions -): Promise => - waitForElement( - () => getQuery(instance)(text), - waitForOptions.timeout, - waitForOptions.interval - ); +): Promise => waitFor(() => getQuery(instance)(text), waitForOptions); export const findByTestId = (instance: ReactTestInstance) => ( testId: string, waitForOptions: WaitForOptions = {} -) => makeFindQuery(instance, fixedGetByTestId, testId, waitForOptions); +) => makeFindQuery(instance, getByTestId, testId, waitForOptions); export const findAllByTestId = (instance: ReactTestInstance) => ( testId: string, diff --git a/src/helpers/getByAPI.js b/src/helpers/getByAPI.js index 052d3d560..ea2342655 100644 --- a/src/helpers/getByAPI.js +++ b/src/helpers/getByAPI.js @@ -5,16 +5,11 @@ import { ErrorWithStack, createLibraryNotSupportedError, prepareErrorMessage, - printDeprecationWarning, - printUnsafeWarning, + throwRemovedFunctionError, } from './errors'; const filterNodeByType = (node, type) => node.type === type; -const filterNodeByName = (node, name) => - typeof node.type !== 'string' && - (node.type.displayName === name || node.type.name === name); - const getNodeByText = (node, text) => { try { // eslint-disable-next-line @@ -85,28 +80,6 @@ const getTextInputNodeByDisplayValue = (node, value) => { } }; -export const getByName = (instance: ReactTestInstance, warnFn?: Function) => - function getByNameFn(name: string | React.ComponentType) { - warnFn && warnFn('getByName'); - try { - return typeof name === 'string' - ? instance.find((node) => filterNodeByName(node, name)) - : instance.findByType(name); - } catch (error) { - throw new ErrorWithStack(prepareErrorMessage(error), getByNameFn); - } - }; - -export const getByType = (instance: ReactTestInstance, warnFn?: Function) => - function getByTypeFn(type: React.ComponentType) { - warnFn && warnFn('getByType'); - try { - return instance.findByType(type); - } catch (error) { - throw new ErrorWithStack(prepareErrorMessage(error), getByTypeFn); - } - }; - export const getByText = (instance: ReactTestInstance) => function getByTextFn(text: string | RegExp) { try { @@ -138,26 +111,7 @@ export const getByDisplayValue = (instance: ReactTestInstance) => } }; -export const getByProps = (instance: ReactTestInstance, warnFn?: Function) => - function getByPropsFn(props: { [propName: string]: any }) { - warnFn && warnFn('getByProps'); - try { - return instance.findByProps(props); - } catch (error) { - throw new ErrorWithStack(prepareErrorMessage(error), getByPropsFn); - } - }; - export const getByTestId = (instance: ReactTestInstance) => - function getByTestIdFn(testID: string) { - try { - return instance.findByProps({ testID }); - } catch (error) { - throw new ErrorWithStack(prepareErrorMessage(error), getByTestIdFn); - } - }; - -export const fixedGetByTestId = (instance: ReactTestInstance) => function getByTestIdFn(testID: string) { try { const results = getAllByTestId(instance)(testID); @@ -176,29 +130,6 @@ export const fixedGetByTestId = (instance: ReactTestInstance) => } }; -export const getAllByName = (instance: ReactTestInstance, warnFn?: Function) => - function getAllByNameFn(name: string | React.ComponentType) { - warnFn && warnFn('getAllByName'); - const results = - typeof name === 'string' - ? instance.findAll((node) => filterNodeByName(node, name)) - : instance.findAllByType(name); - if (results.length === 0) { - throw new ErrorWithStack('No instances found', getAllByNameFn); - } - return results; - }; - -export const getAllByType = (instance: ReactTestInstance, warnFn?: Function) => - function getAllByTypeFn(type: React.ComponentType) { - warnFn && warnFn('getAllByType'); - const results = instance.findAllByType(type); - if (results.length === 0) { - throw new ErrorWithStack('No instances found', getAllByTypeFn); - } - return results; - }; - export const getAllByText = (instance: ReactTestInstance) => function getAllByTextFn(text: string | RegExp) { const results = instance.findAll((node) => getNodeByText(node, text)); @@ -239,19 +170,6 @@ export const getAllByDisplayValue = (instance: ReactTestInstance) => return results; }; -export const getAllByProps = (instance: ReactTestInstance, warnFn?: Function) => - function getAllByPropsFn(props: { [propName: string]: any }) { - warnFn && warnFn('getAllByProps'); - const results = instance.findAllByProps(props); - if (results.length === 0) { - throw new ErrorWithStack( - `No instances found with props:\n${prettyFormat(props)}`, - getAllByPropsFn - ); - } - return results; - }; - export const getAllByTestId = (instance: ReactTestInstance) => function getAllByTestIdFn(testID: string): ReactTestInstance[] { const results = instance @@ -267,25 +185,75 @@ export const getAllByTestId = (instance: ReactTestInstance) => return results; }; +export const UNSAFE_getByType = (instance: ReactTestInstance) => + function getByTypeFn(type: React.ComponentType) { + try { + return instance.findByType(type); + } catch (error) { + throw new ErrorWithStack(prepareErrorMessage(error), getByTypeFn); + } + }; + +export const UNSAFE_getByProps = (instance: ReactTestInstance) => + function getByPropsFn(props: { [propName: string]: any }) { + try { + return instance.findByProps(props); + } catch (error) { + throw new ErrorWithStack(prepareErrorMessage(error), getByPropsFn); + } + }; + +export const UNSAFE_getAllByType = (instance: ReactTestInstance) => + function getAllByTypeFn(type: React.ComponentType) { + const results = instance.findAllByType(type); + if (results.length === 0) { + throw new ErrorWithStack('No instances found', getAllByTypeFn); + } + return results; + }; + +export const UNSAFE_getAllByProps = (instance: ReactTestInstance) => + function getAllByPropsFn(props: { [propName: string]: any }) { + const results = instance.findAllByProps(props); + if (results.length === 0) { + throw new ErrorWithStack( + `No instances found with props:\n${prettyFormat(props)}`, + getAllByPropsFn + ); + } + return results; + }; + export const getByAPI = (instance: ReactTestInstance) => ({ - getByTestId: getByTestId(instance), - getByName: getByName(instance, printDeprecationWarning), - getByType: getByType(instance, printUnsafeWarning), getByText: getByText(instance), getByPlaceholder: getByPlaceholder(instance), getByDisplayValue: getByDisplayValue(instance), - getByProps: getByProps(instance, printUnsafeWarning), - getAllByTestId: getAllByTestId(instance), - getAllByName: getAllByName(instance, printDeprecationWarning), - getAllByType: getAllByType(instance, printUnsafeWarning), + getByTestId: getByTestId(instance), getAllByText: getAllByText(instance), getAllByPlaceholder: getAllByPlaceholder(instance), getAllByDisplayValue: getAllByDisplayValue(instance), - getAllByProps: getAllByProps(instance, printUnsafeWarning), + getAllByTestId: getAllByTestId(instance), + + // Unsafe + UNSAFE_getByType: UNSAFE_getByType(instance), + UNSAFE_getAllByType: UNSAFE_getAllByType(instance), + UNSAFE_getByProps: UNSAFE_getByProps(instance), + UNSAFE_getAllByProps: UNSAFE_getAllByProps(instance), - // Unsafe aliases - UNSAFE_getByType: getByType(instance), - UNSAFE_getAllByType: getAllByType(instance), - UNSAFE_getByProps: getByProps(instance), - UNSAFE_getAllByProps: getAllByProps(instance), + // Removed + getByName: () => + throwRemovedFunctionError('getByName', 'migration-v2#removed-functions'), + getAllByName: () => + throwRemovedFunctionError('getAllByName', 'migration-v2#removed-functions'), + getByType: () => + throwRemovedFunctionError('getByType', 'migration-v2#removed-functions'), + getAllByType: () => + throwRemovedFunctionError('getAllByType', 'migration-v2#removed-functions'), + getByProps: () => + throwRemovedFunctionError('getByProps', 'migration-v2#removed-functions'), + getAllByProps: () => + throwRemovedFunctionError( + 'getAllByProps', + 'migration-v2#removed-functions' + ), }); diff --git a/src/helpers/makeQuery.js b/src/helpers/makeQuery.js index facda0fc3..04e41a18d 100644 --- a/src/helpers/makeQuery.js +++ b/src/helpers/makeQuery.js @@ -1,11 +1,11 @@ // @flow -import waitForElement from '../waitForElement'; +import waitFor from '../waitFor'; +import type { WaitForOptions } from '../waitFor'; import { ErrorWithStack, prepareErrorMessage, createQueryByError, } from './errors'; -import type { WaitForOptions } from './findByAPI'; function isNodeValid(node: ReactTestInstance) { return typeof node.type === 'string'; @@ -70,19 +70,11 @@ const makeQuery = ( }; const findBy = (matcher: M, waitForOptions?: WaitForOptions) => { - return waitForElement( - () => getBy(matcher), - waitForOptions?.timeout, - waitForOptions?.interval - ); + return waitFor(() => getBy(matcher), waitForOptions); }; const findAllBy = (matcher: M, waitForOptions?: WaitForOptions) => { - return waitForElement( - () => getAllBy(matcher), - waitForOptions?.timeout, - waitForOptions?.interval - ); + return waitFor(() => getAllBy(matcher), waitForOptions); }; return { diff --git a/src/helpers/queryByAPI.js b/src/helpers/queryByAPI.js index e2c06b0a0..5566e3e4d 100644 --- a/src/helpers/queryByAPI.js +++ b/src/helpers/queryByAPI.js @@ -2,45 +2,19 @@ import * as React from 'react'; import { getByTestId, - getByName, - getByType, getByText, getByPlaceholder, getByDisplayValue, - getByProps, getAllByTestId, - getAllByName, - getAllByType, getAllByText, getAllByPlaceholder, getAllByDisplayValue, - getAllByProps, + UNSAFE_getByType, + UNSAFE_getByProps, + UNSAFE_getAllByType, + UNSAFE_getAllByProps, } from './getByAPI'; -import { - createQueryByError, - printDeprecationWarning, - printUnsafeWarning, -} from './errors'; - -export const queryByName = (instance: ReactTestInstance, warnFn?: Function) => - function queryByNameFn(name: string | React.ComponentType) { - warnFn && warnFn('queryByName'); - try { - return getByName(instance)(name); - } catch (error) { - return createQueryByError(error, queryByNameFn); - } - }; - -export const queryByType = (instance: ReactTestInstance, warnFn?: Function) => - function queryByTypeFn(type: React.ComponentType) { - warnFn && warnFn('queryByType'); - try { - return getByType(instance)(type); - } catch (error) { - return createQueryByError(error, queryByTypeFn); - } - }; +import { createQueryByError, throwRemovedFunctionError } from './errors'; export const queryByText = (instance: ReactTestInstance) => function queryByTextFn(text: string | RegExp) { @@ -69,16 +43,6 @@ export const queryByDisplayValue = (instance: ReactTestInstance) => } }; -export const queryByProps = (instance: ReactTestInstance, warnFn?: Function) => - function queryByPropsFn(props: { [propName: string]: any }) { - warnFn && warnFn('queryByProps'); - try { - return getByProps(instance)(props); - } catch (error) { - return createQueryByError(error, queryByPropsFn); - } - }; - export const queryByTestId = (instance: ReactTestInstance) => function queryByTestIdFn(testID: string) { try { @@ -88,30 +52,6 @@ export const queryByTestId = (instance: ReactTestInstance) => } }; -export const queryAllByName = ( - instance: ReactTestInstance, - warnFn?: Function -) => (name: string | React.ComponentType) => { - warnFn && warnFn('queryAllByName'); - try { - return getAllByName(instance)(name); - } catch (error) { - return []; - } -}; - -export const queryAllByType = ( - instance: ReactTestInstance, - warnFn?: Function -) => (type: React.ComponentType) => { - warnFn && warnFn('queryAllByType'); - try { - return getAllByType(instance)(type); - } catch (error) { - return []; - } -}; - export const queryAllByText = (instance: ReactTestInstance) => ( text: string | RegExp ) => { @@ -142,23 +82,49 @@ export const queryAllByDisplayValue = (instance: ReactTestInstance) => ( } }; -export const queryAllByProps = ( - instance: ReactTestInstance, - warnFn?: Function -) => (props: { [propName: string]: any }) => { - warnFn && warnFn('queryAllByProps'); +export const queryAllByTestId = (instance: ReactTestInstance) => ( + testID: string +) => { try { - return getAllByProps(instance)(props); + return getAllByTestId(instance)(testID); } catch (error) { return []; } }; -export const queryAllByTestId = (instance: ReactTestInstance) => ( - testID: string +export const UNSAFE_queryByType = (instance: ReactTestInstance) => + function queryByTypeFn(type: React.ComponentType) { + try { + return UNSAFE_getByType(instance)(type); + } catch (error) { + return createQueryByError(error, queryByTypeFn); + } + }; + +export const UNSAFE_queryByProps = (instance: ReactTestInstance) => + function queryByPropsFn(props: { [propName: string]: any }) { + try { + return UNSAFE_getByProps(instance)(props); + } catch (error) { + return createQueryByError(error, queryByPropsFn); + } + }; + +export const UNSAFE_queryAllByType = (instance: ReactTestInstance) => ( + type: React.ComponentType ) => { try { - return getAllByTestId(instance)(testID); + return UNSAFE_getAllByType(instance)(type); + } catch (error) { + return []; + } +}; + +export const UNSAFE_queryAllByProps = (instance: ReactTestInstance) => (props: { + [propName: string]: any, +}) => { + try { + return UNSAFE_getAllByProps(instance)(props); } catch (error) { return []; } @@ -166,23 +132,40 @@ export const queryAllByTestId = (instance: ReactTestInstance) => ( export const queryByAPI = (instance: ReactTestInstance) => ({ queryByTestId: queryByTestId(instance), - queryByName: queryByName(instance, printDeprecationWarning), - queryByType: queryByType(instance, printUnsafeWarning), queryByText: queryByText(instance), queryByPlaceholder: queryByPlaceholder(instance), queryByDisplayValue: queryByDisplayValue(instance), - queryByProps: queryByProps(instance, printUnsafeWarning), queryAllByTestId: queryAllByTestId(instance), - queryAllByName: queryAllByName(instance, printDeprecationWarning), - queryAllByType: queryAllByType(instance, printUnsafeWarning), queryAllByText: queryAllByText(instance), queryAllByPlaceholder: queryAllByPlaceholder(instance), queryAllByDisplayValue: queryAllByDisplayValue(instance), - queryAllByProps: queryAllByProps(instance, printUnsafeWarning), - // Unsafe aliases - UNSAFE_queryByType: queryByType(instance), - UNSAFE_queryAllByType: queryAllByType(instance), - UNSAFE_queryByProps: queryByProps(instance), - UNSAFE_queryAllByProps: queryAllByProps(instance), + // Unsafe + UNSAFE_queryByType: UNSAFE_queryByType(instance), + UNSAFE_queryAllByType: UNSAFE_queryAllByType(instance), + UNSAFE_queryByProps: UNSAFE_queryByProps(instance), + UNSAFE_queryAllByProps: UNSAFE_queryAllByProps(instance), + + // Removed + queryByName: () => + throwRemovedFunctionError('queryByName', 'migration-v2#removed-functions'), + queryAllByName: () => + throwRemovedFunctionError( + 'queryAllByName', + 'migration-v2#removed-functions' + ), + queryByType: () => + throwRemovedFunctionError('queryByType', 'migration-v2#removed-functions'), + queryAllByType: () => + throwRemovedFunctionError( + 'queryAllByType', + 'migration-v2#removed-functions' + ), + queryByProps: () => + throwRemovedFunctionError('queryByProps', 'migration-v2#removed-functions'), + queryAllByProps: () => + throwRemovedFunctionError( + 'queryAllByProps', + 'migration-v2#removed-functions' + ), }); diff --git a/src/index.js b/src/index.js index 2e7ac9f20..d4cb964e8 100644 --- a/src/index.js +++ b/src/index.js @@ -1,20 +1,18 @@ // @flow -import act from './act'; -import cleanup from './cleanup'; -import debug from './debug'; -import fireEvent from './fireEvent'; -import flushMicrotasksQueue from './flushMicrotasksQueue'; -import render from './render'; -import shallow from './shallow'; -import waitForElement from './waitForElement'; -import within from './within'; +import { cleanup } from './pure'; +import { flushMicroTasks } from './flushMicroTasks'; -export { act }; -export { cleanup }; -export { debug }; -export { fireEvent }; -export { flushMicrotasksQueue }; -export { render }; -export { shallow }; -export { waitForElement }; -export { within }; +// If we're running in a test runner that supports afterEach +// then we'll automatically run cleanup afterEach test +// this ensures that tests run in isolation from each other +// if you don't like this then either import the `pure` module +// or set the RNTL_SKIP_AUTO_CLEANUP env variable to 'true'. +if (typeof afterEach === 'function' && !process.env.RNTL_SKIP_AUTO_CLEANUP) { + // eslint-disable-next-line no-undef + afterEach(async () => { + await flushMicroTasks(); + cleanup(); + }); +} + +export * from './pure'; diff --git a/src/pure.js b/src/pure.js new file mode 100644 index 000000000..7765847a6 --- /dev/null +++ b/src/pure.js @@ -0,0 +1,18 @@ +// @flow +import act from './act'; +import cleanup from './cleanup'; +import fireEvent from './fireEvent'; +import flushMicrotasksQueue from './flushMicroTasks'; +import render from './render'; +import shallow from './shallow'; +import waitFor, { waitForElement } from './waitFor'; +import within from './within'; + +export { act }; +export { cleanup }; +export { fireEvent }; +export { flushMicrotasksQueue }; +export { render }; +export { shallow }; +export { waitFor, waitForElement }; +export { within }; diff --git a/src/shallow.js b/src/shallow.js index 576ac913a..828f4dd61 100644 --- a/src/shallow.js +++ b/src/shallow.js @@ -1,7 +1,7 @@ // @flow import * as React from 'react'; import ShallowRenderer from 'react-test-renderer/shallow'; // eslint-disable-line import/no-extraneous-dependencies -import { printDeprecationWarning } from './helpers/errors'; +import { throwRemovedFunctionError } from './helpers/errors'; /** * Renders test component shallowly using react-test-renderer/shallow @@ -18,10 +18,9 @@ export function shallowInternal( }; } -export default function shallow( - instance: ReactTestInstance | React.Element -) { - printDeprecationWarning('shallow'); - - return shallowInternal(instance); +export default function shallow(_: ReactTestInstance | React.Element) { + throwRemovedFunctionError( + 'shallow', + 'migration-v2#removed-global-shallow-function' + ); } diff --git a/src/waitFor.js b/src/waitFor.js new file mode 100644 index 000000000..1820dbe88 --- /dev/null +++ b/src/waitFor.js @@ -0,0 +1,80 @@ +// @flow + +import * as React from 'react'; +import act from './act'; +import { throwRemovedFunctionError } from './helpers/errors'; + +const DEFAULT_TIMEOUT = 4500; +const DEFAULT_INTERVAL = 50; + +function checkReactVersionAtLeast(major: number, minor: number): boolean { + if (React.version === undefined) return false; + const [actualMajor, actualMinor] = React.version.split('.').map(Number); + + return actualMajor > major || (actualMajor === major && actualMinor >= minor); +} + +export type WaitForOptions = { + timeout?: number, + interval?: number, +}; + +function waitForInternal( + expectation: () => T, + options?: WaitForOptions +): Promise { + const timeout = options?.timeout ?? DEFAULT_TIMEOUT; + const interval = options?.interval ?? DEFAULT_INTERVAL; + const startTime = Date.now(); + + return new Promise((resolve, reject) => { + const rejectOrRerun = (error) => { + if (Date.now() - startTime >= timeout) { + reject(error); + return; + } + setTimeout(runExpectation, interval); + }; + function runExpectation() { + try { + const result = expectation(); + resolve(result); + } catch (error) { + rejectOrRerun(error); + } + } + setTimeout(runExpectation, 0); + }); +} + +export default async function waitFor( + expectation: () => T, + options?: WaitForOptions +): Promise { + if (!checkReactVersionAtLeast(16, 9)) { + return waitForInternal(expectation, options); + } + + let result: T; + + //$FlowFixMe: `act` has incorrect flow typing + await act(async () => { + result = await waitForInternal(expectation, options); + }); + + //$FlowFixMe: either we have result or `waitFor` threw error + return result; +} + +export function waitForElement( + expectation: () => T, + _timeout: number = 4500, + _interval: number = 50 +): Promise { + throwRemovedFunctionError( + 'waitForElement', + 'migration-v2#waitfor-api-changes' + ); + + return Promise.reject(); +} diff --git a/src/waitForElement.js b/src/waitForElement.js deleted file mode 100644 index 5072a99b9..000000000 --- a/src/waitForElement.js +++ /dev/null @@ -1,26 +0,0 @@ -// @flow -export default function waitForElement( - expectation: () => T, - timeout: number = 4500, - interval: number = 50 -): Promise { - const startTime = Date.now(); - return new Promise((resolve, reject) => { - const rejectOrRerun = (error) => { - if (Date.now() - startTime >= timeout) { - reject(error); - return; - } - setTimeout(runExpectation, interval); - }; - function runExpectation() { - try { - const result = expectation(); - resolve(result); - } catch (error) { - rejectOrRerun(error); - } - } - setTimeout(runExpectation, 0); - }); -} diff --git a/typings/__tests__/index.test.tsx b/typings/__tests__/index.test.tsx index 3caf5f299..f6f7cb31b 100644 --- a/typings/__tests__/index.test.tsx +++ b/typings/__tests__/index.test.tsx @@ -4,10 +4,8 @@ import { ReactTestInstance } from 'react-test-renderer'; import { render, fireEvent, - shallow, flushMicrotasksQueue, - debug, - waitForElement, + waitFor, act, within, } from '../..'; @@ -16,9 +14,9 @@ interface HasRequiredProp { requiredProp: string; } -const View = props => props.children; -const Text = props => props.children; -const TextInput = props => props.children; +const View = (props) => props.children; +const Text = (props) => props.children; +const TextInput = (props) => props.children; const ElementWithRequiredProps = (props: HasRequiredProp) => ( {props.requiredProp} ); @@ -32,96 +30,89 @@ const TestComponent = () => ( const tree = render(); -// getByAPI tests -const getByNameString: ReactTestInstance = tree.getByName('View'); -const getByNameContructor: ReactTestInstance = tree.getByName(View); -const getByType: ReactTestInstance = tree.getByType(View); -const getByTypeWithRequiredProps: ReactTestInstance = tree.getByType( - ElementWithRequiredProps -); -const getByTextString: ReactTestInstance = tree.getByText(''); -const getByTextRegExp: ReactTestInstance = tree.getByText(/View/g); -const getByPlaceholderString: ReactTestInstance = tree.getByPlaceholder( - 'my placeholder' -); -const getByPlaceholderRegExp: ReactTestInstance = tree.getByPlaceholder( - /placeholder/g -); -const getByDisplayValueString: ReactTestInstance = tree.getByDisplayValue( - 'my value' -); -const getByDisplayValueRegExp: ReactTestInstance = tree.getByDisplayValue( - /value/g -); -const getByProps: ReactTestInstance = tree.getByProps({ value: 2 }); -const getByTestId: ReactTestInstance = tree.getByTestId('test-id'); -const getAllByTestId: ReactTestInstance[] = tree.getAllByTestId('test-id'); -const getAllByNameString: Array = tree.getAllByName('View'); -const getAllByNameConstructor: Array = tree.getAllByName( - View -); -const getAllByType: Array = tree.getAllByType(View); -const getAllByTypeWithRequiredProps: Array< - ReactTestInstance -> = tree.getAllByType(ElementWithRequiredProps); -const getAllByTextString: Array = tree.getAllByText( - '' -); -const getAllByTextRegExp: Array = tree.getAllByText(/Text/g); -const getAllByProps: Array = tree.getAllByProps({ - value: 2, -}); +// getBy API +const getBy: ReactTestInstance[] = [ + tree.getByText(''), + tree.getByText(/View/g), + tree.getByPlaceholder('my placeholder'), + tree.getByPlaceholder(/placeholder/g), + tree.getByDisplayValue('my value'), + tree.getByDisplayValue(/value/g), + tree.getByTestId('test-id'), + tree.getByA11yLabel('label'), + tree.getByA11yHint('label'), + tree.getByA11yRole('button'), + tree.getByA11yStates('selected'), + tree.getByA11yStates(['selected']), + tree.getByA11yState({ busy: true }), + tree.getByA11yValue({ min: 10 }), + tree.UNSAFE_getByType(View), + tree.UNSAFE_getByType(ElementWithRequiredProps), + tree.UNSAFE_getByProps({ value: 2 }), +]; -// queuryByAPI tests -const queryByNameString: ReactTestInstance | null = tree.queryByName('View'); -const queryByNameConstructor: ReactTestInstance | null = tree.queryByName(View); -const queryByType: ReactTestInstance | null = tree.queryByType(View); -const queryByTypeWithRequiredProps: ReactTestInstance | null = tree.queryByType( - ElementWithRequiredProps -); -const queryByTextString: ReactTestInstance | null = tree.queryByText('View'); -const queryByTextRegExp: ReactTestInstance | null = tree.queryByText(/View/g); -const queryByPlaceholderString: ReactTestInstance | null = tree.queryByPlaceholder( - 'my placeholder' -); -const queryByPlaceholderRegExp: ReactTestInstance | null = tree.queryByPlaceholder( - /placeholder/g -); -const queryByDisplayValueString: ReactTestInstance | null = tree.queryByDisplayValue( - 'my value' -); -const queryByDisplayValueRegExp: ReactTestInstance | null = tree.queryByDisplayValue( - /value/g -); -const queryByProps: ReactTestInstance | null = tree.queryByProps({ value: 2 }); -const queryByTestId: ReactTestInstance | null = tree.queryByTestId('test-id'); -const queryAllByTestId: ReactTestInstance[] | null = tree.queryAllByTestId( - 'test-id' -); -const queryAllByNameString: Array = tree.queryAllByName( - 'View' -); -const queryAllByNameConstructor: Array = tree.queryAllByName( - View -); -const queryAllByType: Array = tree.queryAllByType(View); -const queryAllByTypeWithRequiredProps: Array< - ReactTestInstance -> = tree.queryAllByType(ElementWithRequiredProps); -const queryAllByTextString: Array = tree.queryAllByText( - 'View' -); -const queryAllByTextRegExp: Array = tree.queryAllByText( - /View/g -); -const queryAllByDisplayValueString: Array< - ReactTestInstance -> = tree.queryAllByDisplayValue('View'); -const queryAllByDisplayValueRegExp: Array< - ReactTestInstance -> = tree.queryAllByDisplayValue(/View/g); +const getAllBy: ReactTestInstance[][] = [ + tree.getAllByText(''), + tree.getAllByText(/Text/g), + tree.getAllByPlaceholder('my placeholder'), + tree.getAllByPlaceholder(/placeholder/g), + tree.getAllByDisplayValue('my value'), + tree.getAllByDisplayValue(/value/g), + tree.getAllByTestId('test-id'), + tree.getAllByA11yLabel('label'), + tree.getAllByA11yHint('label'), + tree.getAllByA11yRole('button'), + tree.getAllByA11yStates('selected'), + tree.getAllByA11yStates(['selected']), + tree.getAllByA11yState({ busy: true }), + tree.getAllByA11yValue({ min: 10 }), + tree.UNSAFE_getAllByType(View), + tree.UNSAFE_getAllByType(ElementWithRequiredProps), + tree.UNSAFE_getAllByProps({ value: 2 }), +]; + +// queryBy API +const queryBy: Array = [ + tree.queryByText('View'), + tree.queryByText(/View/g), + tree.queryByPlaceholder('my placeholder'), + tree.queryByPlaceholder(/placeholder/g), + tree.queryByDisplayValue('my value'), + tree.queryByDisplayValue(/value/g), + tree.queryByTestId('test-id'), + tree.queryByA11yHint('label'), + tree.queryByA11yLabel('label'), + tree.queryByA11yRole('button'), + tree.queryByA11yStates('selected'), + tree.queryByA11yStates(['selected']), + tree.queryByA11yState({ busy: true }), + tree.queryByA11yValue({ min: 10 }), + tree.UNSAFE_queryByType(View), + tree.UNSAFE_queryByType(ElementWithRequiredProps), + tree.UNSAFE_queryByProps({ value: 2 }), +]; + +const queryAllBy: ReactTestInstance[][] = [ + tree.queryAllByText('View'), + tree.queryAllByText(/View/g), + tree.queryAllByPlaceholder('my placeholder'), + tree.queryAllByPlaceholder(/placeholder/g), + tree.queryAllByDisplayValue('my value'), + tree.queryAllByDisplayValue(/value/g), + tree.queryAllByTestId('test-id'), + tree.queryAllByA11yLabel('label'), + tree.queryAllByA11yHint('label'), + tree.queryAllByA11yRole('button'), + tree.queryAllByA11yStates('selected'), + tree.queryAllByA11yStates(['selected']), + tree.queryAllByA11yState({ busy: true }), + tree.queryAllByA11yValue({ min: 10 }), + tree.UNSAFE_queryAllByType(View), + tree.UNSAFE_queryAllByType(ElementWithRequiredProps), + tree.UNSAFE_queryAllByProps({ value: 2 }), +]; -// findBy API tests +// findBy API const findBy: Promise[] = [ tree.findByText('View'), tree.findByText('View', { timeout: 10, interval: 10 }), @@ -164,6 +155,8 @@ const findAllBy: Promise[] = [ tree.findAllByDisplayValue(/View/g, { timeout: 10, interval: 10 }), tree.findAllByTestId('test-id'), tree.findAllByTestId('test-id', { timeout: 10, interval: 10 }), + tree.findAllByA11yLabel('label'), + tree.findAllByA11yLabel('label', { timeout: 10, interval: 10 }), tree.findAllByA11yHint('label'), tree.findAllByA11yHint('label', { timeout: 10, interval: 10 }), tree.findAllByA11yState({ busy: true }), @@ -172,103 +165,50 @@ const findAllBy: Promise[] = [ tree.findAllByA11yValue({ min: 10 }, { timeout: 10, interval: 10 }), ]; -// Accessibility queries -const getByA11yLabel: ReactTestInstance = tree.getByA11yLabel('label'); -const getAllByA11yLabel: Array = tree.getAllByA11yLabel( - 'label' -); -const queryByA11yLabel: ReactTestInstance = tree.queryByA11yLabel('label'); -const queryAllByA11yLabel: Array = tree.queryAllByA11yLabel( - 'label' -); - -const getByA11yHint: ReactTestInstance = tree.getByA11yHint('label'); -const getAllByA11yHint: Array = tree.getAllByA11yHint( - 'label' -); -const queryByA11yHint: ReactTestInstance = tree.queryByA11yHint('label'); -const queryAllByA11yHint: Array = tree.queryAllByA11yHint( - 'label' -); - -const getByA11yRole: ReactTestInstance = tree.getByA11yRole('button'); -const getAllByA11yRole: Array = tree.getAllByA11yRole( - 'button' -); -const queryByA11yRole: ReactTestInstance = tree.queryByA11yRole('button'); -const queryAllByA11yRole: Array = tree.queryAllByA11yRole( - 'button' -); - -const getByA11yStates: ReactTestInstance = tree.getByA11yStates('selected'); -const getByA11yStatesArray: ReactTestInstance = tree.getByA11yStates(['selected']); -const getAllByA11yStates: Array = tree.getAllByA11yStates( - 'selected' -); -const getAllByA11yStatesArray: Array< - ReactTestInstance -> = tree.getAllByA11yStates(['selected']); -const queryByA11yStates: ReactTestInstance = tree.queryByA11yStates('selected'); -const queryByA11yStatesArray: ReactTestInstance = tree.queryByA11yStates([ - 'selected', -]); -const queryAllByA11yStates: Array< - ReactTestInstance -> = tree.queryAllByA11yStates('selected'); -const queryAllByA11yStatesArray: Array< - ReactTestInstance -> = tree.queryAllByA11yStates(['selected']); - -const getByA11yState: ReactTestInstance = tree.getByA11yState({ busy: true }); -const getAllByA11yState: Array = tree.getAllByA11yState({ busy: true }); -const queryByA11yState: ReactTestInstance = tree.queryByA11yState({ busy: true }); -const queryAllByA11yState: Array = tree.queryAllByA11yState({ busy: true }); - -const getByA11yValue: ReactTestInstance = tree.getByA11yValue({ min: 10 }); -const getAllByA11yValue: Array = tree.getAllByA11yValue({ min: 10 }); -const queryByA11yValue: ReactTestInstance = tree.queryByA11yValue({ min: 10 }); -const queryAllByA11yValue: Array = tree.queryAllByA11yValue({ min: 10 }); - +// debug API const debugFn = tree.debug(); const debugFnWithMessage = tree.debug('my message'); +// update API tree.update(); tree.rerender(); tree.unmount(); -// fireEvent API tests -fireEvent(getByNameString, 'press'); -fireEvent(getByNameString, 'press', 'data'); -fireEvent(getByNameString, 'press', 'param1', 'param2'); -fireEvent.press(getByNameString); -fireEvent.changeText(getByNameString, 'string'); -fireEvent.scroll(getByNameString, 'eventData'); +// fireEvent API +const element: ReactTestInstance = tree.getByText('text'); +fireEvent(element, 'press'); +fireEvent(element, 'press', 'data'); +fireEvent(element, 'press', 'param1', 'param2'); +fireEvent.press(element); +fireEvent.changeText(element, 'string'); +fireEvent.scroll(element, 'eventData'); -// shallow API -const shallowTree: { output: React.ReactElement } = shallow( - -); - -const waitForFlush: Promise = flushMicrotasksQueue(); +// waitFor API +const waitGetBy: Promise[] = [ + waitFor(() => tree.getByA11yLabel('label')), + waitFor(() => tree.getByA11yLabel('label'), { + timeout: 10, + }), + waitFor(() => tree.getByA11yLabel('label'), { + timeout: 100, + interval: 10, + }), +]; -// debug API -debug(); -debug(, 'message'); -debug(getByNameString); -debug(getByNameString, 'message'); -debug.shallow(); -debug.shallow(, 'message'); -debug.deep(); -debug.deep(, 'message'); -debug.deep(tree.toJSON()); +const waitGetAllBy: Promise[] = [ + waitFor(() => tree.getAllByA11yLabel('label')), + waitFor(() => tree.getAllByA11yLabel('label'), { + timeout: 10, + }), + waitFor(() => tree.getAllByA11yLabel('label'), { + timeout: 100, + interval: 10, + }), +]; -const waitBy: Promise = waitForElement( - () => tree.getByName('View') -); -const waitByAll: Promise> = waitForElement< - Array ->(() => tree.getAllByName('View'), 1000, 50); +const waitForFlush: Promise = flushMicrotasksQueue(); +// act API act(() => { render(); }); diff --git a/typings/index.d.ts b/typings/index.d.ts index 0a5bb8d2f..b998fb93a 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1,5 +1,9 @@ import * as React from 'react'; -import { AccessibilityState, AccessibilityStates, AccessibilityRole } from 'react-native'; +import { + AccessibilityState, + AccessibilityStates, + AccessibilityRole, +} from 'react-native'; import { ReactTestInstance, ReactTestRendererJSON } from 'react-test-renderer'; type GetReturn = ReactTestInstance; @@ -10,48 +14,62 @@ type FindReturn = Promise; type FindAllReturn = Promise; interface GetByAPI { - getByName: (name: React.ReactType | string) => ReactTestInstance; - getByType:

(type: React.ComponentType

) => ReactTestInstance; getByText: (text: string | RegExp) => ReactTestInstance; getByPlaceholder: (placeholder: string | RegExp) => ReactTestInstance; getByDisplayValue: (value: string | RegExp) => ReactTestInstance; - getByProps: (props: Record) => ReactTestInstance; getByTestId: (testID: string) => ReactTestInstance; getAllByTestId: (testID: string) => Array; - getAllByName: (name: React.ReactType | string) => Array; - getAllByType:

(type: React.ComponentType

) => Array; getAllByText: (text: string | RegExp) => Array; getAllByPlaceholder: ( placeholder: string | RegExp ) => Array; getAllByDisplayValue: (value: string | RegExp) => Array; - getAllByProps: (props: Record) => Array; - // Unsafe aliases - UNSAFE_getByType:

(type: React.ComponentType

) => ReactTestInstance, - UNSAFE_getAllByType:

(type: React.ComponentType

) => Array, - UNSAFE_getByProps: (props: Record) => ReactTestInstance, - UNSAFE_getAllByProps: (props: Record) => Array, + UNSAFE_getByType:

(type: React.ComponentType

) => ReactTestInstance; + UNSAFE_getAllByType:

( + type: React.ComponentType

+ ) => Array; + UNSAFE_getByProps: (props: Record) => ReactTestInstance; + UNSAFE_getAllByProps: ( + props: Record + ) => Array; + + // Removed + /** + * @deprecated This function has been removed. Please use other queries. + */ + getByName: (name: React.ReactType | string) => ReactTestInstance; + /** + * @deprecated This function has been renamed to `UNSAFE_getByType`. + */ + getByType:

(type: React.ComponentType

) => ReactTestInstance; + /** + * @deprecated This function has been renamed to `UNSAFE_getByProps`. + */ + getByProps: (props: Record) => ReactTestInstance; + /** + * @deprecated This function has been removed. Please use other queries. + */ + getAllByName: (name: React.ReactType | string) => Array; + /** + * @deprecated This function has been renamed to `UNSAFE_getAllByType`. + */ + getAllByType:

(type: React.ComponentType

) => Array; + /** + * @deprecated This function has been renamed to `UNSAFE_getAllByProps`. + */ + getAllByProps: (props: Record) => Array; } interface QueryByAPI { - queryByName: (name: React.ReactType | string) => ReactTestInstance | null; - queryByType:

(type: React.ComponentType

) => ReactTestInstance | null; queryByText: (name: string | RegExp) => ReactTestInstance | null; queryByPlaceholder: ( placeholder: string | RegExp ) => ReactTestInstance | null; queryByDisplayValue: (value: string | RegExp) => ReactTestInstance | null; - queryByProps: (props: Record) => ReactTestInstance | null; queryByTestId: (testID: string) => ReactTestInstance | null; queryAllByTestId: (testID: string) => Array | null; - queryAllByName: ( - name: React.ReactType | string - ) => Array | []; - queryAllByType:

( - type: React.ComponentType

- ) => Array | []; queryAllByText: (text: string | RegExp) => Array | []; queryAllByPlaceholder: ( placeholder: string | RegExp @@ -59,20 +77,50 @@ interface QueryByAPI { queryAllByDisplayValue: ( value: string | RegExp ) => Array | []; - queryAllByProps: ( - props: Record - ) => Array | []; // Unsafe aliases - UNSAFE_queryByType:

(type: React.ComponentType

) => ReactTestInstance | null, - UNSAFE_queryAllByType:

(type: React.ComponentType

) => Array | [], - UNSAFE_queryByProps: (props: Record) => ReactTestInstance | null, - UNSAFE_queryAllByProps: (props: Record) => Array | [], -} + UNSAFE_queryByType:

( + type: React.ComponentType

+ ) => ReactTestInstance | null; + UNSAFE_queryAllByType:

( + type: React.ComponentType

+ ) => Array | []; + UNSAFE_queryByProps: (props: Record) => ReactTestInstance | null; + UNSAFE_queryAllByProps: ( + props: Record + ) => Array | []; -export interface WaitForOptions { - timeout: number; - interval: number; + // Removed + /** + * @deprecated This function has been removed. Please use other queries. + */ + queryByName: (name: React.ReactType | string) => ReactTestInstance | null; + /** + * @deprecated This function has been renamed to `UNSAFE_queryByType`. + */ + queryByType:

(type: React.ComponentType

) => ReactTestInstance | null; + /** + * @deprecated This function has been renamed to `UNSAFE_queryByProps`. + */ + queryByProps: (props: Record) => ReactTestInstance | null; + /** + * @deprecated This function has been removed. Please use other queries. + */ + queryAllByName: ( + name: React.ReactType | string + ) => Array | []; + /** + * @deprecated This function has been renamed to `UNSAFE_queryAllByType`. + */ + queryAllByType:

( + type: React.ComponentType

+ ) => Array | []; + /** + * @deprecated This function has been renamed to `UNSAFE_queryAllByProps`. + */ + queryAllByProps: ( + props: Record + ) => Array | []; } interface FindByAPI { @@ -109,18 +157,18 @@ interface FindByAPI { // Not yet available in DefinitelyTyped export type A11yValue = { - min?: number, - max?: number, - now?: number, - text?: string, + min?: number; + max?: number; + now?: number; + text?: string; }; type A11yAPI = { // Label - getByA11yLabel: (matcher: string | RegExp) => GetReturn, - getAllByA11yLabel: (matcher: string | RegExp) => GetAllReturn, - queryByA11yLabel: (matcher: string | RegExp) => QueryReturn, - queryAllByA11yLabel: (matcher: string | RegExp) => QueryAllReturn, + getByA11yLabel: (matcher: string | RegExp) => GetReturn; + getAllByA11yLabel: (matcher: string | RegExp) => GetAllReturn; + queryByA11yLabel: (matcher: string | RegExp) => QueryReturn; + queryAllByA11yLabel: (matcher: string | RegExp) => QueryAllReturn; findByA11yLabel: ( matcher: string | RegExp, waitForOptions?: WaitForOptions @@ -131,10 +179,10 @@ type A11yAPI = { ) => FindAllReturn; // Hint - getByA11yHint: (matcher: string | RegExp) => GetReturn, - getAllByA11yHint: (matcher: string | RegExp) => GetAllReturn, - queryByA11yHint: (matcher: string | RegExp) => QueryReturn, - queryAllByA11yHint: (matcher: string | RegExp) => QueryAllReturn, + getByA11yHint: (matcher: string | RegExp) => GetReturn; + getAllByA11yHint: (matcher: string | RegExp) => GetAllReturn; + queryByA11yHint: (matcher: string | RegExp) => QueryReturn; + queryAllByA11yHint: (matcher: string | RegExp) => QueryAllReturn; findByA11yHint: ( matcher: string | RegExp, waitForOptions?: WaitForOptions @@ -145,10 +193,10 @@ type A11yAPI = { ) => FindAllReturn; // Role - getByA11yRole: (matcher: AccessibilityRole | RegExp) => GetReturn, - getAllByA11yRole: (matcher: AccessibilityRole | RegExp) => GetAllReturn, - queryByA11yRole: (matcher: AccessibilityRole | RegExp) => QueryReturn, - queryAllByA11yRole: (matcher: AccessibilityRole | RegExp) => QueryAllReturn, + getByA11yRole: (matcher: AccessibilityRole | RegExp) => GetReturn; + getAllByA11yRole: (matcher: AccessibilityRole | RegExp) => GetAllReturn; + queryByA11yRole: (matcher: AccessibilityRole | RegExp) => QueryReturn; + queryAllByA11yRole: (matcher: AccessibilityRole | RegExp) => QueryAllReturn; findByA11yRole: ( matcher: AccessibilityRole | RegExp, waitForOptions?: WaitForOptions @@ -159,16 +207,24 @@ type A11yAPI = { ) => FindAllReturn; // States - getByA11yStates: (matcher: AccessibilityStates | Array) => GetReturn, - getAllByA11yStates: (matcher: AccessibilityStates | Array) => GetAllReturn, - queryByA11yStates: (matcher: AccessibilityStates | Array) => QueryReturn, - queryAllByA11yStates: (matcher: AccessibilityStates | Array) => QueryAllReturn, + getByA11yStates: ( + matcher: AccessibilityStates | Array + ) => GetReturn; + getAllByA11yStates: ( + matcher: AccessibilityStates | Array + ) => GetAllReturn; + queryByA11yStates: ( + matcher: AccessibilityStates | Array + ) => QueryReturn; + queryAllByA11yStates: ( + matcher: AccessibilityStates | Array + ) => QueryAllReturn; // State - getByA11yState: (matcher: AccessibilityState) => GetReturn, - getAllByA11yState: (matcher: AccessibilityState) => GetAllReturn, - queryByA11yState: (matcher: AccessibilityState) => QueryReturn, - queryAllByA11yState: (matcher: AccessibilityState) => QueryAllReturn, + getByA11yState: (matcher: AccessibilityState) => GetReturn; + getAllByA11yState: (matcher: AccessibilityState) => GetAllReturn; + queryByA11yState: (matcher: AccessibilityState) => QueryReturn; + queryAllByA11yState: (matcher: AccessibilityState) => QueryAllReturn; findByA11yState: ( matcher: AccessibilityState, waitForOptions?: WaitForOptions @@ -179,10 +235,10 @@ type A11yAPI = { ) => FindAllReturn; // Value - getByA11yValue: (matcher: A11yValue) => GetReturn, - getAllByA11yValue: (matcher: A11yValue) => GetAllReturn, - queryByA11yValue: (matcher: A11yValue) => QueryReturn, - queryAllByA11yValue: (matcher: A11yValue) => QueryAllReturn, + getByA11yValue: (matcher: A11yValue) => GetReturn; + getAllByA11yValue: (matcher: A11yValue) => GetAllReturn; + queryByA11yValue: (matcher: A11yValue) => QueryReturn; + queryAllByA11yValue: (matcher: A11yValue) => QueryAllReturn; findByA11yValue: ( matcher: A11yValue, waitForOptions?: WaitForOptions @@ -224,36 +280,40 @@ export type FireEventAPI = FireEventFunction & { scroll: (element: ReactTestInstance, ...data: Array) => any; }; -export type WaitForElementFunction = ( +type WaitForOptions = { + timeout?: number; + interval?: number; +}; + +export type WaitForFunction = ( expectation: () => T, - timeout?: number, - interval?: number + options?: WaitForOptions ) => Promise; -export type DebugFunction = ( - instance: ReactTestInstance | React.ReactElement, - message?: string -) => void; - -export type DebugAPI = DebugFunction & { - shallow: DebugFunction; - deep: ( - instance: React.ReactElement | ReactTestRendererJSON | null, - message?: string - ) => void; -}; - export declare const render: ( component: React.ReactElement, options?: RenderOptions ) => RenderAPI; -export declare const shallow:

( - instance: ReactTestInstance | React.ReactElement

-) => { output: React.ReactElement

}; -export declare const flushMicrotasksQueue: () => Promise; + export declare const cleanup: () => void; -export declare const debug: DebugAPI; export declare const fireEvent: FireEventAPI; -export declare const waitForElement: WaitForElementFunction; +export declare const waitFor: WaitForFunction; export declare const act: (callback: () => void) => Thenable; export declare const within: (instance: ReactTestInstance) => Queries; + +/** + * @deprecated This function has been removed. Please use `waitFor` function. + */ +export declare const waitForElement: WaitForFunction; + +/** + * @deprecated This function has been deprecated and will be removed in the next release. + */ +export declare const flushMicrotasksQueue: () => Promise; + +/** + * @deprecated This function has been removed. + */ +export declare const shallow:

( + instance: ReactTestInstance | React.ReactElement

+) => { output: React.ReactElement

}; diff --git a/website/docs/API.md b/website/docs/API.md index 62176f09b..a5ad19ed1 100644 --- a/website/docs/API.md +++ b/website/docs/API.md @@ -74,7 +74,11 @@ Re-render the in-memory tree with a new root element. This simulates a React upd unmount(): void ``` -Unmount the in-memory tree, triggering the appropriate lifecycle events +Unmount the in-memory tree, triggering the appropriate lifecycle events. + +:::note +Usually you should not need to call `unmount` as it is done automatically if your test runner supports `afterEach` hook (like Jest, mocha, Jasmine). +::: ### `debug` @@ -123,10 +127,14 @@ const cleanup: () => void; Unmounts React trees that were mounted with `render`. +:::info +Please note that this is done automatically if the testing framework you're using supports the `afterEach` global (like mocha, Jest, and Jasmine). If not, you will need to do manual cleanups after each test. +::: + For example, if you're using the `jest` testing framework, then you would need to use the `afterEach` hook like so: ```jsx -import { cleanup, render } from 'react-native-testing-library'; +import { cleanup, render } from 'react-native-testing-library/pure'; import { View } from 'react-native'; afterEach(cleanup); @@ -313,29 +321,32 @@ fireEvent.scroll(getByType(ScrollView), eventData); expect(onEndReached).toHaveBeenCalled(); ``` -## `waitForElement` +## `waitFor` -- [`Example code`](https://github.com/callstack/react-native-testing-library/blob/master/src/__tests__/waitForElement.test.js) +- [`Example code`](https://github.com/callstack/react-native-testing-library/blob/master/src/__tests__/waitFor.test.js) Defined as: ```jsx -function waitForElement( +function waitFor( expectation: () => T, - timeout: number = 4500, - interval: number = 50 + { timeout: number = 4500, interval: number = 50 } ): Promise {} ``` -Waits for non-deterministic periods of time until your element appears or times out. `waitForElement` periodically calls `expectation` every `interval` milliseconds to determine whether the element appeared or not. +Waits for non-deterministic periods of time until your element appears or times out. `waitFor` periodically calls `expectation` every `interval` milliseconds to determine whether the element appeared or not. + +:::info +In order to properly use `waitFor` you need at least React >=16.9.0 (featuring async `act`) or React Native >=0.60 (which comes with React >=16.9.0). +::: ```jsx -import { render, waitForElement } from 'react-testing-library'; +import { render, waitFor } from 'react-testing-library'; test('waiting for an Banana to be ready', async () => { const { getByText } = render(); - await waitForElement(() => getByText('Banana ready')); + await waitFor(() => getByText('Banana ready')); }); ``` @@ -370,78 +381,6 @@ Use cases for scoped queries include: - queries scoped to a single item inside a FlatList containing many items - queries scoped to a single screen in tests involving screen transitions (e.g. with react-navigation) -## `debug` - -- [`Example code`](https://github.com/callstack/react-native-testing-library/blob/master/src/__tests__/debug.test.js) - -Log prettified shallowly rendered component or test instance (just like snapshot) to stdout. - -```jsx -import { debug } from 'react-native-testing-library'; - -debug(); -debug.shallow(); // an alias for `debug` -``` - -logs: - -```jsx - - - -``` - -There's also `debug.deep` that renders deeply to stdout. - -```jsx -import { debug } from 'react-native-testing-library'; - -debug.deep(); -debug.deep(toJSON(), 'actually debug JSON too'); // useful when Component state changes -``` - -logs: - -```jsx - - - Press me - - -``` - -Optionally you can provide a string message as a second argument to `debug`, which will be displayed right after the component. - -## `flushMicrotasksQueue` - -Waits for microtasks queue to flush. Useful if you want to wait for some promises with `async/await`. - -```jsx -import { flushMicrotasksQueue, render } from 'react-native-testing-library'; - -test('fetch data', async () => { - const { getByText } = render(); - getByText('fetch'); - await flushMicrotasksQueue(); - expect(getByText('fetch').props.title).toBe('loaded'); -}); -``` - ## `query` APIs Each of the get APIs listed in the render section above have a complimentary query API. The get APIs will throw errors if a proper node cannot be found. This is normally the desired effect. However, if you want to make an assertion that an element is not present in the hierarchy, then you can use the query API instead: @@ -468,4 +407,4 @@ expect(submitButtons).toHaveLength(3); // expect 3 elements ## `act` -Useful function to help testing components that use hooks API. By default any `render`, `update`, and `fireEvent` calls are wrapped by this function, so there is no need to wrap it manually. This method is re-exported from [`react-test-renderer`](https://github.com/facebook/react/blob/master/packages/react-test-renderer/src/ReactTestRenderer.js#L567]). +Useful function to help testing components that use hooks API. By default any `render`, `update`, `fireEvent`, and `waitFor` calls are wrapped by this function, so there is no need to wrap it manually. This method is re-exported from [`react-test-renderer`](https://github.com/facebook/react/blob/master/packages/react-test-renderer/src/ReactTestRenderer.js#L567]). diff --git a/website/docs/GettingStarted.md b/website/docs/GettingStarted.md index dc69fac3e..ebe68f750 100644 --- a/website/docs/GettingStarted.md +++ b/website/docs/GettingStarted.md @@ -66,6 +66,10 @@ This library has a peerDependencies listing for `react-test-renderer` and, of co As you may have noticed, it's not tied to React Native at all – you can safely use it in your React components if you feel like not interacting directly with DOM. +:::info +In order to properly use helpers for async tests (`findBy` queries and `waitFor`) you need at least React >=16.9.0 (featuring async `act`) or React Native >=0.60 (which comes with React >=16.9.0). +::: + ### Additional Jest matchers In order to use addtional React Native-specific jest matchers from [@testing-library/jest-native](https://github.com/testing-library/jest-native) package add it to your project: diff --git a/website/docs/MigrationV2.md b/website/docs/MigrationV2.md new file mode 100644 index 000000000..2a0a5a98c --- /dev/null +++ b/website/docs/MigrationV2.md @@ -0,0 +1,130 @@ +--- +id: migration-v2 +title: Migration to 2.0 +--- + +This guide describes steps necessary to migrate from React Native Testing Library `v1.x` to `v2.0`. + +## Dropping Node 8 + +Node 8 reached its EOL more than 5 months ago, so it's about time to target the library to Node 10. If you used lower version, you'll have to upgrade to v10, but we recommend using the latest LTS version. + +## Auto Cleanup + +`cleanup()` function is now called automatically after every test if your testing framework supports `afterEach` hook (like Jest, Mocha, and Jasmine). + +You should be able to remove all `afterEach(cleanup)` calls in your code. + +This change might break your code, if you tests are not isolated, i.e. you call `render` outside `test` block. Generally, you should [keep your tests isolated](https://kentcdodds.com/blog/test-isolation-with-react). But if you can't or don't want to do this right away you can prevent this behavior using any of the following ways: + +- by importing `'react-native-testing-library/pure'` instead of `'react-native-testing-library'` +- by importing `'react-native-testing-library/dont-cleanup-after-each'` before importing `'react-native-testing-library'`. You can do it in a global way by using Jest's `setupFiles` like this: + + ```json + { + "setupFiles": ["react-native-testing-library/dont-cleanup-after-each"]; + } + ``` + +- by setting `RTNL_SKIP_AUTO_CLEANUP` env variable to `true`. You can do this with `cross-evn` like this: + + ```sh + cross-env RNTL_SKIP_AUTO_CLEANUP=true jest + ``` + +## WaitFor API changes + +We renamed `waitForElement` function to `waitFor` for consistency with React Testing Library. Additionally, the signature has slightly changed from: + +```jsx +export default function waitForElement( + expectation: () => T, + timeout?: number, + interval?: number +): Promise {} +``` + +to: + +```jsx +export default function waitFor( + expectation: () => T, + options: { + timeout?: number, + interval?: number, + } +): Promise {} +``` + +Both changes should improve code readibility. + +`waitFor` calls (and hence also `findBy` queries) are now wrapped in `act` by default, so that you should no longer need to use `act` directly in your tests. + +:::tip +You can usually avoid `waitFor` by a proper use of `findBy` asynchronous queries. It will result in more streamlined testing experience. +::: + +## Removed global `debug` function + +The `debug()` method returned from `render()` function is all you need. We removed the global export to avoid confusion. + +## Removed global `shallow` function + +Shallow rendering React component is usually not a good idea, so we decided to remove the API. But, if you find it useful or need to support legacy tests, feel free to use this implementation: + +```js +import ShallowRenderer from 'react-test-renderer/shallow'; + +export function shallow(instance: ReactTestInstance | React.Element) { + const renderer = new ShallowRenderer(); + renderer.render(React.createElement(instance.type, instance.props)); + + return { output: renderer.getRenderOutput() }; +} +``` + +## Removed functions + +Following query functions have been removed after being deprecated for more than a year now: + +- `getByName` +- `getAllByName` +- `queryByName` +- `queryAllByName` + +The `*ByType` and `*ByProps` queries has been prefixed with `UNSAFE_`. You can rename them using global search/replace in your project: + +- `getByType` -> `UNSAFE_getByType` +- `getAllByType` -> `UNSAFE_getAllByType` +- `queryByType` -> `UNSAFE_queryByType` +- `queryAllByType` -> `UNSAFE_queryAllByType` +- `getByProps` -> `UNSAFE_getByProps` +- `getAllByProps` -> `UNSAFE_getAllByProps` +- `queryByProps` -> `UNSAFE_queryByProps` +- `queryAllByProps` -> `UNSAFE_queryAllByProps` + +## Some `ByTestId` queries behavior changes + +In version `1.x` the `getByTestId` and `queryByTestId` queries could return non-native tinstances. This was a serious bug. Other query functions like `getAllByTestId`, `queryAllByTestId`, `findByTestId` and `findAllByTestId` didn't have this issue. These correctly returned only native components instances (e.g. `View`, `Text`, etc) that got the `testID`. + +In v2 we fixed this inconsistency, which may result in failing tests, if you relied on this behavior. There are few ways to handle these failures: + +- pass the `testID` prop down so it can reach a native component, like `View` or `Text` +- replace `testID` with proper `accessibilityHint` or `accessibilityLabel` if it benefits the user +- use safe queries like `*ByText` or `*ByA11yHint` + +:::caution +In general, you should avoid `*byTestId` queries when possible. Use queries that check things that the user can interact with. Like `*ByText` or `*ByPlaceholder` or accessibility queries (e.g. `*ByA11yHint`, `*ByA11yLabel`). +::: + +## Deprecated `flushMicrotasksQueue` + +We have deprecated `flushMicrotasksQueue` and plan to remove it in the next major. We have better alternatives available for helping you write async tests – `findBy` async queries and `waitFor` helper. + +If you can't or don't want to migrate your tests, don't worry. You can use the same implementation we have today: + +```js +function flushMicrotasksQueue() { + return new Promise((resolve) => setImmediate(resolve)); +} +``` diff --git a/website/docs/Queries.md b/website/docs/Queries.md index ab1465f1a..5a288b119 100644 --- a/website/docs/Queries.md +++ b/website/docs/Queries.md @@ -32,9 +32,12 @@ title: Queries `findAllBy` queries return a promise which resolves to an array when any matching elements are found. The promise is rejected if no elements match after a default timeout of 4500ms. +:::info +In order to properly use `findBy` and `findAllBy` queries you need at least React >=16.9.0 (featuring async `act`) or React Native >=0.60 (which comes with React >=16.9.0). +::: :::info -`findBy` and `findAllBy` queries accept optional `waitForOptions` object argument which can contain `timeout` and `interval` properies which have the same meaning as respective arguments to [`waitForElement`](https://callstack.github.io/react-native-testing-library/docs/api#waitforelement) function. +`findBy` and `findAllBy` queries accept optional `waitForOptions` object argument which can contain `timeout` and `interval` properies which have the same meaning as respective options for [`waitFor`](https://callstack.github.io/react-native-testing-library/docs/api#waitfor) function. ::: ## Queries @@ -105,11 +108,7 @@ const element = getByTestId('unique-id'); ``` :::caution -Please be mindful when using these API and **treat it as an escape hatch**. Your users can't interact with `testID` anyhow, so you may end up writing tests that provide false sense of security. Favor text and accessibility queries instead. -::: - -:::danger -Current implementation of `getByTestId` and `queryByTestId` has a serious flaw, which results in finding more IDs than there really would be present in native React host components. Fixing it may break some of your tests so we'll do it in next major release (v2). As a temporary workaround, please use `getAllByTestId('your-id')[0]` or `queryAllByTestId('your-id')[0]` or migrate off testing with testID, which is considered to be an escape hatch. +Please be mindful when using these API and **treat it as an escape hatch**. Your users can't interact with `testID` anyhow, so you may end up writing tests that provide false sense of security. Favor text and accessibility queries instead. ::: ### `ByA11yLabel`, `ByAccessibilityLabel` @@ -208,23 +207,24 @@ const element = getByA11yValue({ min: 40 }); The interface is the same as for other queries, but we won't provide full names so that they're harder to find by search engines. -### `UNSAFE_ByType`, `ByType` - -> Note: added in v1.4 +### `UNSAFE_ByType` -> This method has been **deprecated** and has been prepended with `UNSAFE_` prefix. In react-native-testing-library 2.x only the prefixed version will work. +> UNSAFE_getByType, UNSAFE_getAllByType, UNSAFE_queryByType, UNSAFE_queryAllByType -A method returning a `ReactTestInstance` with matching a React component type. Throws when no matches. +Returns a `ReactTestInstance` with matching a React component type. -### `UNSAFE_ByProps`, `ByProps` +:::caution +This method has been marked unsafe, since it requires knowledge about implementation details of the component. Use responsibly. +::: -> This method has been **deprecated** and has been prepended with `UNSAFE_` prefix. In react-native-testing-library 2.x only the prefixed version will work. +### `UNSAFE_ByProps` -A method returning a `ReactTestInstance` with matching props object +> UNSAFE_getByProps, UNSAFE_getAllByProps, UNSAFE_queryByProps, UNSAFE_queryAllByProps -### `ByName` +Returns a `ReactTestInstance` with matching props object. -> This method has been **deprecated** because using it results in fragile tests that may break between minor React Native versions. **DON'T USE IT**. It will be removed in next major release (v2.0). Use the other alternatives, such as [`getByText`](#bytext) instead. It's listed here only for back-compat purposes for early adopters of the library -> A method returning a `ReactTestInstance` with matching a React component type. Throws when no matches. +:::caution +This method has been marked unsafe, since it requires knowledge about implementation details of the component. Use responsibly. +::: diff --git a/website/docs/ReactNavigation.md b/website/docs/ReactNavigation.md index 0d4ced387..bdf574184 100644 --- a/website/docs/ReactNavigation.md +++ b/website/docs/ReactNavigation.md @@ -54,7 +54,7 @@ export default function HomeScreen({ navigation }) { new Array(20).fill(null).map((_, idx) => idx + 1) ); - const onOpacityPress = item => navigation.navigate('Details', item); + const onOpacityPress = (item) => navigation.navigate('Details', item); return ( @@ -162,8 +162,6 @@ import AppNavigator from '../AppNavigator'; jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper'); describe('Testing react navigation', () => { - afterEach(cleanup); - test('page contains the header and 10 items', () => { const component = ( diff --git a/website/sidebars.js b/website/sidebars.js index 67b9b5d86..1d5e0411a 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -2,6 +2,7 @@ module.exports = { docs: { Introduction: ['getting-started'], 'API Reference': ['api', 'api-queries'], + Guides: ['migration-v2'], Examples: ['react-navigation', 'redux-integration'], }, }; diff --git a/yarn.lock b/yarn.lock index 1f76f9947..bd7587a25 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,6 +25,15 @@ dependencies: "@babel/highlight" "^7.8.3" +"@babel/compat-data@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.6.tgz#3f604c40e420131affe6f2c8052e9a275ae2049b" + integrity sha512-5QPTrNen2bm7RBc7dsOmcA5hbrS4O2Vhmk5XOL4zWW/zD/hV0iinpefDlkm+tBBy8kDtFaaeEvmAqt+nURAV2g== + dependencies: + browserslist "^4.11.1" + invariant "^2.2.4" + semver "^5.5.0" + "@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.7.5", "@babel/core@^7.9.0": version "7.9.6" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.6.tgz#d9aa1f580abf3b2286ef40b6904d390904c63376" @@ -89,6 +98,17 @@ "@babel/helper-annotate-as-pure" "^7.8.3" "@babel/types" "^7.9.0" +"@babel/helper-compilation-targets@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.9.6.tgz#1e05b7ccc9d38d2f8b40b458b380a04dcfadd38a" + integrity sha512-x2Nvu0igO0ejXzx09B/1fGBxY9NXQlBW2kZsSxCJft+KHN8t9XWzIvFxtPHnBOAXpVsdxZKZFbRUC8TsNKajMw== + dependencies: + "@babel/compat-data" "^7.9.6" + browserslist "^4.11.1" + invariant "^2.2.4" + levenary "^1.1.1" + semver "^5.5.0" + "@babel/helper-create-class-features-plugin@^7.8.3": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.9.5.tgz#79753d44017806b481017f24b02fd4113c7106ea" @@ -101,7 +121,7 @@ "@babel/helper-replace-supers" "^7.8.6" "@babel/helper-split-export-declaration" "^7.8.3" -"@babel/helper-create-regexp-features-plugin@^7.8.3": +"@babel/helper-create-regexp-features-plugin@^7.8.3", "@babel/helper-create-regexp-features-plugin@^7.8.8": version "7.8.8" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz#5d84180b588f560b7864efaeea89243e58312087" integrity sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg== @@ -143,6 +163,13 @@ dependencies: "@babel/types" "^7.8.3" +"@babel/helper-hoist-variables@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" + integrity sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-member-expression-to-functions@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" @@ -270,7 +297,16 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-proposal-class-properties@^7.0.0": +"@babel/plugin-proposal-async-generator-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" + integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + +"@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz#5e06654af5cd04b608915aada9b2a6788004464e" integrity sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA== @@ -278,6 +314,14 @@ "@babel/helper-create-class-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-proposal-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" + integrity sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-proposal-export-default-from@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.8.3.tgz#4cb7c2fdeaed490b60d9bfd3dc8a20f81f9c2e7c" @@ -286,7 +330,15 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-export-default-from" "^7.8.3" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.0.0": +"@babel/plugin-proposal-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" + integrity sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.0" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.0.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== @@ -294,6 +346,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" +"@babel/plugin-proposal-numeric-separator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" + integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-proposal-object-rest-spread@^7.0.0": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz#3fd65911306d8746014ec0d0cf78f0e39a149116" @@ -303,7 +363,16 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-transform-parameters" "^7.9.5" -"@babel/plugin-proposal-optional-catch-binding@^7.0.0": +"@babel/plugin-proposal-object-rest-spread@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.6.tgz#7a093586fcb18b08266eb1a7177da671ac575b63" + integrity sha512-Ga6/fhGqA9Hj+y6whNpPv8psyaK5xzrQwSPsGPloVkvmH+PqW1ixdnfJ9uIO06OjQNYol3PMnfmJ8vfZtkzF+A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.9.5" + +"@babel/plugin-proposal-optional-catch-binding@^7.0.0", "@babel/plugin-proposal-optional-catch-binding@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" integrity sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw== @@ -311,7 +380,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.0.0": +"@babel/plugin-proposal-optional-chaining@^7.0.0", "@babel/plugin-proposal-optional-chaining@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== @@ -319,7 +388,15 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-syntax-async-generators@^7.8.4": +"@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": + version "7.8.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" + integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.8" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== @@ -340,7 +417,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-dynamic-import@^7.0.0": +"@babel/plugin-syntax-dynamic-import@^7.0.0", "@babel/plugin-syntax-dynamic-import@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== @@ -361,7 +438,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-json-strings@^7.8.3": +"@babel/plugin-syntax-json-strings@^7.8.0", "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== @@ -389,7 +466,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.3": +"@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" integrity sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw== @@ -417,6 +494,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" + integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-typescript@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.8.3.tgz#c1f659dda97711a569cef75275f7e15dcaa6cabc" @@ -424,14 +508,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-arrow-functions@^7.0.0": +"@babel/plugin-transform-arrow-functions@^7.0.0", "@babel/plugin-transform-arrow-functions@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-async-to-generator@^7.0.0": +"@babel/plugin-transform-async-to-generator@^7.0.0", "@babel/plugin-transform-async-to-generator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== @@ -440,14 +524,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/helper-remap-async-to-generator" "^7.8.3" -"@babel/plugin-transform-block-scoped-functions@^7.0.0": +"@babel/plugin-transform-block-scoped-functions@^7.0.0", "@babel/plugin-transform-block-scoped-functions@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-block-scoping@^7.0.0": +"@babel/plugin-transform-block-scoping@^7.0.0", "@babel/plugin-transform-block-scoping@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== @@ -455,7 +539,7 @@ "@babel/helper-plugin-utils" "^7.8.3" lodash "^4.17.13" -"@babel/plugin-transform-classes@^7.0.0": +"@babel/plugin-transform-classes@^7.0.0", "@babel/plugin-transform-classes@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz#800597ddb8aefc2c293ed27459c1fcc935a26c2c" integrity sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg== @@ -469,21 +553,36 @@ "@babel/helper-split-export-declaration" "^7.8.3" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.0.0": +"@babel/plugin-transform-computed-properties@^7.0.0", "@babel/plugin-transform-computed-properties@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-destructuring@^7.0.0": +"@babel/plugin-transform-destructuring@^7.0.0", "@babel/plugin-transform-destructuring@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz#72c97cf5f38604aea3abf3b935b0e17b1db76a50" integrity sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-exponentiation-operator@^7.0.0": +"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" + integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-duplicate-keys@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" + integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-exponentiation-operator@^7.0.0", "@babel/plugin-transform-exponentiation-operator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ== @@ -491,7 +590,7 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-flow-strip-types@^7.0.0": +"@babel/plugin-transform-flow-strip-types@^7.0.0", "@babel/plugin-transform-flow-strip-types@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.9.0.tgz#8a3538aa40434e000b8f44a3c5c9ac7229bd2392" integrity sha512-7Qfg0lKQhEHs93FChxVLAvhBshOPQDtJUTVHr/ZwQNRccCm4O9D79r9tVSoV8iNwjP1YgfD+e/fgHcPkN1qEQg== @@ -499,14 +598,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-flow" "^7.8.3" -"@babel/plugin-transform-for-of@^7.0.0": +"@babel/plugin-transform-for-of@^7.0.0", "@babel/plugin-transform-for-of@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e" integrity sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-function-name@^7.0.0": +"@babel/plugin-transform-function-name@^7.0.0", "@babel/plugin-transform-function-name@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== @@ -514,20 +613,29 @@ "@babel/helper-function-name" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-literals@^7.0.0": +"@babel/plugin-transform-literals@^7.0.0", "@babel/plugin-transform-literals@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-member-expression-literals@^7.0.0": +"@babel/plugin-transform-member-expression-literals@^7.0.0", "@babel/plugin-transform-member-expression-literals@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" integrity sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA== dependencies: "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-transform-modules-amd@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.6.tgz#8539ec42c153d12ea3836e0e3ac30d5aae7b258e" + integrity sha512-zoT0kgC3EixAyIAU+9vfaUVKTv9IxBDSabgHoUCBP6FqEJ+iNiN7ip7NBKcYqbfUDfuC2mFCbM7vbu4qJgOnDw== + dependencies: + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-commonjs@^7.0.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz#e3e72f4cbc9b4a260e30be0ea59bdf5a39748940" @@ -538,6 +646,48 @@ "@babel/helper-simple-access" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.0" +"@babel/plugin-transform-modules-commonjs@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.6.tgz#64b7474a4279ee588cacd1906695ca721687c277" + integrity sha512-7H25fSlLcn+iYimmsNe3uK1at79IE6SKW9q0/QeEHTMC9MdOZ+4bA+T1VFB5fgOqBWoqlifXRzYD0JPdmIrgSQ== + dependencies: + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-simple-access" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-systemjs@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.6.tgz#207f1461c78a231d5337a92140e52422510d81a4" + integrity sha512-NW5XQuW3N2tTHim8e1b7qGy7s0kZ2OH3m5octc49K1SdAKGxYxeIx7hiIz05kS1R2R+hOWcsr1eYwcGhrdHsrg== + dependencies: + "@babel/helper-hoist-variables" "^7.8.3" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-umd@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz#e909acae276fec280f9b821a5f38e1f08b480697" + integrity sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ== + dependencies: + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" + integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + +"@babel/plugin-transform-new-target@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" + integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-object-assign@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.8.3.tgz#dc3b8dd50ef03837868a37b7df791f64f288538e" @@ -545,7 +695,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-object-super@^7.0.0": +"@babel/plugin-transform-object-super@^7.0.0", "@babel/plugin-transform-object-super@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== @@ -561,21 +711,30 @@ "@babel/helper-get-function-arity" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-property-literals@^7.0.0": +"@babel/plugin-transform-property-literals@^7.0.0", "@babel/plugin-transform-property-literals@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" integrity sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-react-display-name@^7.0.0": +"@babel/plugin-transform-react-display-name@^7.0.0", "@babel/plugin-transform-react-display-name@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.8.3.tgz#70ded987c91609f78353dd76d2fb2a0bb991e8e5" integrity sha512-3Jy/PCw8Fe6uBKtEgz3M82ljt+lTg+xJaM4og+eyu83qLT87ZUSckn0wy7r31jflURWLO83TW6Ylf7lyXj3m5A== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-react-jsx-self@^7.0.0": +"@babel/plugin-transform-react-jsx-development@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.9.0.tgz#3c2a130727caf00c2a293f0aed24520825dbf754" + integrity sha512-tK8hWKrQncVvrhvtOiPpKrQjfNX3DtkNLSX4ObuGcpS9p0QrGetKmlySIGR07y48Zft8WVgPakqd/bk46JrMSw== + dependencies: + "@babel/helper-builder-react-jsx-experimental" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-jsx" "^7.8.3" + +"@babel/plugin-transform-react-jsx-self@^7.0.0", "@babel/plugin-transform-react-jsx-self@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.9.0.tgz#f4f26a325820205239bb915bad8e06fcadabb49b" integrity sha512-K2ObbWPKT7KUTAoyjCsFilOkEgMvFG+y0FqOl6Lezd0/13kMkkjHskVsZvblRPj1PHA44PrToaZANrryppzTvQ== @@ -583,7 +742,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" -"@babel/plugin-transform-react-jsx-source@^7.0.0": +"@babel/plugin-transform-react-jsx-source@^7.0.0", "@babel/plugin-transform-react-jsx-source@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.9.0.tgz#89ef93025240dd5d17d3122294a093e5e0183de0" integrity sha512-K6m3LlSnTSfRkM6FcRk8saNEeaeyG5k7AVkBU2bZK3+1zdkSED3qNdsWrUgQBeTVD2Tp3VMmerxVO2yM5iITmw== @@ -591,7 +750,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" -"@babel/plugin-transform-react-jsx@^7.0.0": +"@babel/plugin-transform-react-jsx@^7.0.0", "@babel/plugin-transform-react-jsx@^7.9.4": version "7.9.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.9.4.tgz#86f576c8540bd06d0e95e0b61ea76d55f6cbd03f" integrity sha512-Mjqf3pZBNLt854CK0C/kRuXAnE6H/bo7xYojP+WGtX8glDGSibcwnsWwhwoSuRg0+EBnxPC1ouVnuetUIlPSAw== @@ -601,13 +760,20 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" -"@babel/plugin-transform-regenerator@^7.0.0": +"@babel/plugin-transform-regenerator@^7.0.0", "@babel/plugin-transform-regenerator@^7.8.7": version "7.8.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8" integrity sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA== dependencies: regenerator-transform "^0.14.2" +"@babel/plugin-transform-reserved-words@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" + integrity sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-runtime@^7.0.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.0.tgz#45468c0ae74cc13204e1d3b1f4ce6ee83258af0b" @@ -618,21 +784,21 @@ resolve "^1.8.1" semver "^5.5.1" -"@babel/plugin-transform-shorthand-properties@^7.0.0": +"@babel/plugin-transform-shorthand-properties@^7.0.0", "@babel/plugin-transform-shorthand-properties@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-spread@^7.0.0": +"@babel/plugin-transform-spread@^7.0.0", "@babel/plugin-transform-spread@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-sticky-regex@^7.0.0": +"@babel/plugin-transform-sticky-regex@^7.0.0", "@babel/plugin-transform-sticky-regex@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== @@ -640,7 +806,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/helper-regex" "^7.8.3" -"@babel/plugin-transform-template-literals@^7.0.0": +"@babel/plugin-transform-template-literals@^7.0.0", "@babel/plugin-transform-template-literals@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ== @@ -648,6 +814,13 @@ "@babel/helper-annotate-as-pure" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-transform-typeof-symbol@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" + integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-typescript@^7.5.0": version "7.9.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.9.4.tgz#4bb4dde4f10bbf2d787fce9707fb09b483e33359" @@ -657,7 +830,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-typescript" "^7.8.3" -"@babel/plugin-transform-unicode-regex@^7.0.0": +"@babel/plugin-transform-unicode-regex@^7.0.0", "@babel/plugin-transform-unicode-regex@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw== @@ -665,6 +838,103 @@ "@babel/helper-create-regexp-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" +"@babel/preset-env@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.6.tgz#df063b276c6455ec6fcfc6e53aacc38da9b0aea6" + integrity sha512-0gQJ9RTzO0heXOhzftog+a/WyOuqMrAIugVYxMYf83gh1CQaQDjMtsOpqOwXyDL/5JcWsrCm8l4ju8QC97O7EQ== + dependencies: + "@babel/compat-data" "^7.9.6" + "@babel/helper-compilation-targets" "^7.9.6" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-proposal-async-generator-functions" "^7.8.3" + "@babel/plugin-proposal-dynamic-import" "^7.8.3" + "@babel/plugin-proposal-json-strings" "^7.8.3" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-proposal-numeric-separator" "^7.8.3" + "@babel/plugin-proposal-object-rest-spread" "^7.9.6" + "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" + "@babel/plugin-proposal-optional-chaining" "^7.9.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.8.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.8.3" + "@babel/plugin-transform-async-to-generator" "^7.8.3" + "@babel/plugin-transform-block-scoped-functions" "^7.8.3" + "@babel/plugin-transform-block-scoping" "^7.8.3" + "@babel/plugin-transform-classes" "^7.9.5" + "@babel/plugin-transform-computed-properties" "^7.8.3" + "@babel/plugin-transform-destructuring" "^7.9.5" + "@babel/plugin-transform-dotall-regex" "^7.8.3" + "@babel/plugin-transform-duplicate-keys" "^7.8.3" + "@babel/plugin-transform-exponentiation-operator" "^7.8.3" + "@babel/plugin-transform-for-of" "^7.9.0" + "@babel/plugin-transform-function-name" "^7.8.3" + "@babel/plugin-transform-literals" "^7.8.3" + "@babel/plugin-transform-member-expression-literals" "^7.8.3" + "@babel/plugin-transform-modules-amd" "^7.9.6" + "@babel/plugin-transform-modules-commonjs" "^7.9.6" + "@babel/plugin-transform-modules-systemjs" "^7.9.6" + "@babel/plugin-transform-modules-umd" "^7.9.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" + "@babel/plugin-transform-new-target" "^7.8.3" + "@babel/plugin-transform-object-super" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.9.5" + "@babel/plugin-transform-property-literals" "^7.8.3" + "@babel/plugin-transform-regenerator" "^7.8.7" + "@babel/plugin-transform-reserved-words" "^7.8.3" + "@babel/plugin-transform-shorthand-properties" "^7.8.3" + "@babel/plugin-transform-spread" "^7.8.3" + "@babel/plugin-transform-sticky-regex" "^7.8.3" + "@babel/plugin-transform-template-literals" "^7.8.3" + "@babel/plugin-transform-typeof-symbol" "^7.8.4" + "@babel/plugin-transform-unicode-regex" "^7.8.3" + "@babel/preset-modules" "^0.1.3" + "@babel/types" "^7.9.6" + browserslist "^4.11.1" + core-js-compat "^3.6.2" + invariant "^2.2.2" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/preset-flow@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.9.0.tgz#fee847c3e090b0b2d9227c1949e4da1d1379280d" + integrity sha512-88uSmlshIrlmPkNkEcx3UpSZ6b8n0UGBq0/0ZMZCF/uxAW0XIAUuDHBhIOAh0pvweafH4RxOwi/H3rWhtqOYPA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-flow-strip-types" "^7.9.0" + +"@babel/preset-modules@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" + integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-react@^7.9.4": + version "7.9.4" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.9.4.tgz#c6c97693ac65b6b9c0b4f25b948a8f665463014d" + integrity sha512-AxylVB3FXeOTQXNXyiuAQJSvss62FEotbX2Pzx3K/7c+MKJMdSg6Ose6QYllkdCFA8EInCJVw7M/o5QbLuA4ZQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-react-display-name" "^7.8.3" + "@babel/plugin-transform-react-jsx" "^7.9.4" + "@babel/plugin-transform-react-jsx-development" "^7.9.0" + "@babel/plugin-transform-react-jsx-self" "^7.9.0" + "@babel/plugin-transform-react-jsx-source" "^7.9.0" + "@babel/register@^7.0.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.9.0.tgz#02464ede57548bddbb5e9f705d263b7c3f43d48b" @@ -715,7 +985,16 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5", "@babel/types@^7.9.6": +"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444" + integrity sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg== + dependencies: + "@babel/helper-validator-identifier" "^7.9.5" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.9.6": version "7.9.6" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7" integrity sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA== @@ -1947,7 +2226,7 @@ babel-jest@^26.0.1: graceful-fs "^4.2.4" slash "^3.0.0" -babel-plugin-dynamic-import-node@^2.3.0: +babel-plugin-dynamic-import-node@^2.3.0, babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== @@ -2157,6 +2436,16 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== +browserslist@^4.11.1, browserslist@^4.8.5: + version "4.12.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" + integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg== + dependencies: + caniuse-lite "^1.0.30001043" + electron-to-chromium "^1.3.413" + node-releases "^1.1.53" + pkg-up "^2.0.0" + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -2295,6 +2584,11 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w== +caniuse-lite@^1.0.30001043: + version "1.0.30001058" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001058.tgz#9f8a318389e28f060272274ac93a661d17f8bf0d" + integrity sha512-UiRZmBYd1HdVVdFKy7PuLVx9e2NS7SMyx7QpWvFjiklYrLJKpLd19cRnRNqlw4zYa7vVejS3c8JUVobX241zHQ== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -2853,6 +3147,14 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= +core-js-compat@^3.6.2: + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" + integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng== + dependencies: + browserslist "^4.8.5" + semver "7.0.0" + core-js-pure@^3.0.0: version "3.6.5" resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" @@ -3233,6 +3535,11 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= +electron-to-chromium@^1.3.413: + version "1.3.437" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.437.tgz#110f1cd407e5d09b43d5585e5f237b71063412cf" + integrity sha512-PBQn2q68ErqMyBUABh9Gh8R6DunGky8aB5y3N5lPM7OVpldwyUbAK5AX9WcwE/5F6ceqvQ+iQLYkJYRysAs6Bg== + emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -4555,7 +4862,7 @@ interpret@^1.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== -invariant@^2.2.4: +invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -5673,6 +5980,13 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== +levenary@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" + integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== + dependencies: + leven "^3.1.0" + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -6099,7 +6413,7 @@ metro-minify-uglify@0.58.0: dependencies: uglify-es "^3.1.9" -metro-react-native-babel-preset@0.58.0, metro-react-native-babel-preset@^0.58.0: +metro-react-native-babel-preset@0.58.0: version "0.58.0" resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.58.0.tgz#18f48d33fe124280ffabc000ab8b42c488d762a2" integrity sha512-MRriNW+fF6jxABsgPphocUY6mIhmCm8idcrQZ58fT3Iti2vCdtkaK32TyCGUNUptzhUe2/cbE57j4aC+eaodAA== @@ -6559,6 +6873,11 @@ node-notifier@^7.0.0: uuid "^7.0.3" which "^2.0.2" +node-releases@^1.1.53: + version "1.1.55" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.55.tgz#8af23b7c561d8e2e6e36a46637bab84633b07cee" + integrity sha512-H3R3YR/8TjT5WPin/wOoHOUPHgvj8leuU/Keta/rwelEQN9pA/S2Dx8/se4pZ2LBxSd0nAGzsNzhqwa77v7F1w== + node-stream-zip@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.9.1.tgz#66d210204da7c60e2d6d685eb21a11d016981fd0" @@ -7130,6 +7449,13 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" + integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= + dependencies: + find-up "^2.1.0" + plist@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.1.tgz#a9b931d17c304e8912ef0ba3bdd6182baf2e1f8c" @@ -7976,6 +8302,11 @@ semver-diff@^3.1.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + semver@7.3.2, semver@^7.2.1, semver@^7.3.2: version "7.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"