From cefd4352f5c70c7e1732d40c39c5a6c511ae9111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Fri, 24 Jul 2020 22:53:34 +0200 Subject: [PATCH 01/11] feat(breaking): rename `ByPlaceholder` to `ByPlaceholderText` (#455) --- examples/redux/components/AddTodo.test.js | 4 +- src/__tests__/findByApi.test.js | 16 ++++---- src/__tests__/fireEvent.test.js | 7 +++- src/__tests__/render.test.js | 32 ++++++++------- src/__tests__/within.test.js | 10 +++-- src/helpers/errors.js | 12 +++++- src/helpers/findByAPI.js | 27 +++++++++---- src/helpers/getByAPI.js | 32 +++++++++------ src/helpers/queryByAPI.js | 35 +++++++++++------ typings/__tests__/index.test.tsx | 47 ++++++++++++----------- typings/index.d.ts | 12 +++--- website/docs/API.md | 12 +++--- website/docs/MigrationV2.md | 2 +- website/docs/Queries.md | 8 ++-- website/docs/ReduxIntegration.md | 4 +- 15 files changed, 158 insertions(+), 102 deletions(-) diff --git a/examples/redux/components/AddTodo.test.js b/examples/redux/components/AddTodo.test.js index edbbcc163..faeca8508 100644 --- a/examples/redux/components/AddTodo.test.js +++ b/examples/redux/components/AddTodo.test.js @@ -14,9 +14,9 @@ describe('Application test', () => { ); - const { getByPlaceholder, getByText } = render(component); + const { getByPlaceholderText, getByText } = render(component); - const input = getByPlaceholder(/repository/i); + const input = getByPlaceholderText(/repository/i); expect(input).toBeTruthy(); const textToEnter = 'This is a random element'; diff --git a/src/__tests__/findByApi.test.js b/src/__tests__/findByApi.test.js index 191003010..f924cb1b3 100644 --- a/src/__tests__/findByApi.test.js +++ b/src/__tests__/findByApi.test.js @@ -11,8 +11,8 @@ test('findBy queries work asynchronously', async () => { findAllByTestId, findByText, findAllByText, - findByPlaceholder, - findAllByPlaceholder, + findByPlaceholderText, + findAllByPlaceholderText, findByDisplayValue, findAllByDisplayValue, } = render(); @@ -21,10 +21,10 @@ test('findBy queries work asynchronously', async () => { await expect(findByText('Some Text', options)).rejects.toBeTruthy(); await expect(findAllByText('Some Text', options)).rejects.toBeTruthy(); await expect( - findByPlaceholder('Placeholder Text', options) + findByPlaceholderText('Placeholder Text', options) ).rejects.toBeTruthy(); await expect( - findAllByPlaceholder('Placeholder Text', options) + findAllByPlaceholderText('Placeholder Text', options) ).rejects.toBeTruthy(); await expect( findByDisplayValue('Display Value', options) @@ -49,10 +49,10 @@ test('findBy queries work asynchronously', async () => { await expect(findAllByTestId('aTestId')).resolves.toHaveLength(1); await expect(findByText('Some Text')).resolves.toBeTruthy(); await expect(findAllByText('Some Text')).resolves.toHaveLength(1); - await expect(findByPlaceholder('Placeholder Text')).resolves.toBeTruthy(); - await expect(findAllByPlaceholder('Placeholder Text')).resolves.toHaveLength( - 1 - ); + await expect(findByPlaceholderText('Placeholder Text')).resolves.toBeTruthy(); + await expect( + findAllByPlaceholderText('Placeholder Text') + ).resolves.toHaveLength(1); await expect(findByDisplayValue('Display Value')).resolves.toBeTruthy(); await expect(findAllByDisplayValue('Display Value')).resolves.toHaveLength(1); }, 20000); diff --git a/src/__tests__/fireEvent.test.js b/src/__tests__/fireEvent.test.js index c1c69ebad..5a261dba7 100644 --- a/src/__tests__/fireEvent.test.js +++ b/src/__tests__/fireEvent.test.js @@ -123,7 +123,7 @@ test('fireEvent.changeText', () => { const onChangeTextMock = jest.fn(); const CHANGE_TEXT = 'content'; - const { getByPlaceholder } = render( + const { getByPlaceholderText } = render( { ); - fireEvent.changeText(getByPlaceholder('Customer placeholder'), CHANGE_TEXT); + fireEvent.changeText( + getByPlaceholderText('Customer placeholder'), + CHANGE_TEXT + ); expect(onChangeTextMock).toHaveBeenCalledWith(CHANGE_TEXT); }); diff --git a/src/__tests__/render.test.js b/src/__tests__/render.test.js index 617cd105b..d7d4a0b2e 100644 --- a/src/__tests__/render.test.js +++ b/src/__tests__/render.test.js @@ -176,35 +176,39 @@ test('getAllByText, queryAllByText', () => { expect(queryAllByText('InExistent')).toHaveLength(0); }); -test('getByPlaceholder, queryByPlaceholder', () => { - const { getByPlaceholder, queryByPlaceholder } = render(); - const input = getByPlaceholder(/custom/i); +test('getByPlaceholderText, queryByPlaceholderText', () => { + const { getByPlaceholderText, queryByPlaceholderText } = render(); + const input = getByPlaceholderText(/custom/i); expect(input.props.placeholder).toBe(PLACEHOLDER_FRESHNESS); - const sameInput = getByPlaceholder(PLACEHOLDER_FRESHNESS); + const sameInput = getByPlaceholderText(PLACEHOLDER_FRESHNESS); expect(sameInput.props.placeholder).toBe(PLACEHOLDER_FRESHNESS); - expect(() => getByPlaceholder('no placeholder')).toThrow( + expect(() => getByPlaceholderText('no placeholder')).toThrow( 'No instances found' ); - expect(queryByPlaceholder(/add/i)).toBe(input); - expect(queryByPlaceholder('no placeholder')).toBeNull(); - expect(() => queryByPlaceholder(/fresh/)).toThrow('Expected 1 but found 2'); + expect(queryByPlaceholderText(/add/i)).toBe(input); + expect(queryByPlaceholderText('no placeholder')).toBeNull(); + expect(() => queryByPlaceholderText(/fresh/)).toThrow( + 'Expected 1 but found 2' + ); }); -test('getAllByPlaceholder, queryAllByPlaceholder', () => { - const { getAllByPlaceholder, queryAllByPlaceholder } = render(); - const inputs = getAllByPlaceholder(/fresh/i); +test('getAllByPlaceholderText, queryAllByPlaceholderText', () => { + const { getAllByPlaceholderText, queryAllByPlaceholderText } = render( + + ); + const inputs = getAllByPlaceholderText(/fresh/i); expect(inputs).toHaveLength(2); - expect(() => getAllByPlaceholder('no placeholder')).toThrow( + expect(() => getAllByPlaceholderText('no placeholder')).toThrow( 'No instances found' ); - expect(queryAllByPlaceholder(/fresh/i)).toEqual(inputs); - expect(queryAllByPlaceholder('no placeholder')).toHaveLength(0); + expect(queryAllByPlaceholderText(/fresh/i)).toEqual(inputs); + expect(queryAllByPlaceholderText('no placeholder')).toHaveLength(0); }); test('getByDisplayValue, queryByDisplayValue', () => { diff --git a/src/__tests__/within.test.js b/src/__tests__/within.test.js index a4fb956c1..51403731e 100644 --- a/src/__tests__/within.test.js +++ b/src/__tests__/within.test.js @@ -19,7 +19,9 @@ test('within() exposes basic queries', async () => { expect(rootQueries.getAllByText('Same Text')).toHaveLength(2); expect(rootQueries.getAllByDisplayValue('Same Value')).toHaveLength(2); - expect(rootQueries.getAllByPlaceholder('Same Placeholder')).toHaveLength(2); + expect(rootQueries.getAllByPlaceholderText('Same Placeholder')).toHaveLength( + 2 + ); const firstQueries = within(rootQueries.getByA11yHint('first')); expect(firstQueries.getAllByText('Same Text')).toHaveLength(1); @@ -27,12 +29,12 @@ test('within() exposes basic queries', async () => { expect(firstQueries.queryAllByText('Same Text')).toHaveLength(1); expect(firstQueries.queryByText('Same Text')).toBeTruthy(); expect(firstQueries.getByDisplayValue('Same Value')).toBeTruthy(); - expect(firstQueries.getByPlaceholder('Same Placeholder')).toBeTruthy(); + expect(firstQueries.getByPlaceholderText('Same Placeholder')).toBeTruthy(); await expect( firstQueries.findByDisplayValue('Same Value') ).resolves.toBeTruthy(); await expect( - firstQueries.findAllByPlaceholder('Same Placeholder') + firstQueries.findAllByPlaceholderText('Same Placeholder') ).resolves.toHaveLength(1); const secondQueries = within(rootQueries.getByA11yHint('second')); @@ -41,7 +43,7 @@ test('within() exposes basic queries', async () => { expect(secondQueries.queryAllByText('Same Text')).toHaveLength(1); expect(secondQueries.queryByText('Same Text')).toBeTruthy(); expect(secondQueries.getByDisplayValue('Same Value')).toBeTruthy(); - expect(secondQueries.getByPlaceholder('Same Placeholder')).toBeTruthy(); + expect(secondQueries.getByPlaceholderText('Same Placeholder')).toBeTruthy(); }); test('within() exposes a11y queries', async () => { diff --git a/src/helpers/errors.js b/src/helpers/errors.js index ce089b873..df76871cf 100644 --- a/src/helpers/errors.js +++ b/src/helpers/errors.js @@ -44,6 +44,16 @@ export function throwRemovedFunctionError( 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}` + `"${functionName}" has been removed.\n\nPlease consult: https://callstack.github.io/react-native-testing-library/docs/${docsRef}` + ); +} + +export function throwRenamedFunctionError( + functionName: string, + newFunctionName: string +) { + throw new ErrorWithStack( + `The "${functionName}" function has been renamed to "${newFunctionName}". Please replace all occurrences.`, + throwRenamedFunctionError ); } diff --git a/src/helpers/findByAPI.js b/src/helpers/findByAPI.js index 058f51fda..6234a1182 100644 --- a/src/helpers/findByAPI.js +++ b/src/helpers/findByAPI.js @@ -6,11 +6,12 @@ import { getAllByTestId, getByText, getAllByText, - getByPlaceholder, - getAllByPlaceholder, + getByPlaceholderText, + getAllByPlaceholderText, getByDisplayValue, getAllByDisplayValue, } from './getByAPI'; +import { throwRenamedFunctionError } from './errors'; const makeFindQuery = ( instance: ReactTestInstance, @@ -39,15 +40,16 @@ export const findAllByText = (instance: ReactTestInstance) => ( waitForOptions: WaitForOptions = {} ) => makeFindQuery(instance, getAllByText, text, waitForOptions); -export const findByPlaceholder = (instance: ReactTestInstance) => ( +export const findByPlaceholderText = (instance: ReactTestInstance) => ( placeholder: string | RegExp, waitForOptions: WaitForOptions = {} -) => makeFindQuery(instance, getByPlaceholder, placeholder, waitForOptions); +) => makeFindQuery(instance, getByPlaceholderText, placeholder, waitForOptions); -export const findAllByPlaceholder = (instance: ReactTestInstance) => ( +export const findAllByPlaceholderText = (instance: ReactTestInstance) => ( placeholder: string | RegExp, waitForOptions: WaitForOptions = {} -) => makeFindQuery(instance, getAllByPlaceholder, placeholder, waitForOptions); +) => + makeFindQuery(instance, getAllByPlaceholderText, placeholder, waitForOptions); export const findByDisplayValue = (instance: ReactTestInstance) => ( value: string | RegExp, @@ -62,10 +64,19 @@ export const findAllByDisplayValue = (instance: ReactTestInstance) => ( export const findByAPI = (instance: ReactTestInstance) => ({ findByTestId: findByTestId(instance), findByText: findByText(instance), - findByPlaceholder: findByPlaceholder(instance), + findByPlaceholderText: findByPlaceholderText(instance), findByDisplayValue: findByDisplayValue(instance), findAllByTestId: findAllByTestId(instance), findAllByText: findAllByText(instance), - findAllByPlaceholder: findAllByPlaceholder(instance), + findAllByPlaceholderText: findAllByPlaceholderText(instance), findAllByDisplayValue: findAllByDisplayValue(instance), + + // Renamed + findByPlaceholder: () => + throwRenamedFunctionError('findByPlaceholder', 'findByPlaceholderText'), + findAllByPlaceholder: () => + throwRenamedFunctionError( + 'findAllByPlaceholder', + 'findAllByPlaceholderText' + ), }); diff --git a/src/helpers/getByAPI.js b/src/helpers/getByAPI.js index ea2342655..723cc20e5 100644 --- a/src/helpers/getByAPI.js +++ b/src/helpers/getByAPI.js @@ -6,6 +6,7 @@ import { createLibraryNotSupportedError, prepareErrorMessage, throwRemovedFunctionError, + throwRenamedFunctionError, } from './errors'; const filterNodeByType = (node, type) => node.type === type; @@ -50,7 +51,7 @@ const getChildrenAsText = (children, TextComponent, textContent = []) => { return textContent; }; -const getTextInputNodeByPlaceholder = (node, placeholder) => { +const getTextInputNodeByPlaceholderText = (node, placeholder) => { try { // eslint-disable-next-line const { TextInput } = require('react-native'); @@ -89,14 +90,17 @@ export const getByText = (instance: ReactTestInstance) => } }; -export const getByPlaceholder = (instance: ReactTestInstance) => - function getByPlaceholderFn(placeholder: string | RegExp) { +export const getByPlaceholderText = (instance: ReactTestInstance) => + function getByPlaceholderTextFn(placeholder: string | RegExp) { try { return instance.find((node) => - getTextInputNodeByPlaceholder(node, placeholder) + getTextInputNodeByPlaceholderText(node, placeholder) ); } catch (error) { - throw new ErrorWithStack(prepareErrorMessage(error), getByPlaceholderFn); + throw new ErrorWithStack( + prepareErrorMessage(error), + getByPlaceholderTextFn + ); } }; @@ -142,15 +146,15 @@ export const getAllByText = (instance: ReactTestInstance) => return results; }; -export const getAllByPlaceholder = (instance: ReactTestInstance) => - function getAllByPlaceholderFn(placeholder: string | RegExp) { +export const getAllByPlaceholderText = (instance: ReactTestInstance) => + function getAllByPlaceholderTextFn(placeholder: string | RegExp) { const results = instance.findAll((node) => - getTextInputNodeByPlaceholder(node, placeholder) + getTextInputNodeByPlaceholderText(node, placeholder) ); if (results.length === 0) { throw new ErrorWithStack( `No instances found with placeholder: ${String(placeholder)}`, - getAllByPlaceholderFn + getAllByPlaceholderTextFn ); } return results; @@ -226,11 +230,11 @@ export const UNSAFE_getAllByProps = (instance: ReactTestInstance) => export const getByAPI = (instance: ReactTestInstance) => ({ getByText: getByText(instance), - getByPlaceholder: getByPlaceholder(instance), + getByPlaceholderText: getByPlaceholderText(instance), getByDisplayValue: getByDisplayValue(instance), getByTestId: getByTestId(instance), getAllByText: getAllByText(instance), - getAllByPlaceholder: getAllByPlaceholder(instance), + getAllByPlaceholderText: getAllByPlaceholderText(instance), getAllByDisplayValue: getAllByDisplayValue(instance), getAllByTestId: getAllByTestId(instance), @@ -256,4 +260,10 @@ export const getByAPI = (instance: ReactTestInstance) => ({ 'getAllByProps', 'migration-v2#removed-functions' ), + + // Renamed + getByPlaceholder: () => + throwRenamedFunctionError('getByPlaceholder', 'getByPlaceholderText'), + getAllByPlaceholder: () => + throwRenamedFunctionError('getAllByPlaceholder', 'getByPlaceholderText'), }); diff --git a/src/helpers/queryByAPI.js b/src/helpers/queryByAPI.js index 5566e3e4d..fe1076e28 100644 --- a/src/helpers/queryByAPI.js +++ b/src/helpers/queryByAPI.js @@ -3,18 +3,22 @@ import * as React from 'react'; import { getByTestId, getByText, - getByPlaceholder, + getByPlaceholderText, getByDisplayValue, getAllByTestId, getAllByText, - getAllByPlaceholder, + getAllByPlaceholderText, getAllByDisplayValue, UNSAFE_getByType, UNSAFE_getByProps, UNSAFE_getAllByType, UNSAFE_getAllByProps, } from './getByAPI'; -import { createQueryByError, throwRemovedFunctionError } from './errors'; +import { + createQueryByError, + throwRemovedFunctionError, + throwRenamedFunctionError, +} from './errors'; export const queryByText = (instance: ReactTestInstance) => function queryByTextFn(text: string | RegExp) { @@ -25,12 +29,12 @@ export const queryByText = (instance: ReactTestInstance) => } }; -export const queryByPlaceholder = (instance: ReactTestInstance) => - function queryByPlaceholderFn(placeholder: string | RegExp) { +export const queryByPlaceholderText = (instance: ReactTestInstance) => + function queryByPlaceholderTextFn(placeholder: string | RegExp) { try { - return getByPlaceholder(instance)(placeholder); + return getByPlaceholderText(instance)(placeholder); } catch (error) { - return createQueryByError(error, queryByPlaceholderFn); + return createQueryByError(error, queryByPlaceholderTextFn); } }; @@ -62,11 +66,11 @@ export const queryAllByText = (instance: ReactTestInstance) => ( } }; -export const queryAllByPlaceholder = (instance: ReactTestInstance) => ( +export const queryAllByPlaceholderText = (instance: ReactTestInstance) => ( placeholder: string | RegExp ) => { try { - return getAllByPlaceholder(instance)(placeholder); + return getAllByPlaceholderText(instance)(placeholder); } catch (error) { return []; } @@ -133,11 +137,11 @@ export const UNSAFE_queryAllByProps = (instance: ReactTestInstance) => (props: { export const queryByAPI = (instance: ReactTestInstance) => ({ queryByTestId: queryByTestId(instance), queryByText: queryByText(instance), - queryByPlaceholder: queryByPlaceholder(instance), + queryByPlaceholderText: queryByPlaceholderText(instance), queryByDisplayValue: queryByDisplayValue(instance), queryAllByTestId: queryAllByTestId(instance), queryAllByText: queryAllByText(instance), - queryAllByPlaceholder: queryAllByPlaceholder(instance), + queryAllByPlaceholderText: queryAllByPlaceholderText(instance), queryAllByDisplayValue: queryAllByDisplayValue(instance), // Unsafe @@ -168,4 +172,13 @@ export const queryByAPI = (instance: ReactTestInstance) => ({ 'queryAllByProps', 'migration-v2#removed-functions' ), + + // Renamed + queryByPlaceholder: () => + throwRenamedFunctionError('queryByPlaceholder', 'queryByPlaceholderText'), + queryAllByPlaceholder: () => + throwRenamedFunctionError( + 'queryAllByPlaceholder', + 'queryAllByPlaceholderText' + ), }); diff --git a/typings/__tests__/index.test.tsx b/typings/__tests__/index.test.tsx index fb45261f7..64a038e51 100644 --- a/typings/__tests__/index.test.tsx +++ b/typings/__tests__/index.test.tsx @@ -35,8 +35,8 @@ const tree = render(); const getBy: ReactTestInstance[] = [ tree.getByText(''), tree.getByText(/View/g), - tree.getByPlaceholder('my placeholder'), - tree.getByPlaceholder(/placeholder/g), + tree.getByPlaceholderText('my placeholder'), + tree.getByPlaceholderText(/placeholder/g), tree.getByDisplayValue('my value'), tree.getByDisplayValue(/value/g), tree.getByTestId('test-id'), @@ -58,8 +58,8 @@ const getBy: ReactTestInstance[] = [ const getAllBy: ReactTestInstance[][] = [ tree.getAllByText(''), tree.getAllByText(/Text/g), - tree.getAllByPlaceholder('my placeholder'), - tree.getAllByPlaceholder(/placeholder/g), + tree.getAllByPlaceholderText('my placeholder'), + tree.getAllByPlaceholderText(/placeholder/g), tree.getAllByDisplayValue('my value'), tree.getAllByDisplayValue(/value/g), tree.getAllByTestId('test-id'), @@ -82,8 +82,8 @@ const getAllBy: ReactTestInstance[][] = [ const queryBy: Array = [ tree.queryByText('View'), tree.queryByText(/View/g), - tree.queryByPlaceholder('my placeholder'), - tree.queryByPlaceholder(/placeholder/g), + tree.queryByPlaceholderText('my placeholder'), + tree.queryByPlaceholderText(/placeholder/g), tree.queryByDisplayValue('my value'), tree.queryByDisplayValue(/value/g), tree.queryByTestId('test-id'), @@ -105,8 +105,8 @@ const queryBy: Array = [ const queryAllBy: ReactTestInstance[][] = [ tree.queryAllByText('View'), tree.queryAllByText(/View/g), - tree.queryAllByPlaceholder('my placeholder'), - tree.queryAllByPlaceholder(/placeholder/g), + tree.queryAllByPlaceholderText('my placeholder'), + tree.queryAllByPlaceholderText(/placeholder/g), tree.queryAllByDisplayValue('my value'), tree.queryAllByDisplayValue(/value/g), tree.queryAllByTestId('test-id'), @@ -131,10 +131,10 @@ const findBy: Promise[] = [ tree.findByText('View', { timeout: 10, interval: 10 }), tree.findByText(/View/g), tree.findByText(/View/g, { timeout: 10, interval: 5 }), - tree.findByPlaceholder('my placeholder'), - tree.findByPlaceholder('my placeholder', { timeout: 10, interval: 5 }), - tree.findByPlaceholder(/placeholder/g), - tree.findByPlaceholder(/placeholder/g, { timeout: 10, interval: 5 }), + tree.findByPlaceholderText('my placeholder'), + tree.findByPlaceholderText('my placeholder', { timeout: 10, interval: 5 }), + tree.findByPlaceholderText(/placeholder/g), + tree.findByPlaceholderText(/placeholder/g, { timeout: 10, interval: 5 }), tree.findByDisplayValue('my value'), tree.findByDisplayValue('my value', { timeout: 10, interval: 10 }), tree.findByDisplayValue(/value/g), @@ -164,10 +164,13 @@ const findAllBy: Promise[] = [ tree.findAllByText('View', { timeout: 10, interval: 10 }), tree.findAllByText(/View/g), tree.findAllByText(/View/g, { timeout: 10, interval: 5 }), - tree.findAllByPlaceholder('my placeholder'), - tree.findAllByPlaceholder('my placeholder', { timeout: 10, interval: 10 }), - tree.findAllByPlaceholder(/placeholder/g), - tree.findAllByPlaceholder(/placeholder/g, { timeout: 10, interval: 10 }), + tree.findAllByPlaceholderText('my placeholder'), + tree.findAllByPlaceholderText('my placeholder', { + timeout: 10, + interval: 10, + }), + tree.findAllByPlaceholderText(/placeholder/g), + tree.findAllByPlaceholderText(/placeholder/g, { timeout: 10, interval: 10 }), tree.findAllByDisplayValue('View'), tree.findAllByDisplayValue('View', { timeout: 10, interval: 10 }), tree.findAllByDisplayValue(/View/g), @@ -293,7 +296,7 @@ const instance: ReactTestInstance = tree.getByText(''); const withinGet: Array = [ within(instance).getByText('Test'), within(instance).getByDisplayValue('Test'), - within(instance).getByPlaceholder('Test'), + within(instance).getByPlaceholderText('Test'), within(instance).getByTestId('Test'), within(instance).getByA11yLabel('Test'), within(instance).getByLabelText('Test'), @@ -308,7 +311,7 @@ const withinGet: Array = [ const withinGetAll: Array = [ within(instance).getAllByText('Test'), within(instance).getAllByDisplayValue('Test'), - within(instance).getAllByPlaceholder('Test'), + within(instance).getAllByPlaceholderText('Test'), within(instance).getAllByTestId('Test'), within(instance).getAllByA11yLabel('Test'), within(instance).getAllByLabelText('button'), @@ -323,7 +326,7 @@ const withinGetAll: Array = [ const withinQuery: Array = [ within(instance).queryByText('Test'), within(instance).queryByDisplayValue('Test'), - within(instance).queryByPlaceholder('Test'), + within(instance).queryByPlaceholderText('Test'), within(instance).queryByTestId('Test'), within(instance).queryByA11yLabel('Test'), within(instance).queryByLabelText('button'), @@ -338,7 +341,7 @@ const withinQuery: Array = [ const withinQueryAll: Array = [ within(instance).queryAllByText('Test'), within(instance).queryAllByDisplayValue('Test'), - within(instance).queryAllByPlaceholder('Test'), + within(instance).queryAllByPlaceholderText('Test'), within(instance).queryAllByTestId('Test'), within(instance).queryAllByA11yLabel('Test'), within(instance).queryAllByLabelText('Test'), @@ -353,7 +356,7 @@ const withinQueryAll: Array = [ const withinFind: Promise[] = [ within(instance).findByText('Test'), within(instance).findByDisplayValue('Test'), - within(instance).findByPlaceholder('Test'), + within(instance).findByPlaceholderText('Test'), within(instance).findByTestId('Test'), within(instance).findByA11yLabel('Test'), within(instance).findByLabelText('Test'), @@ -368,7 +371,7 @@ const withinFind: Promise[] = [ const withinFindAll: Promise[] = [ within(instance).findAllByText('Test'), within(instance).findAllByDisplayValue('Test'), - within(instance).findAllByPlaceholder('Test'), + within(instance).findAllByPlaceholderText('Test'), within(instance).findAllByTestId('Test'), within(instance).findAllByA11yLabel('Test'), within(instance).findAllByLabelText('Test'), diff --git a/typings/index.d.ts b/typings/index.d.ts index da01039a7..640055fd9 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -16,12 +16,12 @@ type FindAllReturn = Promise; interface GetByAPI { getByText: (text: string | RegExp) => ReactTestInstance; - getByPlaceholder: (placeholder: string | RegExp) => ReactTestInstance; + getByPlaceholderText: (placeholder: string | RegExp) => ReactTestInstance; getByDisplayValue: (value: string | RegExp) => ReactTestInstance; getByTestId: (testID: string) => ReactTestInstance; getAllByTestId: (testID: string) => Array; getAllByText: (text: string | RegExp) => Array; - getAllByPlaceholder: ( + getAllByPlaceholderText: ( placeholder: string | RegExp ) => Array; getAllByDisplayValue: (value: string | RegExp) => Array; @@ -65,14 +65,14 @@ interface GetByAPI { interface QueryByAPI { queryByText: (name: string | RegExp) => ReactTestInstance | null; - queryByPlaceholder: ( + queryByPlaceholderText: ( placeholder: string | RegExp ) => ReactTestInstance | null; queryByDisplayValue: (value: string | RegExp) => ReactTestInstance | null; queryByTestId: (testID: string) => ReactTestInstance | null; queryAllByTestId: (testID: string) => Array | null; queryAllByText: (text: string | RegExp) => Array | []; - queryAllByPlaceholder: ( + queryAllByPlaceholderText: ( placeholder: string | RegExp ) => Array | []; queryAllByDisplayValue: ( @@ -129,7 +129,7 @@ interface FindByAPI { text: string | RegExp, waitForOptions?: WaitForOptions ) => FindReturn; - findByPlaceholder: ( + findByPlaceholderText: ( placeholder: string | RegExp, waitForOptions?: WaitForOptions ) => FindReturn; @@ -142,7 +142,7 @@ interface FindByAPI { text: string | RegExp, waitForOptions?: WaitForOptions ) => FindAllReturn; - findAllByPlaceholder: ( + findAllByPlaceholderText: ( placeholder: string | RegExp, waitForOptions?: WaitForOptions ) => FindAllReturn; diff --git a/website/docs/API.md b/website/docs/API.md index d9b52069a..728cbfd63 100644 --- a/website/docs/API.md +++ b/website/docs/API.md @@ -177,13 +177,13 @@ import { render, fireEvent } from 'react-native-testing-library'; test('fire changeText event', () => { const onEventMock = jest.fn(); - const { getByPlaceholder } = render( + const { getByPlaceholderText } = render( // MyComponent renders TextInput which has a placeholder 'Enter details' // and with `onChangeText` bound to handleChangeText ); - fireEvent(getByPlaceholder('change'), 'onChangeText', 'ab'); + fireEvent(getByPlaceholderText('change'), 'onChangeText', 'ab'); expect(onEventMock).toHaveBeenCalledWith('ab'); }); ``` @@ -196,14 +196,14 @@ import { fireEvent, render } from 'react-native-testing-library'; const onBlurMock = jest.fn(); -const { getByPlaceholder } = render( +const { getByPlaceholderText } = render( ); // you can omit the `on` prefix -fireEvent(getByPlaceholder('my placeholder'), 'blur'); +fireEvent(getByPlaceholderText('my placeholder'), 'blur'); ``` ## `fireEvent[eventName]` @@ -247,13 +247,13 @@ import { render, fireEvent } from 'react-native-testing-library'; const onChangeTextMock = jest.fn(); const CHANGE_TEXT = 'content'; -const { getByPlaceholder } = render( +const { getByPlaceholderText } = render( ); -fireEvent.changeText(getByPlaceholder('Enter data'), CHANGE_TEXT); +fireEvent.changeText(getByPlaceholderText('Enter data'), CHANGE_TEXT); ``` ### `fireEvent.scroll: (element: ReactTestInstance, ...data: Array) => void` diff --git a/website/docs/MigrationV2.md b/website/docs/MigrationV2.md index 84acf2a0a..067072399 100644 --- a/website/docs/MigrationV2.md +++ b/website/docs/MigrationV2.md @@ -114,7 +114,7 @@ In v2 we fixed this inconsistency, which may result in failing tests, if you rel - 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`). +In general, you should avoid `*byTestId` queries when possible. Use queries that check things that the user can interact with. Like `*ByText` or `*ByPlaceholderText` or accessibility queries (e.g. `*ByA11yHint`, `*ByA11yLabel`). ::: ## Deprecated `flushMicrotasksQueue` diff --git a/website/docs/Queries.md b/website/docs/Queries.md index 756c97cb8..b59b4d3ec 100644 --- a/website/docs/Queries.md +++ b/website/docs/Queries.md @@ -68,17 +68,17 @@ const { getByText } = render(); const element = getByText('banana'); ``` -### `ByPlaceholder` +### `ByPlaceholderText` -> getByPlaceholder, getAllByPlaceholder, queryByPlaceholder, queryAllByPlaceholder, findByPlaceholder, findAllByPlaceholder +> getByPlaceholderText, getAllByPlaceholderText, queryByPlaceholderText, queryAllByPlaceholderText, findByPlaceholderText, findAllByPlaceholderText Returns a `ReactTestInstance` for a `TextInput` with a matching placeholder – may be a string or regular expression. ```jsx import { render } from 'react-native-testing-library'; -const { getByPlaceholder } = render(); -const element = getByPlaceholder('username'); +const { getByPlaceholderText } = render(); +const element = getByPlaceholderText('username'); ``` ### `ByDisplayValue` diff --git a/website/docs/ReduxIntegration.md b/website/docs/ReduxIntegration.md index 20d6975df..349922426 100644 --- a/website/docs/ReduxIntegration.md +++ b/website/docs/ReduxIntegration.md @@ -32,11 +32,11 @@ describe('AddTodo component test', () => { ); - const { getByPlaceholder, getByText } = render(component); + const { getByPlaceholderText, getByText } = render(component); // There is a TextInput. // https://github.com/callstack/react-native-testing-library/blob/ae3d4af370487e1e8fedd8219f77225690aefc59/examples/redux/components/AddTodo.js#L24 - const input = getByPlaceholder(/repository/i); + const input = getByPlaceholderText(/repository/i); expect(input).toBeTruthy(); const textToEnter = 'This is a random element'; From c16995abda003a2a61e22b94fcaa074427ff49a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 27 Jul 2020 22:50:26 +0200 Subject: [PATCH 02/11] docs: add migration to v7 guide (#456) * docs: add migration to v7 guide * adjust note about ByTitle because there's no host Button component * add fire event section * mention NativeTestInstance and container * Update website/docs/MigrationV7.md Co-authored-by: Maciej Jastrzebski * Update website/docs/MigrationV7.md Co-authored-by: Maciej Jastrzebski * Update website/docs/MigrationV7.md Co-authored-by: Maciej Jastrzebski * Update website/docs/MigrationV7.md Co-authored-by: Maciej Jastrzebski Co-authored-by: Maciej Jastrzebski --- website/docs/MigrationV7.md | 118 ++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 website/docs/MigrationV7.md diff --git a/website/docs/MigrationV7.md b/website/docs/MigrationV7.md new file mode 100644 index 000000000..2cadebc82 --- /dev/null +++ b/website/docs/MigrationV7.md @@ -0,0 +1,118 @@ +--- +id: migration-v7 +title: Migration to 7.0 +--- + +:::caution +We renamed the `react-native-testing-library` npm package to `@testing-library/react-native`, joining the Testing Library family. +::: + +As the version 7.0 involves merging two libraries together, there are two variants for migration guide, dependent on library you used previously: + +- [guide for `react-native-testing-library` users](#guide-for-react-native-testing-library-users) +- [guide for `@testing-library/react-native` users](#guide-for-testing-libraryreact-native-users) + +# Guide for `react-native-testing-library` users + +This guide describes steps necessary to migrate from React Native Testing Library `v2.x` to `v7.0`. + +## Renaming the library + +1. Install `@testing-library/react-native`. +1. Uninstall `react-native-testing-library`. +1. Rename all references of `react-native-testing-library` to `@testing-library/react-native`. + +You may have noticed a strange v2 to v7 upgrade, skipping versions 3, 4, 5 and 6. This is because we renamed the `react-native-testing-library` npm package to `@testing-library/react-native`, officially joining the "Testing Library" family 🎉. We're merging existing two libraries into a single one. The [native-testing-library](https://github.com/testing-library/native-testing-library) repository, which had v6, will soon be archived and using `@testing-library/react-native` below v7, sourced from mentioned repository, is deprecated. + +For branding purposes we keep the "React Native Testing Library" name, similar to "React Testing Library". Only the npm published package is changing. The code repository also stays the same under Callstack governance. + +## New aliases + +To improve compatibility with React Testing Library, and ease the migration for `@testing-library/react-native` users using version below v7, we've introduced new aliases to our accessibility queries: + +- `ByLabelText` aliasing `ByA11yLabel` queries +- `ByHintText` aliasing `ByA11yHint` queries +- `ByRole` aliasing `ByA11yRole` queries + +We like the new names and consider removing the aliases in future releases. + +## Renaming `ByPlaceholder` queries + +To improve compatibility with React Testing Library, and to ease the migration for `@testing-library/react-native` users using version below v7, we've renamed following queries: + +- `ByPlaceholder` -> `ByPlaceholderText` + +Please replace all occurrences of these queries in your codebase. + +# Guide for `@testing-library/react-native` users + +This guide describes steps necessary to migrate from `@testing-library/react-native` from `v6.0` to `v7.0`. Although the name stays the same, this is a different library, sourced at [Callstack GitHub repository](https://github.com/callstack/react-native-testing-library). We made sure the upgrade path is as easy for you as possible. + +## Changed helpers + +- `getQueriesForElement` is removed, rename it to `within` +- `wait` and `waitForElement` is removed, rename these to `waitFor` + +## Missing queries + +Our library doesn't implement `ByTitle` queries, which are targetting components with `title` prop, specifically `Button` and `RefreshControl`. If your tests only use `ByTitle` to target `Button` components, you can replace them with `ByText` queries, since React Native renders normal `Text` component under the hood. + +If you need to query `RefreshControl` component and can't figure out other way around it, you can use e.g. `UNSAFE_getByProps({title})` query. + +## No custom Jest configuration + +Use the official React Native preset for Jest: + +```diff +{ + "jest": { +- "preset": "@testing-library/react-native" ++ "preset": "react-native" + } +} +``` + +We're told this should also speed up your tests startup on cold cache. Using official preset has another benefit. The library is compatible with any version of React Native without introducing breaking changes. + +## Cleanup is included by default + +Cleaning up (unmounting) components after each test is included by default in the same manner as in React Testing Library. Please remove this setup file from Jest config: + +```diff +{ + "jest": { +- "setupFilesAfterEnv": ["@testing-library/react-native/cleanup-after-each"] + } +} +``` + +You can opt-out of this behavior by running tests with `RNTL_SKIP_AUTO_CLEANUP=true` flag or importing from `@testing-library/react-native/pure`. We encourage you to keep the default though. + +## No special handling for `disabled` prop + +The `disabled` prop on "Touchable\*" components is treated in the same manner as any other prop. We realize that with our library you can press "touchable" components even though they're in "disabled" state, however this is something that we strongly believe should be fixed upstream, in React Native core. + +If you feel strongly about this difference, please send a PR to React Native, adding JavaScript logic to "onPress" functions, making them aware of disabled state in JS logic as well (it's handled on native side for at least iOS, which is the default platform that tests are running in). + +As a mitigation, you'll likely need to modify the logic of "touchable" components to bail if they're pressed in disabled state. + +## No [NativeTestInstance](https://www.native-testing-library.com/docs/api-test-instance) abstraction + +We don't provide any abstraction over `ReactTestInstance` returned by queries, but allow to use it directly to access queried component's `props` or `type` for that example. + +## No `container` returned from `render` + +There's no such key returned from the `render` function. If you must, use `react-test-renderer` directly, although we advise not doing so. + +## Firing events changes + +There are slight differences in how `fireEvent` works in both libraries: + +1. Our library doesn't perform validation checks for events fired upon tested components. +1. Signature is different: + ```diff + -fireEvent[eventName](node: FiberRoot, eventProperties: NativeTestEvent) + +fireEvent(element: ReactTestInstance, eventName: string, ...data: Array) + ``` +1. There is no `NativeTestEvent` - second and rest arguments are used instead. +1. There are only 3 short-hand events: [`fireEvent.press`](`/docs/api/#fireeventpress-element-reacttestinstance--void`), [`fireEvent.changeText`](https://callstack.github.io/react-native-testing-library/docs/api/#fireeventchangetext-element-reacttestinstance-data-arrayany--void), [`fireEvent.scroll`](https://callstack.github.io/react-native-testing-library/docs/api/#fireeventchangetext-element-reacttestinstance-data-arrayany--void). For all other or custom events you can use the base signature. From 455111bba4e9b190c3340da8090456497e35b319 Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Tue, 28 Jul 2020 11:12:32 +0200 Subject: [PATCH 03/11] feat: add `getQueriesForElement` alias to `within` (#461) * feat: getQueriesForElement alias implementation & test * feat: added typescript types and tests * feat: updated docs --- src/__tests__/within.test.js | 6 ++- src/pure.js | 4 +- src/within.js | 4 +- typings/__tests__/index.test.tsx | 73 ++++++++++++++++++++++++++++++++ typings/index.d.ts | 3 ++ website/docs/API.md | 10 +++-- website/docs/MigrationV7.md | 1 - 7 files changed, 93 insertions(+), 8 deletions(-) diff --git a/src/__tests__/within.test.js b/src/__tests__/within.test.js index 51403731e..29e4f3d57 100644 --- a/src/__tests__/within.test.js +++ b/src/__tests__/within.test.js @@ -1,7 +1,7 @@ // @flow import React from 'react'; import { View, Text, TextInput } from 'react-native'; -import { render, within } from '..'; +import { render, within, getQueriesForElement } from '..'; test('within() exposes basic queries', async () => { const rootQueries = render( @@ -91,3 +91,7 @@ test('within() exposes a11y queries', async () => { secondQueries.findAllByA11yHint('Same Hint') ).resolves.toHaveLength(1); }); + +test('getQueriesForElement is alias to within', () => { + expect(getQueriesForElement).toBe(within); +}); diff --git a/src/pure.js b/src/pure.js index 0c1a21aae..b36edc6aa 100644 --- a/src/pure.js +++ b/src/pure.js @@ -7,7 +7,7 @@ import render from './render'; import shallow from './shallow'; import waitFor, { waitForElement } from './waitFor'; import waitForElementToBeRemoved from './waitForElementToBeRemoved'; -import within from './within'; +import { within, getQueriesForElement } from './within'; export { act }; export { cleanup }; @@ -17,4 +17,4 @@ export { render }; export { shallow }; export { waitFor, waitForElement }; export { waitForElementToBeRemoved }; -export { within }; +export { within, getQueriesForElement }; diff --git a/src/within.js b/src/within.js index 3b12c3e06..9d041bb26 100644 --- a/src/within.js +++ b/src/within.js @@ -4,7 +4,7 @@ import { queryByAPI } from './helpers/queryByAPI'; import { findByAPI } from './helpers/findByAPI'; import a11yAPI from './helpers/a11yAPI'; -export default function within(instance: ReactTestInstance) { +export function within(instance: ReactTestInstance) { return { ...getByAPI(instance), ...queryByAPI(instance), @@ -12,3 +12,5 @@ export default function within(instance: ReactTestInstance) { ...a11yAPI(instance), }; } + +export const getQueriesForElement = within; diff --git a/typings/__tests__/index.test.tsx b/typings/__tests__/index.test.tsx index 64a038e51..45d118a01 100644 --- a/typings/__tests__/index.test.tsx +++ b/typings/__tests__/index.test.tsx @@ -9,6 +9,7 @@ import { waitForElementToBeRemoved, act, within, + getQueriesForElement, } from '../..'; interface HasRequiredProp { @@ -306,6 +307,18 @@ const withinGet: Array = [ within(instance).getByRole('button'), within(instance).getByA11yState({ busy: true }), within(instance).getByA11yValue({ min: 10 }), + getQueriesForElement(instance).getByText('Test'), + getQueriesForElement(instance).getByDisplayValue('Test'), + getQueriesForElement(instance).getByPlaceholderText('Test'), + getQueriesForElement(instance).getByTestId('Test'), + getQueriesForElement(instance).getByA11yLabel('Test'), + getQueriesForElement(instance).getByLabelText('Test'), + getQueriesForElement(instance).getByA11yHint('Test'), + getQueriesForElement(instance).getByHintText('Test'), + getQueriesForElement(instance).getByA11yRole('button'), + getQueriesForElement(instance).getByRole('button'), + getQueriesForElement(instance).getByA11yState({ busy: true }), + getQueriesForElement(instance).getByA11yValue({ min: 10 }), ]; const withinGetAll: Array = [ @@ -321,6 +334,18 @@ const withinGetAll: Array = [ within(instance).getAllByRole('button'), within(instance).getAllByA11yState({ busy: true }), within(instance).getAllByA11yValue({ min: 10 }), + getQueriesForElement(instance).getAllByText('Test'), + getQueriesForElement(instance).getAllByDisplayValue('Test'), + getQueriesForElement(instance).getAllByPlaceholderText('Test'), + getQueriesForElement(instance).getAllByTestId('Test'), + getQueriesForElement(instance).getAllByA11yLabel('Test'), + getQueriesForElement(instance).getAllByLabelText('button'), + getQueriesForElement(instance).getAllByA11yHint('Test'), + getQueriesForElement(instance).getAllByHintText('button'), + getQueriesForElement(instance).getAllByA11yRole('button'), + getQueriesForElement(instance).getAllByRole('button'), + getQueriesForElement(instance).getAllByA11yState({ busy: true }), + getQueriesForElement(instance).getAllByA11yValue({ min: 10 }), ]; const withinQuery: Array = [ @@ -336,6 +361,18 @@ const withinQuery: Array = [ within(instance).queryByRole('button'), within(instance).queryByA11yState({ busy: true }), within(instance).queryByA11yValue({ min: 10 }), + getQueriesForElement(instance).queryByText('Test'), + getQueriesForElement(instance).queryByDisplayValue('Test'), + getQueriesForElement(instance).queryByPlaceholderText('Test'), + getQueriesForElement(instance).queryByTestId('Test'), + getQueriesForElement(instance).queryByA11yLabel('Test'), + getQueriesForElement(instance).queryByLabelText('button'), + getQueriesForElement(instance).queryByA11yHint('Test'), + getQueriesForElement(instance).queryByHintText('button'), + getQueriesForElement(instance).queryByA11yRole('button'), + getQueriesForElement(instance).queryByRole('button'), + getQueriesForElement(instance).queryByA11yState({ busy: true }), + getQueriesForElement(instance).queryByA11yValue({ min: 10 }), ]; const withinQueryAll: Array = [ @@ -351,6 +388,18 @@ const withinQueryAll: Array = [ within(instance).queryAllByRole('button'), within(instance).queryAllByA11yState({ busy: true }), within(instance).queryAllByA11yValue({ min: 10 }), + getQueriesForElement(instance).queryAllByText('Test'), + getQueriesForElement(instance).queryAllByDisplayValue('Test'), + getQueriesForElement(instance).queryAllByPlaceholderText('Test'), + getQueriesForElement(instance).queryAllByTestId('Test'), + getQueriesForElement(instance).queryAllByA11yLabel('Test'), + getQueriesForElement(instance).queryAllByLabelText('Test'), + getQueriesForElement(instance).queryAllByA11yHint('Test'), + getQueriesForElement(instance).queryAllByHintText('Test'), + getQueriesForElement(instance).queryAllByA11yRole('button'), + getQueriesForElement(instance).queryAllByRole('button'), + getQueriesForElement(instance).queryAllByA11yState({ busy: true }), + getQueriesForElement(instance).queryAllByA11yValue({ min: 10 }), ]; const withinFind: Promise[] = [ @@ -366,6 +415,18 @@ const withinFind: Promise[] = [ within(instance).findByRole('button'), within(instance).findByA11yState({ busy: true }), within(instance).findByA11yValue({ min: 10 }), + getQueriesForElement(instance).findByText('Test'), + getQueriesForElement(instance).findByDisplayValue('Test'), + getQueriesForElement(instance).findByPlaceholderText('Test'), + getQueriesForElement(instance).findByTestId('Test'), + getQueriesForElement(instance).findByA11yLabel('Test'), + getQueriesForElement(instance).findByLabelText('Test'), + getQueriesForElement(instance).findByA11yHint('Test'), + getQueriesForElement(instance).findByHintText('Test'), + getQueriesForElement(instance).findByA11yRole('button'), + getQueriesForElement(instance).findByRole('button'), + getQueriesForElement(instance).findByA11yState({ busy: true }), + getQueriesForElement(instance).findByA11yValue({ min: 10 }), ]; const withinFindAll: Promise[] = [ @@ -381,4 +442,16 @@ const withinFindAll: Promise[] = [ within(instance).findAllByRole('button'), within(instance).findAllByA11yState({ busy: true }), within(instance).findAllByA11yValue({ min: 10 }), + getQueriesForElement(instance).findAllByText('Test'), + getQueriesForElement(instance).findAllByDisplayValue('Test'), + getQueriesForElement(instance).findAllByPlaceholderText('Test'), + getQueriesForElement(instance).findAllByTestId('Test'), + getQueriesForElement(instance).findAllByA11yLabel('Test'), + getQueriesForElement(instance).findAllByLabelText('Test'), + getQueriesForElement(instance).findAllByA11yHint('Test'), + getQueriesForElement(instance).findAllByHintText('Test'), + getQueriesForElement(instance).findAllByA11yRole('button'), + getQueriesForElement(instance).findAllByRole('button'), + getQueriesForElement(instance).findAllByA11yState({ busy: true }), + getQueriesForElement(instance).findAllByA11yValue({ min: 10 }), ]; diff --git a/typings/index.d.ts b/typings/index.d.ts index 640055fd9..8c483b40b 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -346,6 +346,9 @@ export declare const waitForElementToBeRemoved: WaitForElementToBeRemovedFunctio export declare const act: (callback: () => void) => Thenable; export declare const within: (instance: ReactTestInstance) => Queries; +export declare const getQueriesForElement: ( + instance: ReactTestInstance +) => Queries; /** * @deprecated This function has been removed. Please use `waitFor` function. diff --git a/website/docs/API.md b/website/docs/API.md index 728cbfd63..37fdff2ad 100644 --- a/website/docs/API.md +++ b/website/docs/API.md @@ -368,7 +368,10 @@ function waitForElementToBeRemoved( Waits for non-deterministic periods of time until queried element is removed or times out. `waitForElementToBeRemoved` periodically calls `expectation` every `interval` milliseconds to determine whether the element has been removed or not. ```jsx -import { render, waitForElementToBeRemoved } from 'react-native-testing-library'; +import { + render, + waitForElementToBeRemoved, +} from 'react-native-testing-library'; test('waiting for an Banana to be removed', async () => { const { getByText } = render(); @@ -387,7 +390,7 @@ In order to properly use `waitForElementToBeRemoved` you need at least React >=1 If you're using Jest's [Timer Mocks](https://jestjs.io/docs/en/timer-mocks#docsNav), remember not to use `async/await` syntax as it will stall your tests. -## `within` +## `within`, `getQueriesForElement` - [`Example code`](https://github.com/callstack/react-native-testing-library/blob/master/src/__tests__/within.test.js) @@ -395,9 +398,10 @@ Defined as: ```jsx function within(instance: ReactTestInstance): Queries +function getQueriesForElement(instance: ReactTestInstance): Queries ``` -Perform [queries](./Queries.md) scoped to given element. +`within` (also available as `getQueriesForElement` alias) performs [queries](./Queries.md) scoped to given element. :::note Please note that additional `render` specific operations like `update`, `unmount`, `debug`, `toJSON` are _not_ included. diff --git a/website/docs/MigrationV7.md b/website/docs/MigrationV7.md index 2cadebc82..f55836e6e 100644 --- a/website/docs/MigrationV7.md +++ b/website/docs/MigrationV7.md @@ -50,7 +50,6 @@ This guide describes steps necessary to migrate from `@testing-library/react-nat ## Changed helpers -- `getQueriesForElement` is removed, rename it to `within` - `wait` and `waitForElement` is removed, rename these to `waitFor` ## Missing queries From 57318a5acc19e26b0649d89db8a382850f589648 Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Tue, 28 Jul 2020 11:50:49 +0200 Subject: [PATCH 04/11] fix: update package name in docs (#462) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: package reference in docs * fix: more references to package name * Update README.md Co-authored-by: Michał Pierzchała * Update website/docs/GettingStarted.md Co-authored-by: Michał Pierzchała * Update website/docs/API.md Co-authored-by: Michał Pierzchała --- .github/ISSUE_TEMPLATE/bug_report.md | 4 ++-- CONTRIBUTING.md | 2 +- README.md | 10 +++++----- pure.js | 2 +- src/helpers/errors.js | 2 +- website/docs/API.md | 28 ++++++++++++++-------------- website/docs/GettingStarted.md | 8 ++++---- website/docs/Queries.md | 22 +++++++++++----------- website/docs/ReactNavigation.md | 6 +++--- website/docs/ReduxIntegration.md | 4 ++-- 10 files changed, 44 insertions(+), 44 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 013127896..366ce7186 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -34,5 +34,5 @@ labels: 'bug report' \ No newline at end of file + `npx envinfo --npmPackages react,react-native,react-test-renderer,@testing-library/react-native` +--> diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c662de50c..5951059da 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -63,4 +63,4 @@ You can report issues on our [bug tracker](https://github.com/callstack/react-na ## License -By contributing to `react-native-testing-library`, you agree that your contributions will be licensed under its **MIT** license. +By contributing to `@testing-library/react-native`, you agree that your contributions will be licensed under its **MIT** license. diff --git a/README.md b/README.md index 4b5bbc583..a3d6fba2a 100644 --- a/README.md +++ b/README.md @@ -27,14 +27,14 @@ You finally want to approach testing using only best practices, while Enzyme may ## This solution -The `react-native-testing-library` is a lightweight solution for testing your React Native components. It provides light utility functions on top of `react-test-renderer` letting you always be up to date with latest React features and write any component tests you like. But really not any, it prevents you from testing implementation details because we stand this is a very bad practice. +The React Native Testing Library is a lightweight solution for testing your React Native components. It provides light utility functions on top of `react-test-renderer` letting you always be up to date with latest React features and write any component tests you like. But really not any, it prevents you from testing implementation details because we stand this is a very bad practice. This library is a replacement for [Enzyme](http://airbnb.io/enzyme/). It is tested to work with Jest, but it should work with other test runners as well. ## Example ```jsx -import { render, fireEvent } from 'react-native-testing-library'; +import { render, fireEvent } from '@testing-library/react-native'; import { QuestionsBoard } from '../QuestionsBoard'; test('form submits two answers', () => { @@ -67,13 +67,13 @@ Open a Terminal in your project's folder and run: #### Using `yarn` ```sh -yarn add --dev react-native-testing-library +yarn add --dev @testing-library/react-native ``` #### Using `npm` ```sh -npm install --save-dev react-native-testing-library +npm install --save-dev @testing-library/react-native ``` This library has a peerDependencies listing for `react-test-renderer` and, of course, `react`. Make sure to install them too! @@ -115,7 +115,7 @@ As you may have noticed, it's not tied to React Native at all – you can safely ## API / Usage -The [public API](https://callstack.github.io/react-native-testing-library/docs/api) of `react-native-testing-library` is focused around these essential methods: +The [public API](https://callstack.github.io/react-native-testing-library/docs/api) of `@testing-library/react-native` is focused around these essential methods: - [`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. diff --git a/pure.js b/pure.js index bced0b756..597240bc6 100644 --- a/pure.js +++ b/pure.js @@ -1,2 +1,2 @@ -// makes it so people can import from 'react-native-testing-library/pure' +// makes it so people can import from '@testing-library/react-native/pure' module.exports = require('./build/pure'); diff --git a/src/helpers/errors.js b/src/helpers/errors.js index df76871cf..cd70d8518 100644 --- a/src/helpers/errors.js +++ b/src/helpers/errors.js @@ -33,7 +33,7 @@ export function printDeprecationWarning(functionName: string) { console.warn(` Deprecation Warning: - Use of ${functionName} is not recommended and will be deleted in future versions of react-native-testing-library. + Use of ${functionName} is not recommended and will be deleted in future versions of @testing-library/react-native. `); warned[functionName] = true; diff --git a/website/docs/API.md b/website/docs/API.md index 37fdff2ad..540717a3b 100644 --- a/website/docs/API.md +++ b/website/docs/API.md @@ -3,7 +3,7 @@ id: api title: API --- -This page gathers public API of `react-native-testing-library` along with usage examples. +This page gathers public API of React Native Testing Library along with usage examples. ## `render` @@ -26,7 +26,7 @@ function render( Deeply renders given React element and returns helpers to query the output components structure. ```jsx -import { render } from 'react-native-testing-library'; +import { render } from '@testing-library/react-native'; import { QuestionsBoard } from '../QuestionsBoard'; test('should verify two questions', () => { @@ -50,7 +50,7 @@ See [Queries](./Queries.md) for a complete list. #### Example ```jsx -import { render } from 'react-native-testing-library'; +import { render } from '@testing-library/react-native'; const { getByText, queryByA11yStates } = render(); ``` @@ -134,7 +134,7 @@ Please note that this is done automatically if the testing framework you're usin 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/pure'; +import { cleanup, render } from '@testing-library/react-native/pure'; import { View } from 'react-native'; afterEach(cleanup); @@ -173,7 +173,7 @@ Fires native-like event with data. Invokes a given event handler (whether native or custom) on the element, bubbling to the root of the rendered tree. ```jsx -import { render, fireEvent } from 'react-native-testing-library'; +import { render, fireEvent } from '@testing-library/react-native'; test('fire changeText event', () => { const onEventMock = jest.fn(); @@ -192,7 +192,7 @@ An example using `fireEvent` with native events that aren't already aliased by t ```jsx import { TextInput, View } from 'react-native'; -import { fireEvent, render } from 'react-native-testing-library'; +import { fireEvent, render } from '@testing-library/react-native'; const onBlurMock = jest.fn(); @@ -220,7 +220,7 @@ Invokes `press` event handler on the element or parent element in the tree. ```jsx import { View, Text, TouchableOpacity } from 'react-native'; -import { render, fireEvent } from 'react-native-testing-library'; +import { render, fireEvent } from '@testing-library/react-native'; const onPressMock = jest.fn(); @@ -242,7 +242,7 @@ Invokes `changeText` event handler on the element or parent element in the tree. ```jsx import { View, TextInput } from 'react-native'; -import { render, fireEvent } from 'react-native-testing-library'; +import { render, fireEvent } from '@testing-library/react-native'; const onChangeTextMock = jest.fn(); const CHANGE_TEXT = 'content'; @@ -264,7 +264,7 @@ Invokes `scroll` event handler on the element or parent element in the tree. ```jsx import { ScrollView, Text } from 'react-native'; -import { render, fireEvent } from 'react-native-testing-library'; +import { render, fireEvent } from '@testing-library/react-native'; const onScrollMock = jest.fn(); const eventData = { @@ -288,7 +288,7 @@ fireEvent.scroll(getByText('scroll-view'), eventData); ```jsx import { FlatList, View } from 'react-native'; -import { render, fireEvent } from 'react-native-testing-library'; +import { render, fireEvent } from '@testing-library/react-native'; const onEndReached = jest.fn(); const { getByType } = render( @@ -337,7 +337,7 @@ function waitFor( 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. ```jsx -import { render, waitFor } from 'react-native-testing-library'; +import { render, waitFor } from '@testing-library/react-native'; test('waiting for an Banana to be ready', async () => { const { getByText } = render(); @@ -371,7 +371,7 @@ Waits for non-deterministic periods of time until queried element is removed or import { render, waitForElementToBeRemoved, -} from 'react-native-testing-library'; +} from '@testing-library/react-native'; test('waiting for an Banana to be removed', async () => { const { getByText } = render(); @@ -425,7 +425,7 @@ Use cases for scoped queries include: 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: ```jsx -import { render } from 'react-native-testing-library'; +import { render } from '@testing-library/react-native'; const { queryByText } = render(
); const submitButton = queryByText('submit'); @@ -437,7 +437,7 @@ expect(submitButton).toBeNull(); // it doesn't exist Each of the query APIs have a corresponding queryAll version that always returns an Array of matching nodes. getAll is the same but throws when the array has a length of 0. ```jsx -import { render } from 'react-native-testing-library'; +import { render } from '@testing-library/react-native'; const { queryAllByText } = render(); const submitButtons = queryAllByText('submit'); diff --git a/website/docs/GettingStarted.md b/website/docs/GettingStarted.md index 9ba8587b9..0695b73c4 100644 --- a/website/docs/GettingStarted.md +++ b/website/docs/GettingStarted.md @@ -13,14 +13,14 @@ You finally want to approach testing using only best practices, while Enzyme may ## This solution -The `react-native-testing-library` is a lightweight solution for testing your React Native components. It provides light utility functions on top of `react-test-renderer` letting you always be up to date with latest React features and write any component tests you like. It also prevents you from testing implementation details because we believe this is a very bad practice. +The React Native Testing Library is a lightweight solution for testing your React Native components. It provides light utility functions on top of `react-test-renderer` letting you always be up to date with latest React features and write any component tests you like. It also prevents you from testing implementation details because we believe this is a very bad practice. This library is a replacement for [Enzyme](http://airbnb.io/enzyme/). ## Example ```jsx -import { render, fireEvent } from 'react-native-testing-library'; +import { render, fireEvent } from '@testing-library/react-native'; import { QuestionsBoard } from '../QuestionsBoard'; test('form submits two answers', () => { @@ -53,13 +53,13 @@ Open a Terminal in your project's folder and run: #### Using `yarn` ```sh -yarn add --dev react-native-testing-library +yarn add --dev @testing-library/react-native ``` #### Using `npm` ```sh -npm install --save-dev react-native-testing-library +npm install --save-dev @testing-library/react-native ``` This library has a peerDependencies listing for `react-test-renderer` and, of course, `react`. Make sure to install them too! diff --git a/website/docs/Queries.md b/website/docs/Queries.md index b59b4d3ec..d4c095a9d 100644 --- a/website/docs/Queries.md +++ b/website/docs/Queries.md @@ -62,7 +62,7 @@ Returns a `ReactTestInstance` with matching text – may be a string or regular This method will join `` siblings to find matches, similarly to [how React Native handles these components](https://facebook.github.io/react-native/docs/text#containers). This will allow for querying for strings that will be visually rendered together, but may be semantically separate React components. ```jsx -import { render } from 'react-native-testing-library'; +import { render } from '@testing-library/react-native'; const { getByText } = render(); const element = getByText('banana'); @@ -75,7 +75,7 @@ const element = getByText('banana'); Returns a `ReactTestInstance` for a `TextInput` with a matching placeholder – may be a string or regular expression. ```jsx -import { render } from 'react-native-testing-library'; +import { render } from '@testing-library/react-native'; const { getByPlaceholderText } = render(); const element = getByPlaceholderText('username'); @@ -88,7 +88,7 @@ const element = getByPlaceholderText('username'); Returns a `ReactTestInstance` for a `TextInput` with a matching display value – may be a string or regular expression. ```jsx -import { render } from 'react-native-testing-library'; +import { render } from '@testing-library/react-native'; const { getByDisplayValue } = render(); const element = getByDisplayValue('username'); @@ -101,7 +101,7 @@ const element = getByDisplayValue('username'); Returns a `ReactTestInstance` with matching `testID` prop. ```jsx -import { render } from 'react-native-testing-library'; +import { render } from '@testing-library/react-native'; const { getByTestId } = render(); const element = getByTestId('unique-id'); @@ -120,7 +120,7 @@ Please be mindful when using these API and **treat it as an escape hatch**. Your Returns a `ReactTestInstance` with matching `accessibilityLabel` prop. ```jsx -import { render } from 'react-native-testing-library'; +import { render } from '@testing-library/react-native'; const { getByA11yLabel } = render(); const element = getByA11yLabel('my-label'); @@ -135,7 +135,7 @@ const element = getByA11yLabel('my-label'); Returns a `ReactTestInstance` with matching `accessibilityHint` prop. ```jsx -import { render } from 'react-native-testing-library'; +import { render } from '@testing-library/react-native'; const { getByA11yHint } = render(); const element = getByA11yHint('my-hint'); @@ -149,7 +149,7 @@ const element = getByA11yHint('my-hint'); Returns a `ReactTestInstance` with matching `accessibilityStates` prop. ```jsx -import { render } from 'react-native-testing-library'; +import { render } from '@testing-library/react-native'; const { getByA11yStates } = render(); const element = getByA11yStates(['checked']); @@ -165,7 +165,7 @@ const element2 = getByA11yStates('checked'); Returns a `ReactTestInstance` with matching `accessibilityRole` prop. ```jsx -import { render } from 'react-native-testing-library'; +import { render } from '@testing-library/react-native'; const { getByA11yRole } = render(); const element = getByA11yRole('button'); @@ -179,7 +179,7 @@ const element = getByA11yRole('button'); Returns a `ReactTestInstance` with matching `accessibilityState` prop. ```jsx -import { render } from 'react-native-testing-library'; +import { render } from '@testing-library/react-native'; const { getByA11yState } = render(); const element = getByA11yState({ disabled: true }); @@ -193,7 +193,7 @@ const element = getByA11yState({ disabled: true }); Returns a `ReactTestInstance` with matching `accessibilityValue` prop. ```jsx -import { render } from 'react-native-testing-library'; +import { render } from '@testing-library/react-native'; const { getByA11yValue } = render(); const element = getByA11yValue({ min: 40 }); @@ -203,7 +203,7 @@ const element = getByA11yValue({ min: 40 }); > 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. +`render` from `@testing-library/react-native` 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 diff --git a/website/docs/ReactNavigation.md b/website/docs/ReactNavigation.md index ea946611d..f76bd88b2 100644 --- a/website/docs/ReactNavigation.md +++ b/website/docs/ReactNavigation.md @@ -3,7 +3,7 @@ id: react-navigation title: React Navigation --- -This section deals with integrating `react-native-testing-library` with `react-navigation`, using Jest. +This section deals with integrating `@testing-library/react-native` with `react-navigation`, using Jest. ## Setting up @@ -127,7 +127,7 @@ const styles = StyleSheet.create({ Install required dev dependencies: ``` -$ yarn add -D jest react-native-testing-library +$ yarn add -D jest @testing-library/react-native ``` Create your `jest.config.js` file (or place the following properties in your `package.json` as a "jest" property) @@ -154,7 +154,7 @@ Let's a [`AppNavigator.test.js`](https://github.com/callstack/react-native-testi ```jsx import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; -import { render, fireEvent } from 'react-native-testing-library'; +import { render, fireEvent } from '@testing-library/react-native'; import AppNavigator from '../AppNavigator'; diff --git a/website/docs/ReduxIntegration.md b/website/docs/ReduxIntegration.md index 349922426..7cb6f7426 100644 --- a/website/docs/ReduxIntegration.md +++ b/website/docs/ReduxIntegration.md @@ -18,7 +18,7 @@ For `./components/AddTodo.test.js` ```jsx import React from 'react'; import { Provider } from 'react-redux'; -import { cleanup, fireEvent, render } from 'react-native-testing-library'; +import { cleanup, fireEvent, render } from '@testing-library/react-native'; import configureStore from '../store'; import AddTodo from './AddTodo'; @@ -65,7 +65,7 @@ For the `./components/TodoList.js` ```jsx import React from 'react'; import { Provider } from 'react-redux'; -import { fireEvent, render } from 'react-native-testing-library'; +import { fireEvent, render } from '@testing-library/react-native'; import configureStore from '../store'; import TodoList from './TodoList'; From d6c590f72ca47057acd1de1b0fe19a4d7290309c Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Tue, 28 Jul 2020 15:11:28 +0200 Subject: [PATCH 05/11] feat: prevent events on disabled elements (#460) * feat: add tests * feat: prevent event handling on disabled element * refactor: code cleanup * feat: use props.onStartShouldSetResponder to check for event handling * refactor: code review changes * feat: updated docs * feat: added test for fake 'disabled' prop --- src/__tests__/fireEvent.test.js | 79 +++++++++++++++++++++++++++++++++ src/fireEvent.js | 18 +++++--- website/docs/API.md | 4 ++ website/docs/MigrationV7.md | 14 +++--- 4 files changed, 101 insertions(+), 14 deletions(-) diff --git a/src/__tests__/fireEvent.test.js b/src/__tests__/fireEvent.test.js index 5a261dba7..fa0b9c255 100644 --- a/src/__tests__/fireEvent.test.js +++ b/src/__tests__/fireEvent.test.js @@ -3,6 +3,7 @@ import React from 'react'; import { View, TouchableOpacity, + Pressable, Text, ScrollView, TextInput, @@ -163,3 +164,81 @@ test('event with multiple handler parameters', () => { expect(handlePress).toHaveBeenCalledWith('param1', 'param2'); }); + +test('should not fire on disabled TouchableOpacity', () => { + const handlePress = jest.fn(); + const screen = render( + + Trigger + + ); + + expect(() => fireEvent.press(screen.getByText('Trigger'))).toThrow( + 'No handler function found for event: "press"' + ); + expect(handlePress).not.toHaveBeenCalled(); +}); + +test('should not fire on disabled Pressable', () => { + const handlePress = jest.fn(); + const screen = render( + + Trigger + + ); + + expect(() => fireEvent.press(screen.getByText('Trigger'))).toThrow( + 'No handler function found for event: "press"' + ); + expect(handlePress).not.toHaveBeenCalled(); +}); + +test('should pass event up on disabled TouchableOpacity', () => { + const handleInnerPress = jest.fn(); + const handleOuterPress = jest.fn(); + const screen = render( + + + Inner Trigger + + + ); + + fireEvent.press(screen.getByText('Inner Trigger')); + expect(handleInnerPress).not.toHaveBeenCalled(); + expect(handleOuterPress).toHaveBeenCalledTimes(1); +}); + +test('should pass event up on disabled Pressable', () => { + const handleInnerPress = jest.fn(); + const handleOuterPress = jest.fn(); + const screen = render( + + + Inner Trigger + + + ); + + fireEvent.press(screen.getByText('Inner Trigger')); + expect(handleInnerPress).not.toHaveBeenCalled(); + expect(handleOuterPress).toHaveBeenCalledTimes(1); +}); + +const TestComponent = ({ onPress }) => { + return ( + + Trigger Test + + ); +}; + +test('is not fooled by non-native disabled prop', () => { + const handlePress = jest.fn(); + const screen = render( + + ); + + fireEvent.press(screen.getByText('Trigger Test')); + expect(handlePress).toHaveBeenCalledTimes(1); +}); diff --git a/src/fireEvent.js b/src/fireEvent.js index 787620c5d..c367679f5 100644 --- a/src/fireEvent.js +++ b/src/fireEvent.js @@ -5,13 +5,19 @@ import { ErrorWithStack } from './helpers/errors'; const findEventHandler = ( element: ReactTestInstance, eventName: string, - callsite?: any + callsite?: any, + nearestHostDescendent?: ReactTestInstance ) => { - const eventHandler = toEventHandlerName(eventName); + const isHostComponent = typeof element.type === 'string'; + const hostElement = isHostComponent ? element : nearestHostDescendent; + const isEventEnabled = + hostElement?.props.onStartShouldSetResponder?.() !== false; + + const eventHandlerName = toEventHandlerName(eventName); - if (typeof element.props[eventHandler] === 'function') { - return element.props[eventHandler]; - } else if (typeof element.props[eventName] === 'function') { + if (typeof element.props[eventHandlerName] === 'function' && isEventEnabled) { + return element.props[eventHandlerName]; + } else if (typeof element.props[eventName] === 'function' && isEventEnabled) { return element.props[eventName]; } @@ -23,7 +29,7 @@ const findEventHandler = ( ); } - return findEventHandler(element.parent, eventName, callsite); + return findEventHandler(element.parent, eventName, callsite, hostElement); }; const invokeEvent = ( diff --git a/website/docs/API.md b/website/docs/API.md index 540717a3b..8937c9d25 100644 --- a/website/docs/API.md +++ b/website/docs/API.md @@ -188,6 +188,10 @@ test('fire changeText event', () => { }); ``` +:::note +Please note that from version `7.0` `fireEvent` performs checks that should prevent events firing on disabled elements. +::: + An example using `fireEvent` with native events that aren't already aliased by the `fireEvent` api. ```jsx diff --git a/website/docs/MigrationV7.md b/website/docs/MigrationV7.md index f55836e6e..46ed23b3a 100644 --- a/website/docs/MigrationV7.md +++ b/website/docs/MigrationV7.md @@ -44,6 +44,12 @@ To improve compatibility with React Testing Library, and to ease the migration f Please replace all occurrences of these queries in your codebase. +## `fireEvent` support for disabled components + +To improve compatibility with real React Native environment `fireEvent` now performs checks whether the component is disabled before firing an event on it. The checks internally uses `onStartShouldSetResponder` prop to establish should event fire, which should resemble the actual React Native runtime. + +If your code contained any workarounds for preventing events firing on disabled events, you should now be able to remove them. + # Guide for `@testing-library/react-native` users This guide describes steps necessary to migrate from `@testing-library/react-native` from `v6.0` to `v7.0`. Although the name stays the same, this is a different library, sourced at [Callstack GitHub repository](https://github.com/callstack/react-native-testing-library). We made sure the upgrade path is as easy for you as possible. @@ -87,14 +93,6 @@ Cleaning up (unmounting) components after each test is included by default in th You can opt-out of this behavior by running tests with `RNTL_SKIP_AUTO_CLEANUP=true` flag or importing from `@testing-library/react-native/pure`. We encourage you to keep the default though. -## No special handling for `disabled` prop - -The `disabled` prop on "Touchable\*" components is treated in the same manner as any other prop. We realize that with our library you can press "touchable" components even though they're in "disabled" state, however this is something that we strongly believe should be fixed upstream, in React Native core. - -If you feel strongly about this difference, please send a PR to React Native, adding JavaScript logic to "onPress" functions, making them aware of disabled state in JS logic as well (it's handled on native side for at least iOS, which is the default platform that tests are running in). - -As a mitigation, you'll likely need to modify the logic of "touchable" components to bail if they're pressed in disabled state. - ## No [NativeTestInstance](https://www.native-testing-library.com/docs/api-test-instance) abstraction We don't provide any abstraction over `ReactTestInstance` returned by queries, but allow to use it directly to access queried component's `props` or `type` for that example. From a559dbf6005b70e977a0ef0b2374c85f8381bbde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Tue, 28 Jul 2020 15:45:27 +0200 Subject: [PATCH 06/11] chore(breaking): rename to @testing-library/react-native (#463) --- README.md | 4 ++-- examples/reactnavigation/package.json | 4 ++-- examples/reactnavigation/src/__tests__/AppNavigator.test.js | 2 +- examples/redux/components/AddTodo.test.js | 2 +- examples/redux/components/TodoList.test.js | 2 +- examples/redux/package.json | 2 +- package.json | 6 +++--- website/docusaurus.config.js | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index a3d6fba2a..fb283d4c4 100644 --- a/README.md +++ b/README.md @@ -142,8 +142,8 @@ Supported and used by [Rally Health](https://www.rallyhealth.com/careers-home). -[version-badge]: https://img.shields.io/npm/v/react-native-testing-library.svg?style=flat-square -[package]: https://www.npmjs.com/package/react-native-testing-library +[version-badge]: https://img.shields.io/npm/v/@testing-library/react-native.svg?style=flat-square +[package]: https://www.npmjs.com/package/@testing-library/react-native [prs-welcome-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square [prs-welcome]: http://makeapullrequest.com [chat-badge]: https://img.shields.io/discord/426714625279524876.svg?style=flat-square&colorB=758ED3 diff --git a/examples/reactnavigation/package.json b/examples/reactnavigation/package.json index c2428b592..093ae1542 100644 --- a/examples/reactnavigation/package.json +++ b/examples/reactnavigation/package.json @@ -1,6 +1,6 @@ { "name": "react-navigation-example", - "description": "Testing react-navigation with react-native-testing-library", + "description": "Testing React Navigation with RNTL", "version": "0.0.1", "private": true, "scripts": { @@ -24,7 +24,7 @@ "babel-jest": "^25.4.0", "jest": "^25.4.0", "metro-react-native-babel-preset": "^0.59.0", - "react-native-testing-library": "^1.13.0", + "@testing-library/react-native": "^7.0.0-rc.0", "react-test-renderer": "^16.13.1" } } diff --git a/examples/reactnavigation/src/__tests__/AppNavigator.test.js b/examples/reactnavigation/src/__tests__/AppNavigator.test.js index 81ada1740..e76ea4339 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 } from 'react-native-testing-library'; +import { render, fireEvent } from '@testing-library/react-native'; import AppNavigator from '../AppNavigator'; diff --git a/examples/redux/components/AddTodo.test.js b/examples/redux/components/AddTodo.test.js index faeca8508..3e1155b44 100644 --- a/examples/redux/components/AddTodo.test.js +++ b/examples/redux/components/AddTodo.test.js @@ -1,6 +1,6 @@ import React from 'react'; import { Provider } from 'react-redux'; -import { fireEvent, render } from 'react-native-testing-library'; +import { fireEvent, render } from '@testing-library/react-native'; import configureStore from '../store'; import AddTodo from './AddTodo'; diff --git a/examples/redux/components/TodoList.test.js b/examples/redux/components/TodoList.test.js index 595fcea27..a14d6af1f 100644 --- a/examples/redux/components/TodoList.test.js +++ b/examples/redux/components/TodoList.test.js @@ -1,6 +1,6 @@ import React from 'react'; import { Provider } from 'react-redux'; -import { fireEvent, render } from 'react-native-testing-library'; +import { fireEvent, render } from '@testing-library/react-native'; import configureStore from '../store'; import TodoList from './TodoList'; diff --git a/examples/redux/package.json b/examples/redux/package.json index 95b4ea122..483888439 100644 --- a/examples/redux/package.json +++ b/examples/redux/package.json @@ -16,7 +16,7 @@ "babel-jest": "~25.2.6", "jest": "~25.2.6", "metro-react-native-babel-preset": "^0.59.0", - "react-native-testing-library": "^1.13.2", + "@testing-library/react-native": "^7.0.0-rc.0", "react-test-renderer": "~16.9.0" }, "private": true, diff --git a/package.json b/package.json index d56566a4a..3dbb8b1a9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "react-native-testing-library", - "version": "2.2.0", - "description": "Simple React Native testing utilities helping you write better tests with less effort", + "name": "@testing-library/react-native", + "version": "7.0.0-rc.0", + "description": "Simple and complete React Native testing utilities that encourage good testing practices.", "main": "build/index.js", "typings": "./typings/index.d.ts", "repository": { diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 1b41a02c6..6efb8f468 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -7,7 +7,7 @@ const siteConfig = { url: 'https://callstack.github.io', // Your website URL baseUrl: '/react-native-testing-library/', // Base URL for your project // Used for publishing and more - projectName: 'react-native-testing-library', + projectName: '@testing-library/react-native', organizationName: 'callstack', favicon: 'img/owl.png', From ef207607ed5c3d97ade2d5c4d3433d710271fa93 Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Tue, 28 Jul 2020 17:21:52 +0200 Subject: [PATCH 07/11] Added migration v7 link to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fb283d4c4..4b3fb29d9 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,7 @@ The [public API](https://callstack.github.io/react-native-testing-library/docs/a ## Migration Guides +- [Migration to 7.0](https://callstack.github.io/react-native-testing-library/docs/migration-v7) - [Migration to 2.0](https://callstack.github.io/react-native-testing-library/docs/migration-v2) ## Related External Resources From 338d27186f4fabe911f9d790fc4d3bff764d8de1 Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Tue, 28 Jul 2020 17:31:53 +0200 Subject: [PATCH 08/11] fix: added migration guide v7 to website sidebar (#464) --- website/sidebars.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/sidebars.js b/website/sidebars.js index 1d5e0411a..e9615fc90 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -2,7 +2,7 @@ module.exports = { docs: { Introduction: ['getting-started'], 'API Reference': ['api', 'api-queries'], - Guides: ['migration-v2'], + Guides: ['migration-v7', 'migration-v2'], Examples: ['react-navigation', 'redux-integration'], }, }; From 775010074af2c36f42247c81ff4cc3ffd9f77052 Mon Sep 17 00:00:00 2001 From: Nick McCurdy Date: Thu, 30 Jul 2020 03:20:58 -0400 Subject: [PATCH 09/11] docs: fix typo in migration v7 doc (#465) --- website/docs/MigrationV7.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/MigrationV7.md b/website/docs/MigrationV7.md index 46ed23b3a..4759138f0 100644 --- a/website/docs/MigrationV7.md +++ b/website/docs/MigrationV7.md @@ -56,7 +56,7 @@ This guide describes steps necessary to migrate from `@testing-library/react-nat ## Changed helpers -- `wait` and `waitForElement` is removed, rename these to `waitFor` +- `wait` and `waitForElement` are removed, rename these to `waitFor` ## Missing queries From dc8d759ca46789d73a9aa41c9dae5ab50d205990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Thu, 30 Jul 2020 12:24:43 +0200 Subject: [PATCH 10/11] docs: refresh readme and getting started guide --- README.md | 77 ++++++++++++++++------------------ website/docs/GettingStarted.md | 76 +++++++++++++++++---------------- 2 files changed, 77 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 4b3fb29d9..3c9c7f13b 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,12 @@
+

