;
// Unsafe aliases
UNSAFE_getByType: (type: React.ComponentType
) => ReactTestInstance;
@@ -64,19 +67,22 @@ interface GetByAPI {
}
interface QueryByAPI {
- queryByText: (name: string | RegExp) => ReactTestInstance | null;
+ queryByText: (name: TextMatch, options?: TextMatchOptions) => ReactTestInstance | null;
queryByPlaceholderText: (
- placeholder: string | RegExp
+ placeholder: TextMatch,
+ options?: TextMatchOptions,
) => ReactTestInstance | null;
- queryByDisplayValue: (value: string | RegExp) => ReactTestInstance | null;
- queryByTestId: (testID: string | RegExp) => ReactTestInstance | null;
- queryAllByTestId: (testID: string | RegExp) => Array | [];
- queryAllByText: (text: string | RegExp) => Array | [];
+ queryByDisplayValue: (value: TextMatch, options?: TextMatchOptions) => ReactTestInstance | null;
+ queryByTestId: (testID: TextMatch) => ReactTestInstance | null;
+ queryAllByTestId: (testID: TextMatch) => Array | [];
+ queryAllByText: (text: TextMatch, options?: TextMatchOptions) => Array | [];
queryAllByPlaceholderText: (
- placeholder: string | RegExp
+ placeholder: TextMatch,
+ options?: TextMatchOptions,
) => Array | [];
queryAllByDisplayValue: (
- value: string | RegExp
+ value: TextMatch,
+ options?: TextMatchOptions,
) => Array | [];
// Unsafe aliases
@@ -126,32 +132,38 @@ interface QueryByAPI {
interface FindByAPI {
findByText: (
- text: string | RegExp,
- waitForOptions?: WaitForOptions
+ text: TextMatch,
+ waitForOptions?: WaitForOptions,
+ options?: TextMatchOptions,
) => FindReturn;
findByPlaceholderText: (
- placeholder: string | RegExp,
- waitForOptions?: WaitForOptions
+ placeholder: TextMatch,
+ waitForOptions?: WaitForOptions,
+ options?: TextMatchOptions,
) => FindReturn;
findByDisplayValue: (
- value: string | RegExp,
- waitForOptions?: WaitForOptions
+ value: TextMatch,
+ waitForOptions?: WaitForOptions,
+ options?: TextMatchOptions,
) => FindReturn;
- findByTestId: (testID: string | RegExp, waitForOptions?: WaitForOptions) => FindReturn;
+ findByTestId: (testID: TextMatch, waitForOptions?: WaitForOptions) => FindReturn;
findAllByText: (
- text: string | RegExp,
- waitForOptions?: WaitForOptions
+ text: TextMatch,
+ waitForOptions?: WaitForOptions,
+ options?: TextMatchOptions,
) => FindAllReturn;
findAllByPlaceholderText: (
- placeholder: string | RegExp,
- waitForOptions?: WaitForOptions
+ placeholder: TextMatch,
+ waitForOptions?: WaitForOptions,
+ options?: TextMatchOptions,
) => FindAllReturn;
findAllByDisplayValue: (
- value: string | RegExp,
- waitForOptions?: WaitForOptions
+ value: TextMatch,
+ waitForOptions?: WaitForOptions,
+ options?: TextMatchOptions,
) => FindAllReturn;
findAllByTestId: (
- testID: string | RegExp,
+ testID: TextMatch,
waitForOptions?: WaitForOptions
) => FindAllReturn;
}
@@ -166,54 +178,54 @@ export type A11yValue = {
type A11yAPI = {
// Label
- getByA11yLabel: (matcher: string | RegExp) => GetReturn;
- getByLabelText: (matcher: string | RegExp) => GetReturn;
- getAllByA11yLabel: (matcher: string | RegExp) => GetAllReturn;
- getAllByLabelText: (matcher: string | RegExp) => GetAllReturn;
- queryByA11yLabel: (matcher: string | RegExp) => QueryReturn;
- queryByLabelText: (matcher: string | RegExp) => QueryReturn;
- queryAllByA11yLabel: (matcher: string | RegExp) => QueryAllReturn;
- queryAllByLabelText: (matcher: string | RegExp) => QueryAllReturn;
+ getByA11yLabel: (matcher: TextMatch) => GetReturn;
+ getByLabelText: (matcher: TextMatch) => GetReturn;
+ getAllByA11yLabel: (matcher: TextMatch) => GetAllReturn;
+ getAllByLabelText: (matcher: TextMatch) => GetAllReturn;
+ queryByA11yLabel: (matcher: TextMatch) => QueryReturn;
+ queryByLabelText: (matcher: TextMatch) => QueryReturn;
+ queryAllByA11yLabel: (matcher: TextMatch) => QueryAllReturn;
+ queryAllByLabelText: (matcher: TextMatch) => QueryAllReturn;
findByA11yLabel: (
- matcher: string | RegExp,
+ matcher: TextMatch,
waitForOptions?: WaitForOptions
) => FindReturn;
findByLabelText: (
- matcher: string | RegExp,
+ matcher: TextMatch,
waitForOptions?: WaitForOptions
) => FindReturn;
findAllByA11yLabel: (
- matcher: string | RegExp,
+ matcher: TextMatch,
waitForOptions?: WaitForOptions
) => FindAllReturn;
findAllByLabelText: (
- matcher: string | RegExp,
+ matcher: TextMatch,
waitForOptions?: WaitForOptions
) => FindAllReturn;
// Hint
- getByA11yHint: (matcher: string | RegExp) => GetReturn;
- getByHintText: (matcher: string | RegExp) => GetReturn;
- getAllByA11yHint: (matcher: string | RegExp) => GetAllReturn;
- getAllByHintText: (matcher: string | RegExp) => GetAllReturn;
- queryByA11yHint: (matcher: string | RegExp) => QueryReturn;
- queryByHintText: (matcher: string | RegExp) => QueryReturn;
- queryAllByA11yHint: (matcher: string | RegExp) => QueryAllReturn;
- queryAllByHintText: (matcher: string | RegExp) => QueryAllReturn;
+ getByA11yHint: (matcher: TextMatch) => GetReturn;
+ getByHintText: (matcher: TextMatch) => GetReturn;
+ getAllByA11yHint: (matcher: TextMatch) => GetAllReturn;
+ getAllByHintText: (matcher: TextMatch) => GetAllReturn;
+ queryByA11yHint: (matcher: TextMatch) => QueryReturn;
+ queryByHintText: (matcher: TextMatch) => QueryReturn;
+ queryAllByA11yHint: (matcher: TextMatch) => QueryAllReturn;
+ queryAllByHintText: (matcher: TextMatch) => QueryAllReturn;
findByA11yHint: (
- matcher: string | RegExp,
+ matcher: TextMatch,
waitForOptions?: WaitForOptions
) => FindReturn;
findByHintText: (
- matcher: string | RegExp,
+ matcher: TextMatch,
waitForOptions?: WaitForOptions
) => FindReturn;
findAllByA11yHint: (
- matcher: string | RegExp,
+ matcher: TextMatch,
waitForOptions?: WaitForOptions
) => FindAllReturn;
findAllByHintText: (
- matcher: string | RegExp,
+ matcher: TextMatch,
waitForOptions?: WaitForOptions
) => FindAllReturn;
@@ -325,6 +337,16 @@ export declare const render: (
export declare const cleanup: () => void;
export declare const fireEvent: FireEventAPI;
+type NormalizerFn = (textToNormalize: string) => string;
+type NormalizerConfig = {
+ trim?: boolean,
+ collapseWhitespace?: boolean,
+};
+type TextMatchOptions = {
+ exact?: boolean,
+ normalizer?: NormalizerFn,
+};
+
type WaitForOptions = {
timeout?: number;
interval?: number;
@@ -350,6 +372,8 @@ export declare const getQueriesForElement: (
instance: ReactTestInstance
) => Queries;
+export declare const getDefaultNormalizer: (normalizerConfig: NormalizerConfig) => NormalizerFn;
+
/**
* @deprecated This function has been removed. Please use `waitFor` function.
*/
diff --git a/website/docs/Queries.md b/website/docs/Queries.md
index 43dfcdb82..c518e9b51 100644
--- a/website/docs/Queries.md
+++ b/website/docs/Queries.md
@@ -44,7 +44,7 @@ In order to properly use `findBy` and `findAllBy` queries you need at least Reac
_Note: most methods like this one return a [`ReactTestInstance`](https://reactjs.org/docs/test-renderer.html#testinstance) with following properties that you may be interested in:_
-```jsx
+```typescript
type ReactTestInstance = {
type: string | Function,
props: { [propName: string]: any },
@@ -53,6 +53,10 @@ type ReactTestInstance = {
};
```
+### Options
+
+Query first argument can be a **string** or a **regex**. Some queries accept optional argument which change string matching behaviour. See [TextMatch](api-queries#textmatch) for more info.
+
### `ByText`
> getByText, getAllByText, queryByText, queryAllByText, findByText, findAllByText
@@ -199,6 +203,91 @@ const { getByA11yValue } = render();
const element = getByA11yValue({ min: 40 });
```
+## TextMatch
+
+
+Several APIs accept a `TextMatch` which can be a `string` or `regex`.
+
+```typescript
+type TextMatchOptions = {
+ exact?: boolean;
+ normalizer?: (textToNormalize: string) => string;
+ trim?: boolean;
+ collapseWhitespace?: boolean;
+};
+```
+
+`exact` option defaults to `true` but if you want to search for a text slice or make text matching case-insensitive you can override it. That being said we advise you to use regex in more complex scenarios.
+
+### Normalization
+
+Before running any matching logic against text, it is automatically normalized. By default, normalization consists of trimming whitespace from the start and end of text, and collapsing multiple adjacent whitespace characters into a single space.
+
+If you want to prevent that normalization, or provide alternative normalization (e.g. to remove Unicode control characters), you can provide a `normalizer` function in the options object. This function will be given a string and is expected to return a normalized version of that string.
+
+:::info
+Specifying a value for `normalizer` replaces the built-in normalization, but you can call `getDefaultNormalizer` to obtain a built-in normalizer, either to adjust that normalization or to call it from your own normalizer.
+:::
+
+`getDefaultNormalizer` take options object which allows the selection of behaviour:
+
+- `trim`: Defaults to `true`. Trims leading and trailing whitespace.
+- `collapseWhitespace`: Defaults to `true`. Collapses inner whitespace (newlines, tabs repeated spaces) into a single space.
+
+#### Normalization Examples
+
+To perform a match against text without trimming:
+
+```typescript
+getByText(node, 'text', {
+ normalizer: getDefaultNormalizer({ trim: false }),
+});
+```
+
+To override normalization to remove some Unicode characters whilst keeping some (but not all) of the built-in normalization behavior:
+
+```typescript
+getByText(node, 'text', {
+ normalizer: (str) =>
+ getDefaultNormalizer({ trim: false })(str).replace(/[\u200E-\u200F]*/g, ''),
+});
+```
+
+### TextMatch Examples
+
+Given the following render:
+
+```jsx
+const { getByText } = render(Hello World);
+```
+
+Will **find a match**:
+
+```js
+// Matching a string:
+getByText('Hello World'); // full string match
+getByText('llo Worl', { exact: false }); // substring match
+getByText('hello world', { exact: false }); // ignore case-sensitivity
+
+// Matching a regex:
+getByText(/World/); // substring match
+getByText(/world/i); // substring match, ignore case
+getByText(/^hello world$/i); // full string match, ignore case-sensitivity
+getByText(/Hello W?oRlD/i); // advanced regex
+```
+
+Will **NOT find a match**
+
+```js
+// substring does not match
+getByText('llo Worl');
+// full string does not match
+getByText('Goodbye World');
+
+// case-sensitive regex with different case
+getByText(/hello world/);
+```
+
## Unit testing helpers
> Use sparingly and responsibly, escape hatches here