From 613123debe01b53060b5db66286f6d156b1430d0 Mon Sep 17 00:00:00 2001 From: Kacper Wiszczuk Date: Tue, 28 May 2019 20:41:16 +0200 Subject: [PATCH 1/2] Remove deprecated API --- .../__snapshots__/render.test.js.snap | 2 + .../__snapshots__/shallow.test.js.snap | 25 ------ src/__tests__/debug.test.js | 4 +- src/__tests__/render.test.js | 87 ++----------------- src/__tests__/shallow.test.js | 27 ------ src/__tests__/waitForElement.test.js | 10 +-- src/helpers/getByAPI.js | 81 +---------------- src/helpers/queryByAPI.js | 74 +--------------- src/index.js | 2 - typings/__tests__/index.test.tsx | 62 ++----------- typings/index.d.ts | 19 ---- 11 files changed, 29 insertions(+), 364 deletions(-) delete mode 100644 src/__tests__/__snapshots__/shallow.test.js.snap delete mode 100644 src/__tests__/shallow.test.js 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 28685ff29..5e87d29e1 100644 --- a/src/helpers/getByAPI.js +++ b/src/helpers/getByAPI.js @@ -1,18 +1,9 @@ // @flow import * as React from 'react'; -import prettyFormat from 'pretty-format'; -import { - ErrorWithStack, - createLibraryNotSupportedError, - logDeprecationWarning, -} from './errors'; +import { ErrorWithStack, createLibraryNotSupportedError } 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 @@ -57,27 +48,6 @@ const prepareErrorMessage = error => // Strip info about custom predicate error.message.replace(/ matching custom predicate[^]*/gm, ''); -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 { @@ -98,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 { @@ -116,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)); @@ -164,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 a5ef80622..1b56a7911 100644 --- a/src/helpers/queryByAPI.js +++ b/src/helpers/queryByAPI.js @@ -1,19 +1,12 @@ // @flow -import * as React from 'react'; import { getByTestId, - getByName, - getByType, getByText, getByPlaceholder, - getByProps, - getAllByName, - getAllByType, getAllByText, getAllByPlaceholder, - getAllByProps, } from './getByAPI'; -import { ErrorWithStack, logDeprecationWarning } from './errors'; +import { ErrorWithStack } from './errors'; const createQueryByError = (error: Error, callsite: Function) => { if (error.message.includes('No instances found')) { @@ -22,25 +15,6 @@ const createQueryByError = (error: Error, callsite: Function) => { throw new ErrorWithStack(error.message, callsite); }; -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); - } - }; - export const queryByText = (instance: ReactTestInstance) => function queryByTextFn(text: string | RegExp) { try { @@ -59,15 +33,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 { @@ -77,27 +42,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 ) => { @@ -118,26 +62,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 00da9207b..305c35481 100644 --- a/typings/__tests__/index.test.tsx +++ b/typings/__tests__/index.test.tsx @@ -3,7 +3,6 @@ import { ReactTestInstance } from 'react-test-renderer'; import { render, fireEvent, - shallow, flushMicrotasksQueue, debug, waitForElement, @@ -31,41 +30,17 @@ 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 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( '' ); @@ -74,27 +49,13 @@ const queryByPlaceholderString: ReactTestInstance | null = tree.queryByText( 'my placeholder' ); 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.getAllByName( - 'View' -); -const queryAllByNameConstructor: Array = tree.getAllByName( - View -); -const queryAllByType: Array = tree.getAllByType(View); -const queryAllByTypeWithRequiredProps: Array< - ReactTestInstance -> = tree.getAllByType(ElementWithRequiredProps); const queryAllByTextString: Array = tree.queryAllByText( 'View' ); const queryAllByTextRegExp: Array = tree.queryAllByText( /View/g ); -const queryAllByProps: Array = tree.getAllByProps({ - value: 2, -}); const debugFn = tree.debug(); const debugFnWithMessage = tree.debug('my message'); @@ -103,24 +64,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(); @@ -128,11 +84,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 8838dd271..553f59c60 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2,35 +2,19 @@ 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 | []; } export interface Thenable { @@ -84,9 +68,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; From ae3512426773fd5559310df2b93ca4a47e1e3cf0 Mon Sep 17 00:00:00 2001 From: Kacper Wiszczuk Date: Tue, 28 May 2019 21:27:07 +0200 Subject: [PATCH 2/2] Update docs --- docs/GettingStarted.md | 4 ++-- docs/Queries.md | 29 ----------------------------- 2 files changed, 2 insertions(+), 31 deletions(-) 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. - -