React Native Testing Library

owl -

React Native Testing Library

- -

Lightweight React Native testing utilities helping you write better tests with less effort.

+

Simple and complete React Native testing utilities that encourage good testing practices.

[![Version][version-badge]][package] @@ -15,50 +14,17 @@ [![Chat][chat-badge]][chat] [![Sponsored by Callstack][callstack-badge]][callstack] -_Appreciation notice: This project is heavily inspired by [react-testing-library](https://github.com/testing-library/react-testing-library). Go check it out and use it to test your web React apps._ - ## The problem -You want to write maintainable tests for your React Native components without testing implementation details, but then you're told to use Enzyme, which you learn has no React Native adapter, meaning only shallow rendering is supported. And you want to render deep! But deep rendering may otherwise require jsdom (React Native isn't the web!), while doing deep rendering with `react-test-renderer` is so painful. - -You would also like to use the newest React features, but you need to wait for your testing library's abstractions to catch up and it takes a while. - -You finally want to approach testing using only best practices, while Enzyme may encourage assertions on implementation details. +You want to write maintainable tests for your React Native components. As a part of this goal, you want your tests to avoid including implementation details of your components and rather focus on making your tests give you the confidence for which they are intended. As part of this, you want your testbase to be maintainable in the long run so refactors of your components (changes to implementation but not functionality) don't break your tests and slow you and your team down. ## This solution -The React Native Testing Library is a lightweight solution for testing your React Native components. It provides light utility functions on top of `react-test-renderer` letting you always be up to date with latest React features and write any component tests you like. But really not any, it prevents you from testing implementation details because we stand this is a very bad practice. - -This library is a replacement for [Enzyme](http://airbnb.io/enzyme/). It is tested to work with Jest, but it should work with other test runners as well. - -## Example - -```jsx -import { render, fireEvent } from '@testing-library/react-native'; -import { QuestionsBoard } from '../QuestionsBoard'; - -test('form submits two answers', () => { - const allQuestions = ['q1', 'q2']; - const mockFn = jest.fn(); - - const { getAllByA11yLabel, getByText } = render( - - ); - - const answerInputs = getAllByA11yLabel('answer input'); +The React Native Testing Library (RNTL) is a lightweight solution for testing React Native components. It provides light utility functions on top of `react-test-renderer`, in a way that encourages better testing practices. Its primary guiding principle is: - fireEvent.changeText(answerInputs[0], 'a1'); - fireEvent.changeText(answerInputs[1], 'a2'); - fireEvent.press(getByText('Submit')); +> The more your tests resemble the way your software is used, the more confidence they can give you. - expect(mockFn).toBeCalledWith({ - '1': { q: 'q1', a: 'a1' }, - '2': { q: 'q2', a: 'a2' }, - }); -}); -``` - -You can find the source of `QuestionsBoard` component and this example [here](https://github.com/callstack/react-native-testing-library/blob/master/src/__tests__/questionsBoard.test.js). +This project is inspired by [React Testing Library](https://github.com/testing-library/react-testing-library). Tested to work with Jest, but it should work with other test runners as well. ## Installation @@ -78,6 +44,8 @@ npm install --save-dev @testing-library/react-native This library has a peerDependencies listing for `react-test-renderer` and, of course, `react`. Make sure to install them too! +> 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: @@ -111,7 +79,34 @@ Note for [Flow](https://flow.org) users – you'll also need to install typings flow-typed install react-test-renderer ``` -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. +## Example + +```jsx +import { render, fireEvent } from '@testing-library/react-native'; +import { QuestionsBoard } from '../QuestionsBoard'; + +test('form submits two answers', () => { + const allQuestions = ['q1', 'q2']; + const mockFn = jest.fn(); + + const { getAllByA11yLabel, getByText } = render( + + ); + + const answerInputs = getAllByA11yLabel('answer input'); + + fireEvent.changeText(answerInputs[0], 'a1'); + fireEvent.changeText(answerInputs[1], 'a2'); + fireEvent.press(getByText('Submit')); + + expect(mockFn).toBeCalledWith({ + '1': { q: 'q1', a: 'a1' }, + '2': { q: 'q2', a: 'a2' }, + }); +}); +``` + +You can find the source of `QuestionsBoard` component and this example [here](https://github.com/callstack/react-native-testing-library/blob/master/src/__tests__/questionsBoard.test.js). ## API / Usage diff --git a/website/docs/GettingStarted.md b/website/docs/GettingStarted.md index 0695b73c4..536e96503 100644 --- a/website/docs/GettingStarted.md +++ b/website/docs/GettingStarted.md @@ -5,44 +5,15 @@ title: Getting Started ## The problem -You want to write maintainable tests for your React Native components without testing implementation details, but then you're told to use Enzyme, which you learn has no React Native adapter, meaning only shallow rendering is supported. And you want to render deep! But deep rendering may otherwise require jsdom (React Native isn't the web!), while doing deep rendering with `react-test-renderer` is so painful. - -You would also like to use the newest React features, but you need to wait for your testing library's abstractions to catch up and it takes a while. - -You finally want to approach testing using only best practices, while Enzyme may encourage assertions on implementation details. +You want to write maintainable tests for your React Native components. As a part of this goal, you want your tests to avoid including implementation details of your components and rather focus on making your tests give you the confidence for which they are intended. As part of this, you want your testbase to be maintainable in the long run so refactors of your components (changes to implementation but not functionality) don't break your tests and slow you and your team down. ## This solution -The React Native Testing Library is a lightweight solution for testing your React Native components. It provides light utility functions on top of `react-test-renderer` letting you always be up to date with latest React features and write any component tests you like. It also prevents you from testing implementation details because we believe this is a very bad practice. - -This library is a replacement for [Enzyme](http://airbnb.io/enzyme/). - -## Example - -```jsx -import { render, fireEvent } from '@testing-library/react-native'; -import { QuestionsBoard } from '../QuestionsBoard'; - -test('form submits two answers', () => { - const allQuestions = ['q1', 'q2']; - const mockFn = jest.fn(); - - const { getAllByA11yLabel, getByText } = render( - - ); - - const answerInputs = getAllByA11yLabel('answer input'); +The React Native Testing Library (RNTL) is a lightweight solution for testing React Native components. It provides light utility functions on top of `react-test-renderer`, in a way that encourages better testing practices. Its primary guiding principle is: - fireEvent.changeText(answerInputs[0], 'a1'); - fireEvent.changeText(answerInputs[1], 'a2'); - fireEvent.press(getByText('Submit')); +> The more your tests resemble the way your software is used, the more confidence they can give you. - expect(mockFn).toBeCalledWith({ - '1': { q: 'q1', a: 'a1' }, - '2': { q: 'q2', a: 'a2' }, - }); -}); -``` +This project is inspired by [React Testing Library](https://github.com/testing-library/react-testing-library). Tested to work with Jest, but it should work with other test runners as well. You can find the source of `QuestionsBoard` component and this example [here](https://github.com/callstack/react-native-testing-library/blob/master/src/__tests__/questionsBoard.test.js). @@ -64,8 +35,6 @@ npm install --save-dev @testing-library/react-native This library has a peerDependencies listing for `react-test-renderer` and, of course, `react`. Make sure to install them too! -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). ::: @@ -94,3 +63,40 @@ Then automatically add it to your jest tests by using `setupFilesAfterEnv` optio "setupFilesAfterEnv": ["@testing-library/jest-native/extend-expect"] } ``` + +### Flow + +Note for [Flow](https://flow.org) users – you'll also need to install typings for `react-test-renderer`: + +```sh +flow-typed install react-test-renderer +``` + +## Example + +```jsx +import { render, fireEvent } from '@testing-library/react-native'; +import { QuestionsBoard } from '../QuestionsBoard'; + +test('form submits two answers', () => { + const allQuestions = ['q1', 'q2']; + const mockFn = jest.fn(); + + const { getAllByA11yLabel, getByText } = render( + + ); + + const answerInputs = getAllByA11yLabel('answer input'); + + fireEvent.changeText(answerInputs[0], 'a1'); + fireEvent.changeText(answerInputs[1], 'a2'); + fireEvent.press(getByText('Submit')); + + expect(mockFn).toBeCalledWith({ + '1': { q: 'q1', a: 'a1' }, + '2': { q: 'q2', a: 'a2' }, + }); +}); +``` + +You can find the source of `QuestionsBoard` component and this example [here](https://github.com/callstack/react-native-testing-library/blob/master/src/__tests__/questionsBoard.test.js). From 47f570be9a076c565f5d9f80771841a23b1605da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Thu, 30 Jul 2020 12:47:54 +0200 Subject: [PATCH 11/11] docs: small amendments to the migration guide --- README.md | 2 ++ website/docs/MigrationV7.md | 26 +++++++++++++++----------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 3c9c7f13b..43728611f 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ [![Chat][chat-badge]][chat] [![Sponsored by Callstack][callstack-badge]][callstack] +> We renamed the `react-native-testing-library` npm package to `@testing-library/react-native`, officially joining the "Testing Library" family 🎉. Read the [migration guide](https://callstack.github.io/react-native-testing-library/docs/migration-v7). + ## The problem You want to write maintainable tests for your React Native components. As a part of this goal, you want your tests to avoid including implementation details of your components and rather focus on making your tests give you the confidence for which they are intended. As part of this, you want your testbase to be maintainable in the long run so refactors of your components (changes to implementation but not functionality) don't break your tests and slow you and your team down. diff --git a/website/docs/MigrationV7.md b/website/docs/MigrationV7.md index 4759138f0..55975664d 100644 --- a/website/docs/MigrationV7.md +++ b/website/docs/MigrationV7.md @@ -4,17 +4,17 @@ title: Migration to 7.0 --- :::caution -We renamed the `react-native-testing-library` npm package to `@testing-library/react-native`, joining the Testing Library family. +We renamed the `react-native-testing-library` npm package to `@testing-library/react-native`, officially joining the "Testing Library" family 🎉. ::: As the version 7.0 involves merging two libraries together, there are two variants for migration guide, dependent on library you used previously: -- [guide for `react-native-testing-library` users](#guide-for-react-native-testing-library-users) -- [guide for `@testing-library/react-native` users](#guide-for-testing-libraryreact-native-users) +- [Guide for `react-native-testing-library` users](#guide-for-react-native-testing-library-users) +- [Guide for `@testing-library/react-native` users](#guide-for-testing-libraryreact-native-users) # Guide for `react-native-testing-library` users -This guide describes steps necessary to migrate from React Native Testing Library `v2.x` to `v7.0`. +This guide describes steps necessary to migrate from React Native Testing Library `v2.x` or `v6.0` to `v7.0`. ## Renaming the library @@ -46,7 +46,7 @@ Please replace all occurrences of these queries in your codebase. ## `fireEvent` support for disabled components -To improve compatibility with real React Native environment `fireEvent` now performs checks whether the component is disabled before firing an event on it. The checks internally uses `onStartShouldSetResponder` prop to establish should event fire, which should resemble the actual React Native runtime. +To improve compatibility with the real React Native environment `fireEvent` now performs checks whether the component is "disabled" before firing an event on it. It uses the Responder system to establish should the event fire, which resembles the actual React Native runtime closer than we used to. If your code contained any workarounds for preventing events firing on disabled events, you should now be able to remove them. @@ -54,13 +54,17 @@ If your code contained any workarounds for preventing events firing on disabled This guide describes steps necessary to migrate from `@testing-library/react-native` from `v6.0` to `v7.0`. Although the name stays the same, this is a different library, sourced at [Callstack GitHub repository](https://github.com/callstack/react-native-testing-library). We made sure the upgrade path is as easy for you as possible. -## Changed helpers +## Renaming "wait" helpers -- `wait` and `waitForElement` are removed, rename these to `waitFor` +The `wait` and `waitForElement` helpers are replaced by `waitFor`. Please rename all occurrences of these in your codebase. -## Missing queries +## Changes to `ByTestId` queries -Our library doesn't implement `ByTitle` queries, which are targetting components with `title` prop, specifically `Button` and `RefreshControl`. If your tests only use `ByTitle` to target `Button` components, you can replace them with `ByText` queries, since React Native renders normal `Text` component under the hood. +The `ByTestId` queries don't accept RegExps. Please use strings instead. We're happy to accept PRs adding this functionality :). + +## No `ByTitle` queries + +Our library doesn't implement `ByTitle` queries, which are targetting components with `title` prop, specifically `Button` and `RefreshControl`. If your tests only use `ByTitle` to target `Button` components, you can replace them with `ByText` queries, since React Native renders `Text` under the hood. If you need to query `RefreshControl` component and can't figure out other way around it, you can use e.g. `UNSAFE_getByProps({title})` query. @@ -77,7 +81,7 @@ Use the official React Native preset for Jest: } ``` -We're told this should also speed up your tests startup on cold cache. Using official preset has another benefit. The library is compatible with any version of React Native without introducing breaking changes. +We're told this also speeds up your tests startup on cold cache. Using official preset has another benefit – the library is compatible with any version of React Native without introducing breaking changes. ## Cleanup is included by default @@ -112,4 +116,4 @@ There are slight differences in how `fireEvent` works in both libraries: +fireEvent(element: ReactTestInstance, eventName: string, ...data: Array) ``` 1. There is no `NativeTestEvent` - second and rest arguments are used instead. -1. There are only 3 short-hand events: [`fireEvent.press`](`/docs/api/#fireeventpress-element-reacttestinstance--void`), [`fireEvent.changeText`](https://callstack.github.io/react-native-testing-library/docs/api/#fireeventchangetext-element-reacttestinstance-data-arrayany--void), [`fireEvent.scroll`](https://callstack.github.io/react-native-testing-library/docs/api/#fireeventchangetext-element-reacttestinstance-data-arrayany--void). For all other or custom events you can use the base signature. +1. There are only 3 short-hand events: [`fireEvent.press`](`/docs/api/#fireeventpress-element-reacttestinstance--void`), [`fireEvent.changeText`](https://callstack.github.io/react-native-testing-library/docs/api/#fireeventchangetext-element-reacttestinstance-data-arrayany--void) and [`fireEvent.scroll`](https://callstack.github.io/react-native-testing-library/docs/api/#fireeventchangetext-element-reacttestinstance-data-arrayany--void). For all other or custom events you can use the base signature.