feat: add findBy* queries (#304)

* Basic async findBy queries

* Refactored findBy queries to be built with makeFindQuery

* findBy queries for A11y selectors

* Custom findByTestId implementation that avoids current getByTestId issues

* Fixed prettier issue

* Updates Queries.md with findBy queries

* Trying to fix test timeout error appearing only on CI

* Code review changes

* Added typescript types & tests

* prettier did reformat some code arround

* Removed export of GetByAPI, QueryByAPI and FindByAPI interfaces in TS

* Reversed prettier run on typings

* Added overlapping pieces with `within` operator

* Small cleanup

* Update website/docs/Queries.md

* Moved async/await tests to the end of test methods

Co-authored-by: Michał Pierzchała <thymikee@gmail.com>
This commit is contained in:
Maciej Jastrzebski
2020-05-15 09:52:33 +02:00
committed by GitHub
parent 1809825313
commit ab34712133
13 changed files with 609 additions and 162 deletions
+123 -106
View File
@@ -121,6 +121,57 @@ const queryAllByDisplayValueRegExp: Array<
ReactTestInstance
> = tree.queryAllByDisplayValue(/View/g);
// findBy API tests
const findBy: Promise<ReactTestInstance>[] = [
tree.findByText('View'),
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.findByDisplayValue('my value'),
tree.findByDisplayValue('my value', { timeout: 10, interval: 10 }),
tree.findByDisplayValue(/value/g),
tree.findByDisplayValue(/value/g, { timeout: 10, interval: 10 }),
tree.findByTestId('test-id'),
tree.findByTestId('test-id', { timeout: 10, interval: 10 }),
tree.findByA11yLabel('label'),
tree.findByA11yLabel('label', { timeout: 10, interval: 10 }),
tree.findByA11yHint('label'),
tree.findByA11yHint('label', { timeout: 10, interval: 10 }),
tree.findByA11yRole('button'),
tree.findByA11yRole('button', { timeout: 10, interval: 10 }),
tree.findByA11yState({ busy: true }),
tree.findByA11yState({ busy: true }, { timeout: 10, interval: 10 }),
tree.findByA11yValue({ min: 10 }),
tree.findByA11yValue({ min: 10 }, { timeout: 10, interval: 10 }),
];
const findAllBy: Promise<ReactTestInstance[]>[] = [
tree.findAllByText('View'),
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.findAllByDisplayValue('View'),
tree.findAllByDisplayValue('View', { timeout: 10, interval: 10 }),
tree.findAllByDisplayValue(/View/g),
tree.findAllByDisplayValue(/View/g, { timeout: 10, interval: 10 }),
tree.findAllByTestId('test-id'),
tree.findAllByTestId('test-id', { timeout: 10, interval: 10 }),
tree.findAllByA11yHint('label'),
tree.findAllByA11yHint('label', { timeout: 10, interval: 10 }),
tree.findAllByA11yState({ busy: true }),
tree.findAllByA11yState({ busy: true }, { timeout: 10, interval: 10 }),
tree.findAllByA11yValue({ min: 10 }),
tree.findAllByA11yValue({ min: 10 }, { timeout: 10, interval: 10 }),
];
// Accessibility queries
const getByA11yLabel: ReactTestInstance = tree.getByA11yLabel('label');
const getAllByA11yLabel: Array<ReactTestInstance> = tree.getAllByA11yLabel(
@@ -130,6 +181,7 @@ const queryByA11yLabel: ReactTestInstance = tree.queryByA11yLabel('label');
const queryAllByA11yLabel: Array<ReactTestInstance> = tree.queryAllByA11yLabel(
'label'
);
const getByA11yHint: ReactTestInstance = tree.getByA11yHint('label');
const getAllByA11yHint: Array<ReactTestInstance> = tree.getAllByA11yHint(
'label'
@@ -138,6 +190,7 @@ const queryByA11yHint: ReactTestInstance = tree.queryByA11yHint('label');
const queryAllByA11yHint: Array<ReactTestInstance> = tree.queryAllByA11yHint(
'label'
);
const getByA11yRole: ReactTestInstance = tree.getByA11yRole('button');
const getAllByA11yRole: Array<ReactTestInstance> = tree.getAllByA11yRole(
'button'
@@ -146,6 +199,7 @@ const queryByA11yRole: ReactTestInstance = tree.queryByA11yRole('button');
const queryAllByA11yRole: Array<ReactTestInstance> = tree.queryAllByA11yRole(
'button'
);
const getByA11yStates: ReactTestInstance = tree.getByA11yStates('selected');
const getByA11yStatesArray: ReactTestInstance = tree.getByA11yStates(['selected']);
const getAllByA11yStates: Array<ReactTestInstance> = tree.getAllByA11yStates(
@@ -221,112 +275,75 @@ act(() => {
// within API
const instance: ReactTestInstance = tree.getByText('<View />');
const withinGetByText: ReactTestInstance = within(instance).getByText('Test');
const withinGetAllByText: ReactTestInstance[] = within(instance).getAllByText(
'Test'
);
const withinGetByDisplayValue: ReactTestInstance = within(
instance
).getByDisplayValue('Test');
const withinGetAllByDisplayValue: ReactTestInstance[] = within(
instance
).getAllByDisplayValue('Test');
const withinGetByPlaceholder: ReactTestInstance = within(
instance
).getByPlaceholder('Test');
const withinGetAllByPlaceholder: ReactTestInstance[] = within(
instance
).getAllByPlaceholder('Test');
const withinGetByTestId: ReactTestInstance = within(instance).getByTestId(
'Test'
);
const withinGetAllByTestId: ReactTestInstance[] = within(
instance
).getAllByTestId('Test');
const withinQueryByText: ReactTestInstance | null = within(
instance
).queryByText('Test');
const withinQueryAllByText: ReactTestInstance[] = within(
instance
).queryAllByText('Test');
const withinQueryByDisplayValue: ReactTestInstance | null = within(
instance
).queryByDisplayValue('Test');
const withinQueryAllByDisplayValue: ReactTestInstance[] = within(
instance
).queryAllByDisplayValue('Test');
const withinQueryByPlaceholder: ReactTestInstance | null = within(
instance
).queryByPlaceholder('Test');
const withinQueryAllByPlaceholder: ReactTestInstance[] = within(
instance
).queryAllByPlaceholder('Test');
const withinQueryByTestId: ReactTestInstance | null = within(
instance
).queryByTestId('Test');
const withinQueryAllByTestId: ReactTestInstance[] = within(
instance
).queryAllByTestId('Test');
const withinGet: Array<ReactTestInstance> = [
within(instance).getByText('Test'),
within(instance).getByDisplayValue('Test'),
within(instance).getByPlaceholder('Test'),
within(instance).getByTestId('Test'),
within(instance).getByA11yLabel('Test'),
within(instance).getByA11yHint('Test'),
within(instance).getByA11yRole('button'),
within(instance).getByA11yState({ busy: true }),
within(instance).getByA11yValue({ min: 10 }),
];
const withinGetByA11yLabel: ReactTestInstance = within(instance).getByA11yLabel(
'Test'
);
const withinGetAllByA11yLabel: ReactTestInstance[] = within(
instance
).getAllByA11yLabel('Test');
const withinGetByA11yHint: ReactTestInstance = within(instance).getByA11yHint(
'Test'
);
const withinGetAllByA11yHint: ReactTestInstance[] = within(
instance
).getAllByA11yHint('Test');
const withinGetByA11yRole: ReactTestInstance = within(instance).getByA11yRole(
'button'
);
const withinGetAllByA11yRole: ReactTestInstance[] = within(
instance
).getAllByA11yRole('button');
const withinGetByA11yState: ReactTestInstance = within(
instance
).getByA11yState({ busy: true });
const withinGetAllByA11yState: ReactTestInstance[] = within(
instance
).getAllByA11yState({ busy: true });
const withinGetByA11yValue: ReactTestInstance = within(
instance
).getByA11yValue({ min: 10 });
const withinGetAllByA11yValue: ReactTestInstance[] = within(
instance
).getAllByA11yValue({ min: 10 });
const withinGetAll: Array<ReactTestInstance[]> = [
within(instance).getAllByText('Test'),
within(instance).getAllByDisplayValue('Test'),
within(instance).getAllByPlaceholder('Test'),
within(instance).getAllByTestId('Test'),
within(instance).getAllByA11yLabel('Test'),
within(instance).getAllByA11yHint('Test'),
within(instance).getAllByA11yRole('button'),
within(instance).getAllByA11yState({ busy: true }),
within(instance).getAllByA11yValue({ min: 10 }),
];
const withinQueryByA11yLabel: ReactTestInstance | null = within(
instance
).queryByA11yLabel('Test');
const withinQueryAllByA11yLabel: ReactTestInstance[] = within(
instance
).queryAllByA11yLabel('Test');
const withinQueryByA11yHint: ReactTestInstance | null = within(
instance
).queryByA11yHint('Test');
const withinQueryAllByA11yHint: ReactTestInstance[] = within(
instance
).queryAllByA11yHint('Test');
const withinQueryByA11yRole: ReactTestInstance | null = within(
instance
).queryByA11yRole('button');
const withinQueryAllByA11yRole: ReactTestInstance[] = within(
instance
).queryAllByA11yRole('button');
const withinQueryByA11yState: ReactTestInstance | null = within(
instance
).queryByA11yState({ busy: true });
const withinQueryAllByA11yState: ReactTestInstance[] = within(
instance
).queryAllByA11yState({ busy: true });
const withinQueryByA11yValue: ReactTestInstance | null = within(
instance
).queryByA11yValue({ min: 10 });
const withinQueryAllByA11yValue: ReactTestInstance[] = within(
instance
).queryAllByA11yValue({ min: 10 });
const withinQuery: Array<ReactTestInstance | null> = [
within(instance).queryByText('Test'),
within(instance).queryByDisplayValue('Test'),
within(instance).queryByPlaceholder('Test'),
within(instance).queryByTestId('Test'),
within(instance).queryByA11yLabel('Test'),
within(instance).queryByA11yHint('Test'),
within(instance).queryByA11yRole('button'),
within(instance).queryByA11yState({ busy: true }),
within(instance).queryByA11yValue({ min: 10 }),
];
const withinQueryAll: Array<ReactTestInstance[]> = [
within(instance).queryAllByText('Test'),
within(instance).queryAllByDisplayValue('Test'),
within(instance).queryAllByPlaceholder('Test'),
within(instance).queryAllByTestId('Test'),
within(instance).queryAllByA11yLabel('Test'),
within(instance).queryAllByA11yHint('Test'),
within(instance).queryAllByA11yRole('button'),
within(instance).queryAllByA11yState({ busy: true }),
within(instance).queryAllByA11yValue({ min: 10 }),
];
const withinFind: Promise<ReactTestInstance>[] = [
within(instance).findByText('Test'),
within(instance).findByDisplayValue('Test'),
within(instance).findByPlaceholder('Test'),
within(instance).findByTestId('Test'),
within(instance).findByA11yLabel('Test'),
within(instance).findByA11yHint('Test'),
within(instance).findByA11yRole('button'),
within(instance).findByA11yState({ busy: true }),
within(instance).findByA11yValue({ min: 10 }),
];
const withinFindAll: Promise<ReactTestInstance[]>[] = [
within(instance).findAllByText('Test'),
within(instance).findAllByDisplayValue('Test'),
within(instance).findAllByPlaceholder('Test'),
within(instance).findAllByTestId('Test'),
within(instance).findAllByA11yLabel('Test'),
within(instance).findAllByA11yHint('Test'),
within(instance).findAllByA11yRole('button'),
within(instance).findAllByA11yState({ busy: true }),
within(instance).findAllByA11yValue({ min: 10 }),
];
+86 -7
View File
@@ -2,7 +2,14 @@ import * as React from 'react';
import { AccessibilityState, AccessibilityStates, AccessibilityRole } from 'react-native';
import { ReactTestInstance, ReactTestRendererJSON } from 'react-test-renderer';
export interface GetByAPI {
type GetReturn = ReactTestInstance;
type GetAllReturn = Array<ReactTestInstance>;
type QueryReturn = ReactTestInstance | null;
type QueryAllReturn = Array<ReactTestInstance> | [];
type FindReturn = Promise<ReactTestInstance>;
type FindAllReturn = Promise<ReactTestInstance[]>;
interface GetByAPI {
getByName: (name: React.ReactType | string) => ReactTestInstance;
getByType: <P>(type: React.ComponentType<P>) => ReactTestInstance;
getByText: (text: string | RegExp) => ReactTestInstance;
@@ -28,7 +35,7 @@ export interface GetByAPI {
UNSAFE_getAllByProps: (props: Record<string, any>) => Array<ReactTestInstance>,
}
export interface QueryByAPI {
interface QueryByAPI {
queryByName: (name: React.ReactType | string) => ReactTestInstance | null;
queryByType: <P>(type: React.ComponentType<P>) => ReactTestInstance | null;
queryByText: (name: string | RegExp) => ReactTestInstance | null;
@@ -63,10 +70,42 @@ export interface QueryByAPI {
UNSAFE_queryAllByProps: (props: Record<string, any>) => Array<ReactTestInstance> | [],
}
type GetReturn = ReactTestInstance;
type GetAllReturn = Array<ReactTestInstance>;
type QueryReturn = ReactTestInstance | null;
type QueryAllReturn = Array<ReactTestInstance> | [];
export interface WaitForOptions {
timeout: number;
interval: number;
}
interface FindByAPI {
findByText: (
text: string | RegExp,
waitForOptions?: WaitForOptions
) => FindReturn;
findByPlaceholder: (
placeholder: string | RegExp,
waitForOptions?: WaitForOptions
) => FindReturn;
findByDisplayValue: (
value: string | RegExp,
waitForOptions?: WaitForOptions
) => FindReturn;
findByTestId: (testID: string, waitForOptions?: WaitForOptions) => FindReturn;
findAllByText: (
text: string | RegExp,
waitForOptions?: WaitForOptions
) => FindAllReturn;
findAllByPlaceholder: (
placeholder: string | RegExp,
waitForOptions?: WaitForOptions
) => FindAllReturn;
findAllByDisplayValue: (
value: string | RegExp,
waitForOptions?: WaitForOptions
) => FindAllReturn;
findAllByTestId: (
testID: string,
waitForOptions?: WaitForOptions
) => FindAllReturn;
}
// Not yet available in DefinitelyTyped
export type A11yValue = {
@@ -82,18 +121,42 @@ type A11yAPI = {
getAllByA11yLabel: (matcher: string | RegExp) => GetAllReturn,
queryByA11yLabel: (matcher: string | RegExp) => QueryReturn,
queryAllByA11yLabel: (matcher: string | RegExp) => QueryAllReturn,
findByA11yLabel: (
matcher: string | RegExp,
waitForOptions?: WaitForOptions
) => FindReturn;
findAllByA11yLabel: (
matcher: string | RegExp,
waitForOptions?: WaitForOptions
) => FindAllReturn;
// Hint
getByA11yHint: (matcher: string | RegExp) => GetReturn,
getAllByA11yHint: (matcher: string | RegExp) => GetAllReturn,
queryByA11yHint: (matcher: string | RegExp) => QueryReturn,
queryAllByA11yHint: (matcher: string | RegExp) => QueryAllReturn,
findByA11yHint: (
matcher: string | RegExp,
waitForOptions?: WaitForOptions
) => FindReturn;
findAllByA11yHint: (
matcher: string | RegExp,
waitForOptions?: WaitForOptions
) => FindAllReturn;
// Role
getByA11yRole: (matcher: AccessibilityRole | RegExp) => GetReturn,
getAllByA11yRole: (matcher: AccessibilityRole | RegExp) => GetAllReturn,
queryByA11yRole: (matcher: AccessibilityRole | RegExp) => QueryReturn,
queryAllByA11yRole: (matcher: AccessibilityRole | RegExp) => QueryAllReturn,
findByA11yRole: (
matcher: AccessibilityRole | RegExp,
waitForOptions?: WaitForOptions
) => FindReturn;
findAllByA11yRole: (
matcher: AccessibilityRole | RegExp,
waitForOptions?: WaitForOptions
) => FindAllReturn;
// States
getByA11yStates: (matcher: AccessibilityStates | Array<AccessibilityStates>) => GetReturn,
@@ -106,12 +169,28 @@ type A11yAPI = {
getAllByA11yState: (matcher: AccessibilityState) => GetAllReturn,
queryByA11yState: (matcher: AccessibilityState) => QueryReturn,
queryAllByA11yState: (matcher: AccessibilityState) => QueryAllReturn,
findByA11yState: (
matcher: AccessibilityState,
waitForOptions?: WaitForOptions
) => FindReturn;
findAllByA11yState: (
matcher: AccessibilityState,
waitForOptions?: WaitForOptions
) => FindAllReturn;
// Value
getByA11yValue: (matcher: A11yValue) => GetReturn,
getAllByA11yValue: (matcher: A11yValue) => GetAllReturn,
queryByA11yValue: (matcher: A11yValue) => QueryReturn,
queryAllByA11yValue: (matcher: A11yValue) => QueryAllReturn,
findByA11yValue: (
matcher: A11yValue,
waitForOptions?: WaitForOptions
) => FindReturn;
findAllByA11yValue: (
matcher: A11yValue,
waitForOptions?: WaitForOptions
) => FindAllReturn;
};
export interface Thenable {
@@ -123,7 +202,7 @@ export interface RenderOptions {
createNodeMock?: (element: React.ReactElement<any>) => any;
}
type Queries = GetByAPI & QueryByAPI & A11yAPI;
type Queries = GetByAPI & QueryByAPI & FindByAPI & A11yAPI;
export interface RenderAPI extends Queries {
update(nextElement: React.ReactElement<any>): void;