From 5ffa5b9e6f384edd0924b58f3b9d4ef24ea85178 Mon Sep 17 00:00:00 2001 From: Patryk Fryda Date: Thu, 20 Oct 2022 08:54:36 +0200 Subject: [PATCH 01/12] feat: check accessibilityLabelledBy in *ByLabelText queries --- src/queries/__tests__/labelText.test.tsx | 22 ++++++++++++- src/queries/labelText.ts | 41 ++++++++++++++++++++++-- website/docs/Queries.md | 5 ++- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/queries/__tests__/labelText.test.tsx b/src/queries/__tests__/labelText.test.tsx index 9e1b5c0cd..42bfde552 100644 --- a/src/queries/__tests__/labelText.test.tsx +++ b/src/queries/__tests__/labelText.test.tsx @@ -1,11 +1,13 @@ import * as React from 'react'; -import { View, Text, TouchableOpacity } from 'react-native'; +import { View, Text, TouchableOpacity, TextInput } from 'react-native'; import { render } from '../..'; const BUTTON_LABEL = 'cool button'; const BUTTON_HINT = 'click this button'; const TEXT_LABEL = 'cool text'; const TEXT_HINT = 'static text'; +const INPUT_LABEL = 'cool input'; +const INPUT_LABELLED_BY = 'formLabel'; // Little hack to make all the methods happy with type const NO_MATCHES_TEXT: any = 'not-existent-element'; @@ -41,6 +43,15 @@ const Section = () => ( ); +const FormInput = () => ( + <> + + {INPUT_LABEL} + + + +); + test('getByLabelText, queryByLabelText, findByLabelText', async () => { const { getByLabelText, queryByLabelText, findByLabelText } = render(
@@ -165,3 +176,12 @@ test('byLabelText queries support hidden option', () => { `"Unable to find an element with accessibilityLabel: hidden"` ); }); +test('getByLabelText supports accessibilityLabelledBy', async () => { + const { getByLabelText, queryByLabelText } = render(); + + expect(getByLabelText(INPUT_LABEL).props.accessibilityLabelledBy).toEqual( + INPUT_LABELLED_BY + ); + const textInput = queryByLabelText(/input/g); + expect(textInput?.props.accessibilityLabelledBy).toEqual(INPUT_LABELLED_BY); +}); diff --git a/src/queries/labelText.ts b/src/queries/labelText.ts index acfed4520..f3c584b2b 100644 --- a/src/queries/labelText.ts +++ b/src/queries/labelText.ts @@ -2,6 +2,7 @@ import type { ReactTestInstance } from 'react-test-renderer'; import { findAll } from '../helpers/findAll'; import { matches, TextMatch, TextMatchOptions } from '../matches'; import { makeQueries } from './makeQueries'; +import { getNodeByText } from './text'; import type { FindAllByQuery, FindByQuery, @@ -17,12 +18,48 @@ type ByLabelTextOptions = CommonQueryOptions & TextMatchOptions; const getNodeByLabelText = ( node: ReactTestInstance, text: TextMatch, - options: TextMatchOptions = {} + options: TextMatchOptions ) => { const { exact, normalizer } = options; return matches(text, node.props.accessibilityLabel, normalizer, exact); }; +const matchAccessibilityLabelledByText = ( + rootInstance: ReactTestInstance, + nativeID: string | undefined, + text: TextMatch, + options: TextMatchOptions +) => { + if (!nativeID) { + return false; + } + + const { exact, normalizer } = options; + + return rootInstance + .findAll((node) => + matches(nativeID, node.props.nativeID, normalizer, exact) + ) + .some((node) => node.findAll((n) => getNodeByText(n, text)).length > 0); +}; + +const matchAccessibilityLabel = ( + rootInstance: ReactTestInstance, + node: ReactTestInstance, + text: TextMatch, + options: TextMatchOptions = {} +) => { + return ( + getNodeByLabelText(node, text, options) || + matchAccessibilityLabelledByText( + rootInstance, + node.props.accessibilityLabelledBy, + text, + options + ) + ); +}; + const queryAllByLabelText = ( instance: ReactTestInstance ): (( @@ -34,7 +71,7 @@ const queryAllByLabelText = ( instance, (node) => typeof node.type === 'string' && - getNodeByLabelText(node, text, queryOptions), + matchAccessibilityLabel(instance, node, text, queryOptions), queryOptions ); }; diff --git a/website/docs/Queries.md b/website/docs/Queries.md index 979038f81..5e4dfcc70 100644 --- a/website/docs/Queries.md +++ b/website/docs/Queries.md @@ -212,7 +212,10 @@ getByLabelText( ): ReactTestInstance; ``` -Returns a `ReactTestInstance` with matching `accessibilityLabel` prop. +Returns a `ReactTestInstance` with matching label: + +- by matching `accessibilityLabel` prop +- or by matching text content of text view referenced by `accessibilityLabelledBy` prop ```jsx import { render, screen } from '@testing-library/react-native'; From 518dffb10ed2802af464ffb22a28d2c157580592 Mon Sep 17 00:00:00 2001 From: Patryk Fryda Date: Fri, 21 Oct 2022 10:37:48 +0200 Subject: [PATCH 02/12] refactor: move getNodeByText to matchTextContent helper --- src/helpers/matchers/matchTextContent.ts | 7 +++++++ src/queries/labelText.ts | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/helpers/matchers/matchTextContent.ts b/src/helpers/matchers/matchTextContent.ts index cf7770e27..6dc3556f1 100644 --- a/src/helpers/matchers/matchTextContent.ts +++ b/src/helpers/matchers/matchTextContent.ts @@ -6,6 +6,13 @@ import { filterNodeByType } from '../filterNodeByType'; import { getTextContent } from '../getTextContent'; import { getHostComponentNames } from '../host-component-names'; +/** + * Matches the given node's text content against string or regex matcher. + * + * @param node - Node which text content will be matched + * @param text - The string or regex to match. + * @returns - Whether the node's text content matches the given string or regex. + */ export function matchTextContent( node: ReactTestInstance, text: TextMatch, diff --git a/src/queries/labelText.ts b/src/queries/labelText.ts index f3c584b2b..75f3d4d54 100644 --- a/src/queries/labelText.ts +++ b/src/queries/labelText.ts @@ -1,8 +1,8 @@ import type { ReactTestInstance } from 'react-test-renderer'; import { findAll } from '../helpers/findAll'; import { matches, TextMatch, TextMatchOptions } from '../matches'; +import { matchTextContent } from '../helpers/matchers/matchTextContent'; import { makeQueries } from './makeQueries'; -import { getNodeByText } from './text'; import type { FindAllByQuery, FindByQuery, @@ -40,7 +40,7 @@ const matchAccessibilityLabelledByText = ( .findAll((node) => matches(nativeID, node.props.nativeID, normalizer, exact) ) - .some((node) => node.findAll((n) => getNodeByText(n, text)).length > 0); + .some((node) => node.findAll((n) => matchTextContent(n, text)).length > 0); }; const matchAccessibilityLabel = ( From 805de760f84ca19f197e21beeb9bcf50d39c5172 Mon Sep 17 00:00:00 2001 From: Patryk Fryda Date: Tue, 8 Nov 2022 08:50:31 +0100 Subject: [PATCH 03/12] test: improve getByLabelText tests --- src/matches.ts | 2 +- src/queries/__tests__/labelText.test.tsx | 37 ++++++++++++++---------- src/queries/labelText.ts | 2 +- src/queries/testId.ts | 2 +- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/matches.ts b/src/matches.ts index a2c22225a..ed9985986 100644 --- a/src/matches.ts +++ b/src/matches.ts @@ -8,7 +8,7 @@ export type TextMatchOptions = { export function matches( matcher: TextMatch, - text: string, + text: string | undefined, normalizer: NormalizerFn = getDefaultNormalizer(), exact: boolean = true ): boolean { diff --git a/src/queries/__tests__/labelText.test.tsx b/src/queries/__tests__/labelText.test.tsx index 42bfde552..b6ccee872 100644 --- a/src/queries/__tests__/labelText.test.tsx +++ b/src/queries/__tests__/labelText.test.tsx @@ -6,8 +6,6 @@ const BUTTON_LABEL = 'cool button'; const BUTTON_HINT = 'click this button'; const TEXT_LABEL = 'cool text'; const TEXT_HINT = 'static text'; -const INPUT_LABEL = 'cool input'; -const INPUT_LABELLED_BY = 'formLabel'; // Little hack to make all the methods happy with type const NO_MATCHES_TEXT: any = 'not-existent-element'; @@ -43,15 +41,6 @@ const Section = () => ( ); -const FormInput = () => ( - <> - - {INPUT_LABEL} - - - -); - test('getByLabelText, queryByLabelText, findByLabelText', async () => { const { getByLabelText, queryByLabelText, findByLabelText } = render(
@@ -176,12 +165,28 @@ test('byLabelText queries support hidden option', () => { `"Unable to find an element with accessibilityLabel: hidden"` ); }); + test('getByLabelText supports accessibilityLabelledBy', async () => { - const { getByLabelText, queryByLabelText } = render(); + const { getByLabelText, getByTestId } = render( + <> + Label for input + + + ); + expect(getByLabelText('Label for input')).toEqual(getByTestId('textInput')); + expect(getByLabelText(/input/)).toEqual(getByTestId('textInput')); +}); - expect(getByLabelText(INPUT_LABEL).props.accessibilityLabelledBy).toEqual( - INPUT_LABELLED_BY +test('getByLabelText supports nested accessibilityLabelledBy', async () => { + const { getByLabelText, getByTestId } = render( + <> + + Label for input + + + ); - const textInput = queryByLabelText(/input/g); - expect(textInput?.props.accessibilityLabelledBy).toEqual(INPUT_LABELLED_BY); + + expect(getByLabelText('Label for input')).toEqual(getByTestId('textInput')); + expect(getByLabelText(/input/)).toEqual(getByTestId('textInput')); }); diff --git a/src/queries/labelText.ts b/src/queries/labelText.ts index 75f3d4d54..bd94e6d57 100644 --- a/src/queries/labelText.ts +++ b/src/queries/labelText.ts @@ -38,7 +38,7 @@ const matchAccessibilityLabelledByText = ( return rootInstance .findAll((node) => - matches(nativeID, node.props.nativeID, normalizer, exact) + matches(nativeID, node.props?.nativeID, normalizer, exact) ) .some((node) => node.findAll((n) => matchTextContent(n, text)).length > 0); }; diff --git a/src/queries/testId.ts b/src/queries/testId.ts index 3e7977d9f..441d0cf8a 100644 --- a/src/queries/testId.ts +++ b/src/queries/testId.ts @@ -20,7 +20,7 @@ const getNodeByTestId = ( options: TextMatchOptions = {} ) => { const { exact, normalizer } = options; - return matches(testID, node.props.testID, normalizer, exact); + return matches(testID, node.props?.testID, normalizer, exact); }; const queryAllByTestId = ( From 771f3a5e1b6dacd1abd7df87b93c1d5e035ca569 Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Wed, 30 Nov 2022 17:18:24 +0100 Subject: [PATCH 04/12] refactor: extract matchLabelText --- src/helpers/matchers/matchLabelText.ts | 47 ++++++++++++++++++ src/helpers/matchers/matchTextContent.ts | 11 ----- src/queries/labelText.ts | 61 +++--------------------- src/queries/text.ts | 19 ++++++-- 4 files changed, 68 insertions(+), 70 deletions(-) create mode 100644 src/helpers/matchers/matchLabelText.ts diff --git a/src/helpers/matchers/matchLabelText.ts b/src/helpers/matchers/matchLabelText.ts new file mode 100644 index 000000000..83a8ef068 --- /dev/null +++ b/src/helpers/matchers/matchLabelText.ts @@ -0,0 +1,47 @@ +import { ReactTestInstance } from 'react-test-renderer'; +import { matches, TextMatch, TextMatchOptions } from '../../matches'; +import { matchTextContent } from './matchTextContent'; + +export function matchLabelText( + rootInstance: ReactTestInstance, + node: ReactTestInstance, + text: TextMatch, + options: TextMatchOptions = {} +) { + return ( + matchAccessibilityLabel(node, text, options) || + matchAccessibilityLabelledBy( + rootInstance, + node.props.accessibilityLabelledBy, + text, + options + ) + ); +} + +export function matchAccessibilityLabel( + node: ReactTestInstance, + text: TextMatch, + options: TextMatchOptions +) { + const { exact, normalizer } = options; + return matches(text, node.props.accessibilityLabel, normalizer, exact); +} + +export function matchAccessibilityLabelledBy( + rootInstance: ReactTestInstance, + nativeID: string | undefined, + text: TextMatch, + options: TextMatchOptions +) { + if (!nativeID) { + return false; + } + + const { exact, normalizer } = options; + return rootInstance + .findAll((node) => + matches(nativeID, node.props?.nativeID, normalizer, exact) + ) + .some((node) => matchTextContent(node, text)); +} diff --git a/src/helpers/matchers/matchTextContent.ts b/src/helpers/matchers/matchTextContent.ts index 6dc3556f1..4c025e6ac 100644 --- a/src/helpers/matchers/matchTextContent.ts +++ b/src/helpers/matchers/matchTextContent.ts @@ -1,10 +1,6 @@ -import { Text } from 'react-native'; import type { ReactTestInstance } from 'react-test-renderer'; -import { getConfig } from '../../config'; import { matches, TextMatch, TextMatchOptions } from '../../matches'; -import { filterNodeByType } from '../filterNodeByType'; import { getTextContent } from '../getTextContent'; -import { getHostComponentNames } from '../host-component-names'; /** * Matches the given node's text content against string or regex matcher. @@ -18,13 +14,6 @@ export function matchTextContent( text: TextMatch, options: TextMatchOptions = {} ) { - const textType = getConfig().useBreakingChanges - ? getHostComponentNames().text - : Text; - if (!filterNodeByType(node, textType)) { - return false; - } - const textContent = getTextContent(node); const { exact, normalizer } = options; return matches(text, textContent, normalizer, exact); diff --git a/src/queries/labelText.ts b/src/queries/labelText.ts index bd94e6d57..7b5fba156 100644 --- a/src/queries/labelText.ts +++ b/src/queries/labelText.ts @@ -1,7 +1,7 @@ import type { ReactTestInstance } from 'react-test-renderer'; import { findAll } from '../helpers/findAll'; -import { matches, TextMatch, TextMatchOptions } from '../matches'; -import { matchTextContent } from '../helpers/matchers/matchTextContent'; +import { TextMatch, TextMatchOptions } from '../matches'; +import { matchLabelText } from '../helpers/matchers/matchLabelText'; import { makeQueries } from './makeQueries'; import type { FindAllByQuery, @@ -15,66 +15,17 @@ import { CommonQueryOptions } from './options'; type ByLabelTextOptions = CommonQueryOptions & TextMatchOptions; -const getNodeByLabelText = ( - node: ReactTestInstance, - text: TextMatch, - options: TextMatchOptions -) => { - const { exact, normalizer } = options; - return matches(text, node.props.accessibilityLabel, normalizer, exact); -}; - -const matchAccessibilityLabelledByText = ( - rootInstance: ReactTestInstance, - nativeID: string | undefined, - text: TextMatch, - options: TextMatchOptions -) => { - if (!nativeID) { - return false; - } - - const { exact, normalizer } = options; - - return rootInstance - .findAll((node) => - matches(nativeID, node.props?.nativeID, normalizer, exact) - ) - .some((node) => node.findAll((n) => matchTextContent(n, text)).length > 0); -}; - -const matchAccessibilityLabel = ( - rootInstance: ReactTestInstance, - node: ReactTestInstance, - text: TextMatch, - options: TextMatchOptions = {} -) => { - return ( - getNodeByLabelText(node, text, options) || - matchAccessibilityLabelledByText( - rootInstance, - node.props.accessibilityLabelledBy, - text, - options - ) - ); -}; - -const queryAllByLabelText = ( - instance: ReactTestInstance -): (( - text: TextMatch, - queryOptions?: ByLabelTextOptions -) => Array) => - function queryAllByLabelTextFn(text, queryOptions) { +function queryAllByLabelText(instance: ReactTestInstance) { + return (text: TextMatch, queryOptions?: ByLabelTextOptions) => { return findAll( instance, (node) => typeof node.type === 'string' && - matchAccessibilityLabel(instance, node, text, queryOptions), + matchLabelText(instance, node, text, queryOptions), queryOptions ); }; +} const getMultipleError = (labelText: TextMatch) => `Found multiple elements with accessibilityLabel: ${String(labelText)} `; diff --git a/src/queries/text.ts b/src/queries/text.ts index ef34333a9..119f4b676 100644 --- a/src/queries/text.ts +++ b/src/queries/text.ts @@ -1,6 +1,7 @@ import type { ReactTestInstance } from 'react-test-renderer'; import { Text } from 'react-native'; import { findAll } from '../helpers/findAll'; +import { filterNodeByType } from '../helpers/filterNodeByType'; import { matchTextContent } from '../helpers/matchers/matchTextContent'; import { TextMatch, TextMatchOptions } from '../matches'; import { @@ -18,6 +19,7 @@ import type { QueryByQuery, } from './makeQueries'; import type { CommonQueryOptions } from './options'; +import { getHostComponentNames } from '../helpers/host-component-names'; type ByTextOptions = CommonQueryOptions & TextMatchOptions; @@ -47,10 +49,19 @@ const queryAllByText = ( } // vNext version: returns host Text - return findAll(instance, (node) => matchTextContent(node, text, options), { - ...options, - matchDeepestOnly: true, - }); + const textType = getConfig().useBreakingChanges + ? getHostComponentNames().text + : Text; + + return findAll( + instance, + (node) => node.type === textType && matchTextContent(node, text, options), + { + ...options, + matchDeepestOnly: true, + } + ); + }; const getMultipleError = (text: TextMatch) => From d867c6eb31c72768f459902a74e158861879ea93 Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Wed, 30 Nov 2022 18:13:05 +0100 Subject: [PATCH 05/12] refactor: tweaks --- src/helpers/matchers/matchLabelText.ts | 39 ++++++++++++++------------ website/docs/Queries.md | 5 ++-- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/helpers/matchers/matchLabelText.ts b/src/helpers/matchers/matchLabelText.ts index 83a8ef068..bfdcb0209 100644 --- a/src/helpers/matchers/matchLabelText.ts +++ b/src/helpers/matchers/matchLabelText.ts @@ -1,47 +1,50 @@ import { ReactTestInstance } from 'react-test-renderer'; import { matches, TextMatch, TextMatchOptions } from '../../matches'; +import { findAll } from '../findAll'; import { matchTextContent } from './matchTextContent'; export function matchLabelText( - rootInstance: ReactTestInstance, - node: ReactTestInstance, + root: ReactTestInstance, + element: ReactTestInstance, text: TextMatch, options: TextMatchOptions = {} ) { return ( - matchAccessibilityLabel(node, text, options) || + matchAccessibilityLabel(element, text, options) || matchAccessibilityLabelledBy( - rootInstance, - node.props.accessibilityLabelledBy, + root, + element.props.accessibilityLabelledBy, text, options ) ); } -export function matchAccessibilityLabel( - node: ReactTestInstance, +function matchAccessibilityLabel( + element: ReactTestInstance, text: TextMatch, options: TextMatchOptions ) { const { exact, normalizer } = options; - return matches(text, node.props.accessibilityLabel, normalizer, exact); + return matches(text, element.props.accessibilityLabel, normalizer, exact); } -export function matchAccessibilityLabelledBy( - rootInstance: ReactTestInstance, - nativeID: string | undefined, +function matchAccessibilityLabelledBy( + root: ReactTestInstance, + nativeId: string | undefined, text: TextMatch, options: TextMatchOptions ) { - if (!nativeID) { + if (!nativeId) { return false; } - const { exact, normalizer } = options; - return rootInstance - .findAll((node) => - matches(nativeID, node.props?.nativeID, normalizer, exact) - ) - .some((node) => matchTextContent(node, text)); + return ( + findAll( + root, + (element) => + element.props?.nativeID === nativeId && + matchTextContent(element, text, options) + ).length > 0 + ); } diff --git a/website/docs/Queries.md b/website/docs/Queries.md index 5e4dfcc70..ddacabeac 100644 --- a/website/docs/Queries.md +++ b/website/docs/Queries.md @@ -213,9 +213,8 @@ getByLabelText( ``` Returns a `ReactTestInstance` with matching label: - -- by matching `accessibilityLabel` prop -- or by matching text content of text view referenced by `accessibilityLabelledBy` prop +- either by matching [`accessibilityLabel`](https://reactnative.dev/docs/accessibility#accessibilitylabel) prop +- or by matching text content of view referenced by [`accessibilityLabelledBy`](https://reactnative.dev/docs/accessibility#accessibilitylabelledby-android) prop ```jsx import { render, screen } from '@testing-library/react-native'; From fec9c19f06f8faab8d47d3864c43a50636b336d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Jastrze=CC=A8bski?= Date: Sat, 14 Jan 2023 23:26:59 +0000 Subject: [PATCH 06/12] refactor: code review changes --- src/helpers/matchers/matchLabelText.ts | 7 ++++--- src/matches.ts | 2 +- src/queries/__tests__/labelText.test.tsx | 11 ++++++----- src/queries/testId.ts | 10 +++++----- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/helpers/matchers/matchLabelText.ts b/src/helpers/matchers/matchLabelText.ts index bfdcb0209..cc7c1d2d9 100644 --- a/src/helpers/matchers/matchLabelText.ts +++ b/src/helpers/matchers/matchLabelText.ts @@ -42,9 +42,10 @@ function matchAccessibilityLabelledBy( return ( findAll( root, - (element) => - element.props?.nativeID === nativeId && - matchTextContent(element, text, options) + (node) => + typeof node.type === 'string' && + node.props?.nativeID === nativeId && + matchTextContent(node, text, options) ).length > 0 ); } diff --git a/src/matches.ts b/src/matches.ts index ed9985986..a2c22225a 100644 --- a/src/matches.ts +++ b/src/matches.ts @@ -8,7 +8,7 @@ export type TextMatchOptions = { export function matches( matcher: TextMatch, - text: string | undefined, + text: string, normalizer: NormalizerFn = getDefaultNormalizer(), exact: boolean = true ): boolean { diff --git a/src/queries/__tests__/labelText.test.tsx b/src/queries/__tests__/labelText.test.tsx index b6ccee872..0a05c3716 100644 --- a/src/queries/__tests__/labelText.test.tsx +++ b/src/queries/__tests__/labelText.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { View, Text, TouchableOpacity, TextInput } from 'react-native'; +import { View, Text, TextInput, TouchableOpacity } from 'react-native'; import { render } from '../..'; const BUTTON_LABEL = 'cool button'; @@ -173,8 +173,9 @@ test('getByLabelText supports accessibilityLabelledBy', async () => { ); - expect(getByLabelText('Label for input')).toEqual(getByTestId('textInput')); - expect(getByLabelText(/input/)).toEqual(getByTestId('textInput')); + + expect(getByLabelText('Label for input')).toBe(getByTestId('textInput')); + expect(getByLabelText(/input/)).toBe(getByTestId('textInput')); }); test('getByLabelText supports nested accessibilityLabelledBy', async () => { @@ -187,6 +188,6 @@ test('getByLabelText supports nested accessibilityLabelledBy', async () => { ); - expect(getByLabelText('Label for input')).toEqual(getByTestId('textInput')); - expect(getByLabelText(/input/)).toEqual(getByTestId('textInput')); + expect(getByLabelText('Label for input')).toBe(getByTestId('textInput')); + expect(getByLabelText(/input/)).toBe(getByTestId('textInput')); }); diff --git a/src/queries/testId.ts b/src/queries/testId.ts index 441d0cf8a..c33122b91 100644 --- a/src/queries/testId.ts +++ b/src/queries/testId.ts @@ -20,7 +20,7 @@ const getNodeByTestId = ( options: TextMatchOptions = {} ) => { const { exact, normalizer } = options; - return matches(testID, node.props?.testID, normalizer, exact); + return matches(testID, node.props.testID, normalizer, exact); }; const queryAllByTestId = ( @@ -30,13 +30,13 @@ const queryAllByTestId = ( queryOptions?: ByTestIdOptions ) => Array) => function queryAllByTestIdFn(testId, queryOptions) { - const results = findAll( + return findAll( instance, - (node) => getNodeByTestId(node, testId, queryOptions), + (node) => + typeof node.type === 'string' && + getNodeByTestId(node, testId, queryOptions), queryOptions ); - - return results.filter((element) => typeof element.type === 'string'); }; const getMultipleError = (testId: TextMatch) => From 09d892552de3e55f0066a9d9bda075c1cf0f6ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Jastrze=CC=A8bski?= Date: Sat, 14 Jan 2023 23:28:50 +0000 Subject: [PATCH 07/12] refactor: code review changes --- src/helpers/matchers/matchLabelText.ts | 2 +- src/queries/text.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/helpers/matchers/matchLabelText.ts b/src/helpers/matchers/matchLabelText.ts index cc7c1d2d9..8058f2904 100644 --- a/src/helpers/matchers/matchLabelText.ts +++ b/src/helpers/matchers/matchLabelText.ts @@ -44,7 +44,7 @@ function matchAccessibilityLabelledBy( root, (node) => typeof node.type === 'string' && - node.props?.nativeID === nativeId && + node.props.nativeID === nativeId && matchTextContent(node, text, options) ).length > 0 ); diff --git a/src/queries/text.ts b/src/queries/text.ts index 119f4b676..5f25dcfb5 100644 --- a/src/queries/text.ts +++ b/src/queries/text.ts @@ -61,7 +61,6 @@ const queryAllByText = ( matchDeepestOnly: true, } ); - }; const getMultipleError = (text: TextMatch) => From cdb70938796d6559d8aa2100d08d32f524130c99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Jastrze=CC=A8bski?= Date: Sun, 15 Jan 2023 22:34:05 +0000 Subject: [PATCH 08/12] chore: rebase on main --- package.json | 4 ++- src/queries/__tests__/text.breaking.test.tsx | 1 - src/queries/__tests__/text.test.tsx | 6 ++++- src/queries/text.ts | 27 +++++++++++--------- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 81e1aba96..71b5791f3 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,9 @@ }, "jest": { "preset": "./jest-preset", - "setupFilesAfterEnv": ["./jest-setup.ts"], + "setupFilesAfterEnv": [ + "./jest-setup.ts" + ], "testPathIgnorePatterns": [ "timerUtils", "examples/" diff --git a/src/queries/__tests__/text.breaking.test.tsx b/src/queries/__tests__/text.breaking.test.tsx index 322588ad7..eb243edd1 100644 --- a/src/queries/__tests__/text.breaking.test.tsx +++ b/src/queries/__tests__/text.breaking.test.tsx @@ -510,6 +510,5 @@ test('byText support hidden option', () => { test('byText should return host component', () => { const { getByText } = render(hello); - expect(getByText('hello').type).toBe('Text'); }); diff --git a/src/queries/__tests__/text.test.tsx b/src/queries/__tests__/text.test.tsx index a7d280d32..fcb4801f0 100644 --- a/src/queries/__tests__/text.test.tsx +++ b/src/queries/__tests__/text.test.tsx @@ -8,6 +8,7 @@ import { TextInput, } from 'react-native'; import { render, getDefaultNormalizer, within } from '../..'; +import { getConfig } from '../../config'; test('byText matches simple text', () => { const { getByText } = render(Hello World); @@ -504,7 +505,10 @@ test('byText support hidden option', () => { }); test('byText should return composite Text', () => { + const textType = getConfig().useBreakingChanges + ? getHostComponentNames().text + : Text; + console.log('BB', getConfig().useBreakingChanges, textType); const { getByText } = render(hello); - expect(getByText('hello').type).toBe(Text); }); diff --git a/src/queries/text.ts b/src/queries/text.ts index 5f25dcfb5..266a429ae 100644 --- a/src/queries/text.ts +++ b/src/queries/text.ts @@ -1,14 +1,15 @@ import type { ReactTestInstance } from 'react-test-renderer'; import { Text } from 'react-native'; -import { findAll } from '../helpers/findAll'; -import { filterNodeByType } from '../helpers/filterNodeByType'; -import { matchTextContent } from '../helpers/matchers/matchTextContent'; -import { TextMatch, TextMatchOptions } from '../matches'; +import { getConfig, resetToDefaults } from '../config'; import { getCompositeParentOfType, isHostElementForType, } from '../helpers/component-tree'; -import { getConfig } from '../config'; +import { filterNodeByType } from '../helpers/filterNodeByType'; +import { findAll } from '../helpers/findAll'; +import { getHostComponentNames } from '../helpers/host-component-names'; +import { matchTextContent } from '../helpers/matchers/matchTextContent'; +import { TextMatch, TextMatchOptions } from '../matches'; import { makeQueries } from './makeQueries'; import type { FindAllByQuery, @@ -19,7 +20,10 @@ import type { QueryByQuery, } from './makeQueries'; import type { CommonQueryOptions } from './options'; -import { getHostComponentNames } from '../helpers/host-component-names'; + +beforeEach(() => { + resetToDefaults(); +}); type ByTextOptions = CommonQueryOptions & TextMatchOptions; @@ -41,7 +45,8 @@ const queryAllByText = ( const results = findAll( baseInstance, - (node) => matchTextContent(node, text, options), + (node) => + filterNodeByType(node, Text) && matchTextContent(node, text, options), { ...options, matchDeepestOnly: true } ); @@ -49,13 +54,11 @@ const queryAllByText = ( } // vNext version: returns host Text - const textType = getConfig().useBreakingChanges - ? getHostComponentNames().text - : Text; - return findAll( instance, - (node) => node.type === textType && matchTextContent(node, text, options), + (node) => + filterNodeByType(node, getHostComponentNames().text) && + matchTextContent(node, text, options), { ...options, matchDeepestOnly: true, From 9b57f1374286aa3e26d165d38355dcca99652370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Jastrze=CC=A8bski?= Date: Sun, 15 Jan 2023 22:37:19 +0000 Subject: [PATCH 09/12] chore: fix lint --- src/queries/__tests__/text.test.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/queries/__tests__/text.test.tsx b/src/queries/__tests__/text.test.tsx index fcb4801f0..27f9eb82a 100644 --- a/src/queries/__tests__/text.test.tsx +++ b/src/queries/__tests__/text.test.tsx @@ -8,7 +8,6 @@ import { TextInput, } from 'react-native'; import { render, getDefaultNormalizer, within } from '../..'; -import { getConfig } from '../../config'; test('byText matches simple text', () => { const { getByText } = render(Hello World); @@ -505,10 +504,6 @@ test('byText support hidden option', () => { }); test('byText should return composite Text', () => { - const textType = getConfig().useBreakingChanges - ? getHostComponentNames().text - : Text; - console.log('BB', getConfig().useBreakingChanges, textType); const { getByText } = render(hello); expect(getByText('hello').type).toBe(Text); }); From 1586bf4434b8ef2a0bfb69d68ba44259403d2fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Jastrze=CC=A8bski?= Date: Wed, 18 Jan 2023 10:00:44 +0000 Subject: [PATCH 10/12] chore: fix test code in files --- src/queries/text.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/queries/text.ts b/src/queries/text.ts index 266a429ae..9f61a76ca 100644 --- a/src/queries/text.ts +++ b/src/queries/text.ts @@ -21,10 +21,6 @@ import type { } from './makeQueries'; import type { CommonQueryOptions } from './options'; -beforeEach(() => { - resetToDefaults(); -}); - type ByTextOptions = CommonQueryOptions & TextMatchOptions; const queryAllByText = ( From 21acc57a871a89d76eba5cbfd756ef8eaa88fada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Jastrze=CC=A8bski?= Date: Wed, 18 Jan 2023 12:04:35 +0000 Subject: [PATCH 11/12] chore: fix lint --- src/queries/text.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/queries/text.ts b/src/queries/text.ts index 9f61a76ca..744d88a04 100644 --- a/src/queries/text.ts +++ b/src/queries/text.ts @@ -1,6 +1,6 @@ import type { ReactTestInstance } from 'react-test-renderer'; import { Text } from 'react-native'; -import { getConfig, resetToDefaults } from '../config'; +import { getConfig } from '../config'; import { getCompositeParentOfType, isHostElementForType, From ccbe912d5218c20760bae13fe2b862365187fa1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Jastrze=CC=A8bski?= Date: Mon, 23 Jan 2023 22:49:37 +0000 Subject: [PATCH 12/12] chore: fix ts error due to missing RN typing --- src/queries/__tests__/labelText.test.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/queries/__tests__/labelText.test.tsx b/src/queries/__tests__/labelText.test.tsx index 0a05c3716..07aa3fccc 100644 --- a/src/queries/__tests__/labelText.test.tsx +++ b/src/queries/__tests__/labelText.test.tsx @@ -170,6 +170,7 @@ test('getByLabelText supports accessibilityLabelledBy', async () => { const { getByLabelText, getByTestId } = render( <> Label for input + {/* @ts-expect-error: waiting for RN 0.71.2 to fix incorrectly omitted `accessibilityLabelledBy` typedef. */} ); @@ -184,6 +185,7 @@ test('getByLabelText supports nested accessibilityLabelledBy', async () => { Label for input + {/* @ts-expect-error: waiting for RN 0.71.2 to fix incorrectly omitted `accessibilityLabelledBy` typedef. */} );