diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md index c666a0f1b..017f050c4 100644 --- a/docs/GettingStarted.md +++ b/docs/GettingStarted.md @@ -29,8 +29,8 @@ function setAnswer(question, answer) { } test('should verify two questions', () => { - const { getAllByType, getByText } = render(); - const allQuestions = getAllByType(Question); + const { getAllByText, getByText } = render(); + const allQuestions = getAllByText('Question?'); setAnswer(allQuestions[0], 'a1'); setAnswer(allQuestions[1], 'a2'); diff --git a/docs/Queries.md b/docs/Queries.md index 9753dcc83..c90fb8eee 100644 --- a/docs/Queries.md +++ b/docs/Queries.md @@ -139,32 +139,3 @@ import { render } from 'react-native-testing-library'; const { getByA11yRole } = render(); const element = getByA11yRole('button'); ``` - -## Unit testing helpers - -> Use sparingly and responsibly, escape hatches here - -`render` from `react-native-testing-library` exposes additional queries that **should not be used in component integration testing**, but some users (like component library creators) interested in unit testing some components may find helpful. - -
- Queries helpful in unit testing - -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. - -### `ByType` - -> Note: added in v1.4 - -A method returning a `ReactTestInstance` with matching a React component type. Throws when no matches. - -### `ByProps` - -A method returning a `ReactTestInstance` with matching props object - -### `ByName` - -> 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 [`getByTestId`](#bytestid) 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. - -
diff --git a/src/__tests__/__snapshots__/render.test.js.snap b/src/__tests__/__snapshots__/render.test.js.snap index 58f470c13..86e01e89c 100644 --- a/src/__tests__/__snapshots__/render.test.js.snap +++ b/src/__tests__/__snapshots__/render.test.js.snap @@ -118,6 +118,7 @@ exports[`debug: shallow 1`] = ` /> @@ -72,53 +76,6 @@ test('getByTestId, queryByTestId', () => { expect(queryByTestId('InExistent')).toBeNull(); }); -test('getByName, queryByName', () => { - const { getByTestId, getByName, queryByName } = render(); - const bananaFresh = getByTestId('bananaFresh'); - 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 3'); - - 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); - 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(queryAllByType(Text)[1]).toBe(status); - expect(queryAllByType(InExistent)).toHaveLength(0); -}); - test('getByText, queryByText', () => { const { getByText, queryByText } = render(); const button = getByText(/change/i); @@ -200,36 +157,10 @@ test('getAllByPlaceholder, queryAllByPlaceholder', () => { expect(queryAllByPlaceholder('no placeholder')).toHaveLength(0); }); -test('getByProps, queryByProps', () => { - const { getByProps, queryByProps } = render(); - const primaryType = getByProps({ type: 'primary' }); - - expect(primaryType.props.children).toBe('Change freshness!'); - expect(() => getByProps({ type: 'inexistent' })).toThrow( - 'No instances found' - ); - - expect(queryByProps({ type: 'primary' })).toBe(primaryType); - expect(queryByProps({ type: 'inexistent' })).toBeNull(); -}); - -test('getAllByProp, queryAllByProps', () => { - const { getAllByProps, queryAllByProps } = render(); - const primaryTypes = getAllByProps({ type: 'primary' }); - - expect(primaryTypes).toHaveLength(1); - expect(() => getAllByProps({ type: 'inexistent' })).toThrow( - 'No instances found' - ); - - expect(queryAllByProps({ type: 'primary' })).toEqual(primaryTypes); - expect(queryAllByProps({ type: 'inexistent' })).toHaveLength(0); -}); - test('update', () => { const fn = jest.fn(); - const { getByName, update, rerender } = render(); - const button = getByName('Button'); + const { getByTestId, update, rerender } = render(); + const button = getByTestId('changeFreshness'); button.props.onPress(); @@ -278,9 +209,9 @@ test('debug', () => { test('debug changing component', () => { jest.spyOn(console, 'log').mockImplementation(x => x); - const { getByProps, debug } = render(); + const { getByTestId, debug } = render(); - fireEvent.press(getByProps({ type: 'primary' })); + fireEvent.press(getByTestId('changeFreshness')); debug(); diff --git a/src/__tests__/shallow.test.js b/src/__tests__/shallow.test.js deleted file mode 100644 index 927ee1bfc..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 { getByTestId } = render(); - const { output } = shallow(getByTestId('text-button')); - - expect(output).toMatchSnapshot(); -}); diff --git a/src/__tests__/waitForElement.test.js b/src/__tests__/waitForElement.test.js index 231464940..ba954e15e 100644 --- a/src/__tests__/waitForElement.test.js +++ b/src/__tests__/waitForElement.test.js @@ -13,7 +13,7 @@ class Banana extends React.Component<*, *> { return ( {this.props.fresh && Fresh} - + Change freshness! @@ -37,9 +37,9 @@ class BananaContainer extends React.Component<*, *> { } test('waits for element until it stops throwing', async () => { - const { getByTestId, getByName, queryByTestId } = render(); + const { getByTestId, queryByTestId } = render(); - fireEvent.press(getByName('TouchableOpacity')); + fireEvent.press(getByTestId('changeFreshness')); expect(queryByTestId('fresh')).toBeNull(); @@ -49,9 +49,9 @@ test('waits for element until it stops throwing', async () => { }); test('waits for element until timeout is met', async () => { - const { getByTestId, getByName } = render(); + const { getByTestId } = render(); - fireEvent.press(getByName('TouchableOpacity')); + fireEvent.press(getByTestId('changeFreshness')); await expect( waitForElement(() => getByTestId('fresh'), 100) diff --git a/src/helpers/getByAPI.js b/src/helpers/getByAPI.js index c8fe5c429..c5e452535 100644 --- a/src/helpers/getByAPI.js +++ b/src/helpers/getByAPI.js @@ -1,19 +1,13 @@ // @flow import * as React from 'react'; -import prettyFormat from 'pretty-format'; import { ErrorWithStack, createLibraryNotSupportedError, - logDeprecationWarning, prepareErrorMessage, } 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 @@ -54,27 +48,6 @@ const getTextInputNodeByPlaceholder = (node, placeholder) => { } }; -export const getByName = (instance: ReactTestInstance) => - function getByNameFn(name: string | React.ComponentType<*>) { - logDeprecationWarning('getByName', 'getByType'); - 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) => - function getByTypeFn(type: React.ComponentType<*>) { - try { - return instance.findByType(type); - } catch (error) { - throw new ErrorWithStack(prepareErrorMessage(error), getByTypeFn); - } - }; - export const getByText = (instance: ReactTestInstance) => function getByTextFn(text: string | RegExp) { try { @@ -95,15 +68,6 @@ export const getByPlaceholder = (instance: ReactTestInstance) => } }; -export const getByProps = (instance: ReactTestInstance) => - function getByPropsFn(props: { [propName: string]: any }) { - try { - return instance.findByProps(props); - } catch (error) { - throw new ErrorWithStack(prepareErrorMessage(error), getByPropsFn); - } - }; - export const getByTestId = (instance: ReactTestInstance) => function getByTestIdFn(testID: string) { try { @@ -113,28 +77,6 @@ export const getByTestId = (instance: ReactTestInstance) => } }; -export const getAllByName = (instance: ReactTestInstance) => - function getAllByNameFn(name: string | React.ComponentType<*>) { - logDeprecationWarning('getAllByName', 'getAllByType'); - 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) => - 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 getAllByText = (instance: ReactTestInstance) => function getAllByTextFn(text: string | RegExp) { const results = instance.findAll(node => getNodeByText(node, text)); @@ -161,28 +103,10 @@ export const getAllByPlaceholder = (instance: ReactTestInstance) => return results; }; -export const 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), - getByType: getByType(instance), getByText: getByText(instance), getByPlaceholder: getByPlaceholder(instance), - getByProps: getByProps(instance), - getAllByName: getAllByName(instance), - getAllByType: getAllByType(instance), getAllByText: getAllByText(instance), getAllByPlaceholder: getAllByPlaceholder(instance), - getAllByProps: getAllByProps(instance), }); diff --git a/src/helpers/queryByAPI.js b/src/helpers/queryByAPI.js index 8ca7dbff5..06e093ba0 100644 --- a/src/helpers/queryByAPI.js +++ b/src/helpers/queryByAPI.js @@ -1,38 +1,12 @@ // @flow -import * as React from 'react'; import { getByTestId, - getByName, - getByType, getByText, getByPlaceholder, - getByProps, - getAllByName, - getAllByType, getAllByText, getAllByPlaceholder, - getAllByProps, } from './getByAPI'; -import { logDeprecationWarning, createQueryByError } from './errors'; - -export const queryByName = (instance: ReactTestInstance) => - function queryByNameFn(name: string | React.ComponentType<*>) { - logDeprecationWarning('queryByName', 'getByName'); - try { - return getByName(instance)(name); - } catch (error) { - return createQueryByError(error, queryByNameFn); - } - }; - -export const queryByType = (instance: ReactTestInstance) => - function queryByTypeFn(type: React.ComponentType<*>) { - try { - return getByType(instance)(type); - } catch (error) { - return createQueryByError(error, queryByTypeFn); - } - }; +import { createQueryByError } from './errors'; export const queryByText = (instance: ReactTestInstance) => function queryByTextFn(text: string | RegExp) { @@ -52,15 +26,6 @@ export const queryByPlaceholder = (instance: ReactTestInstance) => } }; -export const queryByProps = (instance: ReactTestInstance) => - function queryByPropsFn(props: { [propName: string]: any }) { - try { - return getByProps(instance)(props); - } catch (error) { - return createQueryByError(error, queryByPropsFn); - } - }; - export const queryByTestId = (instance: ReactTestInstance) => function queryByTestIdFn(testID: string) { try { @@ -70,27 +35,6 @@ export const queryByTestId = (instance: ReactTestInstance) => } }; -export const queryAllByName = (instance: ReactTestInstance) => ( - name: string | React.ComponentType<*> -) => { - logDeprecationWarning('queryAllByName', 'getAllByName'); - try { - return getAllByName(instance)(name); - } catch (error) { - return []; - } -}; - -export const queryAllByType = (instance: ReactTestInstance) => ( - type: React.ComponentType<*> -) => { - try { - return getAllByType(instance)(type); - } catch (error) { - return []; - } -}; - export const queryAllByText = (instance: ReactTestInstance) => ( text: string | RegExp ) => { @@ -111,26 +55,10 @@ export const queryAllByPlaceholder = (instance: ReactTestInstance) => ( } }; -export const queryAllByProps = (instance: ReactTestInstance) => (props: { - [propName: string]: any, -}) => { - try { - return getAllByProps(instance)(props); - } catch (error) { - return []; - } -}; - export const queryByAPI = (instance: ReactTestInstance) => ({ queryByTestId: queryByTestId(instance), - queryByName: queryByName(instance), - queryByType: queryByType(instance), queryByText: queryByText(instance), queryByPlaceholder: queryByPlaceholder(instance), - queryByProps: queryByProps(instance), - queryAllByName: queryAllByName(instance), - queryAllByType: queryAllByType(instance), queryAllByText: queryAllByText(instance), queryAllByPlaceholder: queryAllByPlaceholder(instance), - queryAllByProps: queryAllByProps(instance), }); diff --git a/src/index.js b/src/index.js index 42547250c..92aa5d70b 100644 --- a/src/index.js +++ b/src/index.js @@ -1,14 +1,12 @@ // @flow import act from './act'; import render from './render'; -import shallow from './shallow'; import flushMicrotasksQueue from './flushMicrotasksQueue'; import debug from './debug'; import fireEvent from './fireEvent'; import waitForElement from './waitForElement'; export { render }; -export { shallow }; export { flushMicrotasksQueue }; export { debug }; export { fireEvent }; diff --git a/typings/__tests__/index.test.tsx b/typings/__tests__/index.test.tsx index cd14058c1..a3b939b04 100644 --- a/typings/__tests__/index.test.tsx +++ b/typings/__tests__/index.test.tsx @@ -4,7 +4,6 @@ import { ReactTestInstance } from 'react-test-renderer'; import { render, fireEvent, - shallow, flushMicrotasksQueue, debug, waitForElement, @@ -32,12 +31,6 @@ 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( @@ -46,31 +39,13 @@ const getByPlaceholderString: ReactTestInstance = tree.getByPlaceholder( const getByPlaceholderRegExp: ReactTestInstance = tree.getByPlaceholder( /placeholder/g ); -const getByProps: ReactTestInstance = tree.getByProps({ value: 2 }); const getByTestId: ReactTestInstance = tree.getByTestId('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, -}); // 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( '' ); @@ -81,18 +56,7 @@ const queryByPlaceholderString: ReactTestInstance | null = tree.queryByText( const queryByPlaceholderRegExp: ReactTestInstance | null = tree.queryByText( /placeholder/g ); -const queryByProps: ReactTestInstance | null = tree.queryByProps({ value: 2 }); const queryByTestId: ReactTestInstance | null = tree.queryByTestId('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' ); @@ -152,24 +116,19 @@ tree.rerender(); tree.unmount(); // fireEvent API tests -fireEvent(getByNameString, 'press'); -fireEvent(getByNameString, 'press', 'data'); -fireEvent.press(getByNameString); -fireEvent.changeText(getByNameString, 'string'); -fireEvent.scroll(getByNameString, 'eventData'); - -// shallow API -const shallowTree: { output: React.ReactElement } = shallow( - -); +fireEvent(getByTextString, 'press'); +fireEvent(getByTextString, 'press', 'data'); +fireEvent.press(getByTextString); +fireEvent.changeText(getByTextString, 'string'); +fireEvent.scroll(getByTextString, 'eventData'); const waitForFlush: Promise = flushMicrotasksQueue(); // debug API debug(); debug(, 'message'); -debug(getByNameString); -debug(getByNameString, 'message'); +debug(getByTextString); +debug(getByTextString, 'message'); debug.shallow(); debug.shallow(, 'message'); debug.deep(); @@ -177,11 +136,11 @@ debug.deep(, 'message'); debug.deep(tree.toJSON()); const waitBy: Promise = waitForElement( - () => tree.getByName('View') + () => tree.getByText('View') ); const waitByAll: Promise> = waitForElement< Array ->(() => tree.getAllByName('View'), 1000, 50); +>(() => tree.getAllByText('View'), 1000, 50); act(() => { render(); diff --git a/typings/index.d.ts b/typings/index.d.ts index af96bf17c..e3d4979e9 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2,43 +2,25 @@ import * as React from 'react'; import { ReactTestInstance, ReactTestRendererJSON } from 'react-test-renderer'; export interface GetByAPI { - getByName: (name: React.ReactType | string) => ReactTestInstance; - getByType:

(type: React.ComponentType

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

(type: React.ComponentType

) => Array; getAllByText: (text: string | RegExp) => Array; getAllByPlaceholder: ( placeholder: string | RegExp ) => Array; - getAllByProps: (props: Record) => Array; } export 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; - queryByProps: (props: Record) => ReactTestInstance | null; queryByTestId: (testID: string) => ReactTestInstance | null; - queryAllByName: ( - name: React.ReactType | string - ) => Array | []; - queryAllByType:

( - type: React.ComponentType

- ) => Array | []; queryAllByText: (text: string | RegExp) => Array | []; queryAllByPlaceholder: ( placeholder: string | RegExp ) => Array | []; - queryAllByProps: ( - props: Record - ) => Array | []; } type QueryFn = (text: string | RegExp) => ReactTestInstance | null; @@ -120,9 +102,6 @@ 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 debug: DebugAPI; export declare const fireEvent: FireEventAPI;