@testing-library/react-native 12.1.1 → 12.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.DS_Store +0 -0
- package/.codecov.yml +9 -0
- package/.eslintcache +1 -0
- package/.eslintignore +2 -0
- package/.eslintrc +19 -0
- package/.flowconfig +63 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +14 -0
- package/.github/ISSUE_TEMPLATE/question.md +9 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +10 -0
- package/.github/actions/setup-deps/action.yml +22 -0
- package/.github/actions/setup-website-deps/action.yml +22 -0
- package/.github/dependabot.yml +10 -0
- package/.github/workflows/deploy-website.yml +36 -0
- package/.github/workflows/example-apps.yml +25 -0
- package/.github/workflows/main.yml +103 -0
- package/.gitignore +11 -0
- package/.prettierrc.js +5 -0
- package/CODE_OF_CONDUCT.md +73 -0
- package/CONTRIBUTING.md +64 -0
- package/README.md +8 -7
- package/babel.config.js +22 -0
- package/build/act.js.map +1 -1
- package/build/cleanup.js.map +1 -1
- package/build/config.d.ts +1 -0
- package/build/config.js.map +1 -1
- package/build/fireEvent.d.ts +13 -5
- package/build/fireEvent.js +57 -48
- package/build/fireEvent.js.map +1 -1
- package/build/flush-micro-tasks.d.ts +19 -0
- package/build/flush-micro-tasks.js +36 -0
- package/build/flush-micro-tasks.js.map +1 -0
- package/build/helpers/accessiblity.js +3 -1
- package/build/helpers/accessiblity.js.map +1 -1
- package/build/helpers/component-tree.d.ts +0 -15
- package/build/helpers/component-tree.js +0 -45
- package/build/helpers/component-tree.js.map +1 -1
- package/build/helpers/deprecation.d.ts +1 -0
- package/build/helpers/deprecation.js +16 -0
- package/build/helpers/deprecation.js.map +1 -1
- package/build/helpers/errors.d.ts +0 -4
- package/build/helpers/errors.js +1 -25
- package/build/helpers/errors.js.map +1 -1
- package/build/helpers/findAll.js.map +1 -1
- package/build/helpers/format-default.js.map +1 -1
- package/build/helpers/format.js.map +1 -1
- package/build/helpers/host-component-names.js +4 -1
- package/build/helpers/host-component-names.js.map +1 -1
- package/build/helpers/matchers/matchLabelText.js.map +1 -1
- package/build/helpers/pointer-events.d.ts +9 -0
- package/build/helpers/pointer-events.js +25 -0
- package/build/helpers/pointer-events.js.map +1 -0
- package/build/helpers/stringValidation.js.map +1 -1
- package/build/helpers/timers.js.map +1 -1
- package/build/index.js +2 -2
- package/build/index.js.map +1 -1
- package/build/matches.js.map +1 -1
- package/build/pure.d.ts +1 -1
- package/build/pure.js.map +1 -1
- package/build/queries/a11yState.js.map +1 -1
- package/build/queries/a11yValue.js.map +1 -1
- package/build/queries/displayValue.js.map +1 -1
- package/build/queries/hintText.js.map +1 -1
- package/build/queries/labelText.js.map +1 -1
- package/build/queries/makeQueries.js.map +1 -1
- package/build/queries/placeholderText.js.map +1 -1
- package/build/queries/role.js.map +1 -1
- package/build/queries/testId.js.map +1 -1
- package/build/queries/text.js.map +1 -1
- package/build/queries/unsafeProps.js.map +1 -1
- package/build/render.d.ts +171 -12
- package/build/render.js +11 -4
- package/build/render.js.map +1 -1
- package/build/renderHook.d.ts +3 -6
- package/build/renderHook.js +4 -3
- package/build/renderHook.js.map +1 -1
- package/build/shallow.js.map +1 -1
- package/build/test-utils/events.d.ts +10 -0
- package/build/test-utils/events.js +27 -0
- package/build/test-utils/events.js.map +1 -0
- package/build/test-utils/index.d.ts +1 -0
- package/build/test-utils/index.js +17 -0
- package/build/test-utils/index.js.map +1 -0
- package/build/user-event/event-builder/common.d.ts +45 -0
- package/build/user-event/event-builder/common.js +58 -0
- package/build/user-event/event-builder/common.js.map +1 -0
- package/build/user-event/event-builder/index.d.ts +32 -0
- package/build/user-event/event-builder/index.js +12 -0
- package/build/user-event/event-builder/index.js.map +1 -0
- package/build/user-event/index.d.ts +9 -0
- package/build/user-event/index.js +16 -0
- package/build/user-event/index.js.map +1 -0
- package/build/user-event/press/constants.d.ts +2 -0
- package/build/user-event/press/constants.js +16 -0
- package/build/user-event/press/constants.js.map +1 -0
- package/build/user-event/press/index.d.ts +1 -0
- package/build/user-event/press/index.js +19 -0
- package/build/user-event/press/index.js.map +1 -0
- package/build/user-event/press/press.d.ts +7 -0
- package/build/user-event/press/press.js +106 -0
- package/build/user-event/press/press.js.map +1 -0
- package/build/user-event/press/utils/warnAboutRealTimers.d.ts +1 -0
- package/build/user-event/press/utils/warnAboutRealTimers.js +14 -0
- package/build/user-event/press/utils/warnAboutRealTimers.js.map +1 -0
- package/build/user-event/setup/index.d.ts +2 -0
- package/build/user-event/setup/index.js +13 -0
- package/build/user-event/setup/index.js.map +1 -0
- package/build/user-event/setup/setup.d.ts +39 -0
- package/build/user-event/setup/setup.js +56 -0
- package/build/user-event/setup/setup.js.map +1 -0
- package/build/user-event/type/index.d.ts +1 -0
- package/build/user-event/type/index.js +13 -0
- package/build/user-event/type/index.js.map +1 -0
- package/build/user-event/type/type.d.ts +3 -0
- package/build/user-event/type/type.js +18 -0
- package/build/user-event/type/type.js.map +1 -0
- package/build/user-event/utils/events.d.ts +9 -0
- package/build/user-event/utils/events.js +44 -0
- package/build/user-event/utils/events.js.map +1 -0
- package/build/user-event/utils/index.d.ts +2 -0
- package/build/user-event/utils/index.js +28 -0
- package/build/user-event/utils/index.js.map +1 -0
- package/build/user-event/utils/wait.d.ts +2 -0
- package/build/user-event/utils/wait.js +14 -0
- package/build/user-event/utils/wait.js.map +1 -0
- package/build/waitFor.js +3 -3
- package/build/waitFor.js.map +1 -1
- package/build/waitForElementToBeRemoved.js.map +1 -1
- package/examples/basic/.expo-shared/assets.json +4 -0
- package/examples/basic/.gitignore +14 -0
- package/examples/basic/App.tsx +20 -0
- package/examples/basic/README.md +11 -0
- package/examples/basic/__tests__/App.test.tsx +119 -0
- package/examples/basic/app.json +31 -0
- package/examples/basic/assets/adaptive-icon.png +0 -0
- package/examples/basic/assets/favicon.png +0 -0
- package/examples/basic/assets/icon.png +0 -0
- package/examples/basic/assets/splash.png +0 -0
- package/examples/basic/babel.config.js +6 -0
- package/examples/basic/components/Home.tsx +28 -0
- package/examples/basic/components/LoginForm.tsx +138 -0
- package/examples/basic/jest-setup.ts +7 -0
- package/examples/basic/jest.config.js +5 -0
- package/examples/basic/package.json +30 -0
- package/examples/basic/tsconfig.json +7 -0
- package/examples/react-navigation/README.md +14 -0
- package/examples/react-navigation/babel.config.js +4 -0
- package/examples/react-navigation/jest-setup.js +11 -0
- package/examples/react-navigation/jest.config.js +10 -0
- package/examples/react-navigation/package.json +31 -0
- package/examples/react-navigation/src/App.js +21 -0
- package/examples/react-navigation/src/DrawerNavigator.js +15 -0
- package/examples/react-navigation/src/DrawerNavigator.test.js +42 -0
- package/examples/react-navigation/src/NativeStackNavigator.js +15 -0
- package/examples/react-navigation/src/NativeStackNavigator.test.js +34 -0
- package/examples/react-navigation/src/StackNavigator.js +15 -0
- package/examples/react-navigation/src/StackNavigator.test.js +34 -0
- package/examples/react-navigation/src/TabNavigator.js +15 -0
- package/examples/react-navigation/src/TabNavigator.test.js +21 -0
- package/examples/react-navigation/src/screens/DetailsScreen.js +43 -0
- package/examples/react-navigation/src/screens/DetailsScreen.test.js +27 -0
- package/examples/react-navigation/src/screens/DrawerHomeScreen.js +26 -0
- package/examples/react-navigation/src/screens/HomeScreen.js +48 -0
- package/examples/react-navigation/src/screens/SettingsScreen.js +20 -0
- package/examples/react-navigation/src/test-utils.js +12 -0
- package/examples/redux/App.js +27 -0
- package/examples/redux/actions/todoActions.js +25 -0
- package/examples/redux/babel.config.js +6 -0
- package/examples/redux/components/AddTodo.js +73 -0
- package/examples/redux/components/AddTodo.test.js +27 -0
- package/examples/redux/components/TodoElem.js +25 -0
- package/examples/redux/components/TodoList.js +29 -0
- package/examples/redux/components/TodoList.test.js +34 -0
- package/examples/redux/index.js +8 -0
- package/examples/redux/jest-setup.js +2 -0
- package/examples/redux/jest.config.js +4 -0
- package/examples/redux/package.json +23 -0
- package/examples/redux/reducers/index.js +6 -0
- package/examples/redux/reducers/todoReducer.js +27 -0
- package/examples/redux/store.js +10 -0
- package/examples/redux/test-utils.js +11 -0
- package/experiments-app/.expo/README.md +15 -0
- package/experiments-app/.expo/devices.json +3 -0
- package/experiments-app/.expo/packager-info.json +9 -0
- package/experiments-app/.expo/settings.json +9 -0
- package/experiments-app/.gitignore +17 -0
- package/experiments-app/.prettierrc.js +5 -0
- package/experiments-app/app.json +30 -0
- package/experiments-app/assets/adaptive-icon.png +0 -0
- package/experiments-app/assets/favicon.png +0 -0
- package/experiments-app/assets/icon.png +0 -0
- package/experiments-app/assets/splash.png +0 -0
- package/experiments-app/babel.config.js +6 -0
- package/experiments-app/index.js +4 -0
- package/experiments-app/package.json +31 -0
- package/experiments-app/src/App.tsx +31 -0
- package/experiments-app/src/MainScreen.tsx +51 -0
- package/experiments-app/src/experiments.ts +17 -0
- package/experiments-app/src/screens/TextInputEventPropagation.tsx +54 -0
- package/experiments-app/src/screens/TextInputEvents.tsx +50 -0
- package/experiments-app/src/utils/helpers.ts +8 -0
- package/experiments-app/tsconfig.json +6 -0
- package/experiments-app/yarn.lock +6913 -0
- package/flow-typed/npm/jest_v26.x.x.js +1218 -0
- package/flow-typed/npm/react-test-renderer_v16.x.x.js +81 -0
- package/jest-setup.ts +10 -0
- package/package.json +6 -6
- package/renovate.json +19 -0
- package/scripts/test_react_17 +12 -0
- package/src/__tests__/__snapshots__/render-debug.test.tsx.snap +548 -0
- package/src/__tests__/__snapshots__/render.test.tsx.snap +39 -0
- package/src/__tests__/act.test.tsx +52 -0
- package/src/__tests__/auto-cleanup-skip.test.tsx +39 -0
- package/src/__tests__/auto-cleanup.test.tsx +50 -0
- package/src/__tests__/cleanup.test.tsx +26 -0
- package/src/__tests__/config.test.ts +55 -0
- package/src/__tests__/fireEvent-textInput.test.tsx +154 -0
- package/src/__tests__/fireEvent.test.tsx +485 -0
- package/src/__tests__/host-component-names.test.tsx +109 -0
- package/src/__tests__/host-text-nesting.test.tsx +90 -0
- package/src/__tests__/jest-native.test.tsx +84 -0
- package/src/__tests__/questionsBoard.test.tsx +62 -0
- package/src/__tests__/react-native-api.test.tsx +126 -0
- package/src/__tests__/render-debug.test.tsx +207 -0
- package/src/__tests__/render-stringValidation.test.tsx +157 -0
- package/src/__tests__/render.test.tsx +256 -0
- package/src/__tests__/renderHook.test.tsx +114 -0
- package/src/__tests__/screen.test.tsx +66 -0
- package/src/__tests__/timerUtils.ts +7 -0
- package/src/__tests__/timers.test.ts +27 -0
- package/src/__tests__/waitFor.test.tsx +327 -0
- package/src/__tests__/waitForElementToBeRemoved.test.tsx +151 -0
- package/src/__tests__/within.test.tsx +96 -0
- package/src/act.ts +86 -0
- package/src/cleanup.ts +15 -0
- package/src/config.ts +72 -0
- package/src/fireEvent.ts +163 -0
- package/src/flush-micro-tasks.ts +30 -0
- package/src/helpers/__tests__/accessiblity.test.tsx +373 -0
- package/src/helpers/__tests__/component-tree.test.tsx +226 -0
- package/src/helpers/__tests__/format-default.tsx +114 -0
- package/src/helpers/__tests__/getTextContent.test.tsx +49 -0
- package/src/helpers/__tests__/includeHiddenElements.test.tsx +39 -0
- package/src/helpers/__tests__/query-name.test.ts +10 -0
- package/src/helpers/__tests__/timers.test.ts +8 -0
- package/src/helpers/accessiblity.ts +108 -0
- package/src/helpers/component-tree.ts +89 -0
- package/src/helpers/debugDeep.ts +27 -0
- package/src/helpers/debugShallow.ts +22 -0
- package/src/helpers/deprecation.ts +53 -0
- package/src/helpers/errors.ts +66 -0
- package/src/helpers/filterNodeByType.ts +7 -0
- package/src/helpers/findAll.ts +68 -0
- package/src/helpers/format-default.ts +72 -0
- package/src/helpers/format.ts +47 -0
- package/src/helpers/getTextContent.ts +20 -0
- package/src/helpers/host-component-names.tsx +67 -0
- package/src/helpers/matchers/__tests__/matchArrayValue.test.ts +34 -0
- package/src/helpers/matchers/__tests__/matchObject.test.ts +37 -0
- package/src/helpers/matchers/__tests__/matchStringValue.test.ts +15 -0
- package/src/helpers/matchers/accessibilityState.ts +48 -0
- package/src/helpers/matchers/accessibilityValue.ts +24 -0
- package/src/helpers/matchers/matchArrayProp.ts +21 -0
- package/src/helpers/matchers/matchLabelText.ts +51 -0
- package/src/helpers/matchers/matchObjectProp.ts +25 -0
- package/src/helpers/matchers/matchStringProp.ts +23 -0
- package/src/helpers/matchers/matchTextContent.ts +20 -0
- package/src/helpers/pointer-events.ts +27 -0
- package/src/helpers/query-name.ts +4 -0
- package/src/helpers/stringValidation.ts +36 -0
- package/src/helpers/timers.ts +98 -0
- package/src/index.ts +33 -0
- package/src/matches.ts +49 -0
- package/src/pure.ts +25 -0
- package/src/queries/__tests__/a11yState.test.tsx +439 -0
- package/src/queries/__tests__/a11yValue.test.tsx +309 -0
- package/src/queries/__tests__/displayValue.test.tsx +221 -0
- package/src/queries/__tests__/hintText.test.tsx +177 -0
- package/src/queries/__tests__/labelText.test.tsx +242 -0
- package/src/queries/__tests__/makeQueries.test.tsx +235 -0
- package/src/queries/__tests__/placeholderText.test.tsx +136 -0
- package/src/queries/__tests__/role-value.test.tsx +176 -0
- package/src/queries/__tests__/role.test.tsx +824 -0
- package/src/queries/__tests__/testId.test.tsx +200 -0
- package/src/queries/__tests__/text.test.tsx +556 -0
- package/src/queries/a11yState.ts +131 -0
- package/src/queries/a11yValue.ts +131 -0
- package/src/queries/displayValue.ts +78 -0
- package/src/queries/hintText.ts +112 -0
- package/src/queries/labelText.ts +59 -0
- package/src/queries/makeQueries.ts +255 -0
- package/src/queries/options.ts +14 -0
- package/src/queries/placeholderText.ts +79 -0
- package/src/queries/role.ts +132 -0
- package/src/queries/testId.ts +71 -0
- package/src/queries/text.ts +66 -0
- package/src/queries/unsafeProps.ts +76 -0
- package/src/queries/unsafeType.ts +73 -0
- package/src/react-versions.ts +11 -0
- package/src/render-act.ts +19 -0
- package/src/render.tsx +183 -0
- package/src/renderHook.tsx +56 -0
- package/src/screen.ts +123 -0
- package/src/shallow.ts +18 -0
- package/src/test-utils/events.ts +24 -0
- package/src/test-utils/index.ts +1 -0
- package/src/user-event/event-builder/common.ts +50 -0
- package/src/user-event/event-builder/index.ts +5 -0
- package/src/user-event/index.ts +14 -0
- package/src/user-event/press/__tests__/longPress.real-timers.test.tsx +115 -0
- package/src/user-event/press/__tests__/longPress.test.tsx +157 -0
- package/src/user-event/press/__tests__/press.real-timers.test.tsx +318 -0
- package/src/user-event/press/__tests__/press.test.tsx +422 -0
- package/src/user-event/press/constants.ts +7 -0
- package/src/user-event/press/index.ts +1 -0
- package/src/user-event/press/press.ts +134 -0
- package/src/user-event/press/utils/warnAboutRealTimers.ts +6 -0
- package/src/user-event/setup/index.ts +2 -0
- package/src/user-event/setup/setup.ts +93 -0
- package/src/user-event/type/__tests__/__snapshots__/type.test.tsx.snap +26 -0
- package/src/user-event/type/__tests__/type.test.tsx +63 -0
- package/src/user-event/type/index.ts +1 -0
- package/src/user-event/type/type.ts +20 -0
- package/src/user-event/utils/__tests__/wait.test.ts +63 -0
- package/src/user-event/utils/events.ts +54 -0
- package/src/user-event/utils/index.ts +2 -0
- package/src/user-event/utils/wait.ts +15 -0
- package/src/waitFor.ts +228 -0
- package/src/waitForElementToBeRemoved.ts +42 -0
- package/src/within.ts +30 -0
- package/tsconfig.json +17 -0
- package/tsconfig.release.json +8 -0
- package/website/.gitignore +20 -0
- package/website/README.md +33 -0
- package/website/docker/.dockerignore +3 -0
- package/website/docker/Dockerfile +9 -0
- package/website/docker/docker-compose.yml +11 -0
- package/website/docs/API.md +946 -0
- package/website/docs/EslintPLluginTestingLibrary.md +28 -0
- package/website/docs/FAQ.md +44 -0
- package/website/docs/GettingStarted.md +100 -0
- package/website/docs/HowShouldIQuery.md +21 -0
- package/website/docs/MigrationV11.md +64 -0
- package/website/docs/MigrationV12.md +67 -0
- package/website/docs/MigrationV2.md +126 -0
- package/website/docs/MigrationV7.md +119 -0
- package/website/docs/MigrationV9.md +67 -0
- package/website/docs/Queries.md +567 -0
- package/website/docs/ReactNavigation.md +371 -0
- package/website/docs/ReduxIntegration.md +137 -0
- package/website/docs/TestingEnvironment.md +154 -0
- package/website/docs/Troubleshooting.md +44 -0
- package/website/docs/UnderstandingAct.md +227 -0
- package/website/docs/UserEvent.md +66 -0
- package/website/docusaurus.config.js +114 -0
- package/website/package.json +31 -0
- package/website/sidebars.js +20 -0
- package/website/src/components/Feature.js +31 -0
- package/website/src/css/custom.css +13 -0
- package/website/src/css/index.module.css +77 -0
- package/website/src/pages/index.js +82 -0
- package/website/static/.nojekyll +0 -0
- package/website/static/css/custom.css +28 -0
- package/website/static/img/hit.png +0 -0
- package/website/static/img/locomotive.png +0 -0
- package/website/static/img/owl.png +0 -0
- package/website/static/img/tools.png +0 -0
- package/website/yarn.lock +7669 -0
- package/yarn.lock +7765 -0
- package/build/flushMicroTasks.d.ts +0 -5
- package/build/flushMicroTasks.js +0 -17
- package/build/flushMicroTasks.js.map +0 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { getQueryPrefix } from './query-name';
|
|
2
|
+
|
|
3
|
+
export function deprecateQueries<Queries extends Record<string, any>>(
|
|
4
|
+
queriesObject: Queries,
|
|
5
|
+
recommendation: string
|
|
6
|
+
): Queries {
|
|
7
|
+
const result = {} as Queries;
|
|
8
|
+
Object.keys(queriesObject).forEach((queryName) => {
|
|
9
|
+
const queryFn = queriesObject[queryName];
|
|
10
|
+
// @ts-expect-error: generic typing is hard
|
|
11
|
+
result[queryName] = deprecateQuery(queryFn, queryName, recommendation);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function deprecateQuery<QueryFn extends (...args: any) => any>(
|
|
18
|
+
queryFn: QueryFn,
|
|
19
|
+
queryName: string,
|
|
20
|
+
recommendation: string
|
|
21
|
+
): QueryFn {
|
|
22
|
+
const formattedRecommendation = recommendation.replace(
|
|
23
|
+
/{queryPrefix}/g,
|
|
24
|
+
getQueryPrefix(queryName)
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
// @ts-expect-error: generic typing is hard
|
|
28
|
+
const wrapper: QueryFn = (...args: any) => {
|
|
29
|
+
const errorMessage = `${queryName}(...) is deprecated and will be removed in the future.\n\n${formattedRecommendation}`;
|
|
30
|
+
// eslint-disable-next-line no-console
|
|
31
|
+
console.warn(errorMessage);
|
|
32
|
+
return queryFn(...args);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return wrapper;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const warned: { [functionName: string]: boolean } = {};
|
|
39
|
+
|
|
40
|
+
// istambul ignore next: Occasionally used
|
|
41
|
+
export function printDeprecationWarning(functionName: string) {
|
|
42
|
+
if (warned[functionName]) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// eslint-disable-next-line no-console
|
|
47
|
+
console.warn(`
|
|
48
|
+
Deprecation Warning:
|
|
49
|
+
Use of ${functionName} is not recommended and will be deleted in future versions of @testing-library/react-native.
|
|
50
|
+
`);
|
|
51
|
+
|
|
52
|
+
warned[functionName] = true;
|
|
53
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import prettyFormat from 'pretty-format';
|
|
2
|
+
|
|
3
|
+
export class ErrorWithStack extends Error {
|
|
4
|
+
constructor(message: string | undefined, callsite: Function) {
|
|
5
|
+
super(message);
|
|
6
|
+
if (Error.captureStackTrace) {
|
|
7
|
+
Error.captureStackTrace(this, callsite);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const prepareErrorMessage = (
|
|
13
|
+
// TS states that error caught in a catch close are of type `unknown`
|
|
14
|
+
// most real cases will be `Error`, but better safe than sorry
|
|
15
|
+
error: unknown,
|
|
16
|
+
name?: string,
|
|
17
|
+
value?: unknown
|
|
18
|
+
): string => {
|
|
19
|
+
let errorMessage: string;
|
|
20
|
+
if (error instanceof Error) {
|
|
21
|
+
// Strip info about custom predicate
|
|
22
|
+
errorMessage = error.message.replace(
|
|
23
|
+
/ matching custom predicate[^]*/gm,
|
|
24
|
+
''
|
|
25
|
+
);
|
|
26
|
+
} else if (error && typeof error === 'object') {
|
|
27
|
+
errorMessage = error.toString();
|
|
28
|
+
} else {
|
|
29
|
+
errorMessage = 'Caught unknown error';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (name && value) {
|
|
33
|
+
errorMessage += ` with ${name} ${prettyFormat(value, { min: true })}`;
|
|
34
|
+
}
|
|
35
|
+
return errorMessage;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const createQueryByError = (
|
|
39
|
+
error: unknown,
|
|
40
|
+
callsite: Function
|
|
41
|
+
): null => {
|
|
42
|
+
if (error instanceof Error) {
|
|
43
|
+
if (error.message.includes('No instances found')) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
throw new ErrorWithStack(error.message, callsite);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
throw new ErrorWithStack(
|
|
50
|
+
// generic refining of `unknown` is very hard, you cannot do `'toString' in error` or anything like that
|
|
51
|
+
// Converting as any with extra safe optional chaining will do the job just as well
|
|
52
|
+
`Query: caught unknown error type: ${typeof error}, value: ${(
|
|
53
|
+
error as any
|
|
54
|
+
)?.toString?.()}`,
|
|
55
|
+
callsite
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export function copyStackTrace(target: unknown, stackTraceSource: Error) {
|
|
60
|
+
if (target instanceof Error && stackTraceSource.stack) {
|
|
61
|
+
target.stack = stackTraceSource.stack.replace(
|
|
62
|
+
stackTraceSource.message,
|
|
63
|
+
target.message
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ReactTestInstance } from 'react-test-renderer';
|
|
2
|
+
import { getConfig } from '../config';
|
|
3
|
+
import { isHiddenFromAccessibility } from './accessiblity';
|
|
4
|
+
|
|
5
|
+
interface FindAllOptions {
|
|
6
|
+
/** Match elements hidden from accessibility */
|
|
7
|
+
includeHiddenElements?: boolean;
|
|
8
|
+
|
|
9
|
+
/** RTL-compatible alias to `includeHiddenElements` */
|
|
10
|
+
hidden?: boolean;
|
|
11
|
+
|
|
12
|
+
/* Exclude any ancestors of deepest matched elements even if they match the predicate */
|
|
13
|
+
matchDeepestOnly?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function findAll(
|
|
17
|
+
root: ReactTestInstance,
|
|
18
|
+
predicate: (element: ReactTestInstance) => boolean,
|
|
19
|
+
options?: FindAllOptions
|
|
20
|
+
) {
|
|
21
|
+
const results = findAllInternal(root, predicate, options);
|
|
22
|
+
|
|
23
|
+
const includeHiddenElements =
|
|
24
|
+
options?.includeHiddenElements ??
|
|
25
|
+
options?.hidden ??
|
|
26
|
+
getConfig()?.defaultIncludeHiddenElements;
|
|
27
|
+
|
|
28
|
+
if (includeHiddenElements) {
|
|
29
|
+
return results;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const cache = new WeakMap<ReactTestInstance>();
|
|
33
|
+
return results.filter(
|
|
34
|
+
(element) => !isHiddenFromAccessibility(element, { cache })
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Extracted from React Test Renderer
|
|
39
|
+
// src: https://github.com/facebook/react/blob/8e2bde6f2751aa6335f3cef488c05c3ea08e074a/packages/react-test-renderer/src/ReactTestRenderer.js#L402
|
|
40
|
+
function findAllInternal(
|
|
41
|
+
root: ReactTestInstance,
|
|
42
|
+
predicate: (element: ReactTestInstance) => boolean,
|
|
43
|
+
options?: FindAllOptions
|
|
44
|
+
): Array<ReactTestInstance> {
|
|
45
|
+
const results: ReactTestInstance[] = [];
|
|
46
|
+
|
|
47
|
+
// Match descendants first but do not add them to results yet.
|
|
48
|
+
const matchingDescendants: ReactTestInstance[] = [];
|
|
49
|
+
root.children.forEach((child) => {
|
|
50
|
+
if (typeof child === 'string') {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
matchingDescendants.push(...findAllInternal(child, predicate, options));
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (
|
|
57
|
+
// When matchDeepestOnly = true: add current element only if no descendants match
|
|
58
|
+
(!options?.matchDeepestOnly || matchingDescendants.length === 0) &&
|
|
59
|
+
predicate(root)
|
|
60
|
+
) {
|
|
61
|
+
results.push(root);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Add matching descendants after element to preserve original tree walk order.
|
|
65
|
+
results.push(...matchingDescendants);
|
|
66
|
+
|
|
67
|
+
return results;
|
|
68
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { StyleSheet, ViewStyle } from 'react-native';
|
|
2
|
+
import { MapPropsFunction } from './format';
|
|
3
|
+
|
|
4
|
+
const propsToDisplay = [
|
|
5
|
+
'testID',
|
|
6
|
+
'nativeID',
|
|
7
|
+
'accessibilityElementsHidden',
|
|
8
|
+
'accessibilityViewIsModal',
|
|
9
|
+
'importantForAccessibility',
|
|
10
|
+
'accessibilityRole',
|
|
11
|
+
'accessibilityLabel',
|
|
12
|
+
'accessibilityLabelledBy',
|
|
13
|
+
'accessibilityHint',
|
|
14
|
+
'placeholder',
|
|
15
|
+
'value',
|
|
16
|
+
'defaultValue',
|
|
17
|
+
'title',
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Preserve props that are helpful in diagnosing test failures, while stripping rest
|
|
22
|
+
*/
|
|
23
|
+
export const defaultMapProps: MapPropsFunction = (props) => {
|
|
24
|
+
const result: Record<string, unknown> = {};
|
|
25
|
+
|
|
26
|
+
const styles = StyleSheet.flatten(props.style as ViewStyle);
|
|
27
|
+
if (styles?.display === 'none') {
|
|
28
|
+
result.style = { display: 'none' };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const accessibilityState = removeUndefinedKeys(props.accessibilityState);
|
|
32
|
+
if (accessibilityState !== undefined) {
|
|
33
|
+
result.accessibilityState = accessibilityState;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const accessibilityValue = removeUndefinedKeys(props.accessibilityValue);
|
|
37
|
+
if (accessibilityValue !== undefined) {
|
|
38
|
+
result.accessibilityValue = accessibilityValue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
propsToDisplay.forEach((propName) => {
|
|
42
|
+
if (propName in props) {
|
|
43
|
+
result[propName] = props[propName];
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
function isObject(value: unknown): value is Record<string, unknown> {
|
|
51
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function removeUndefinedKeys(prop: unknown) {
|
|
55
|
+
if (!isObject(prop)) {
|
|
56
|
+
return prop;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const result: Record<string, unknown> = {};
|
|
60
|
+
Object.entries(prop).forEach(([key, value]) => {
|
|
61
|
+
if (value !== undefined) {
|
|
62
|
+
result[key] = value;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// If object does not have any props we will ignore it.
|
|
67
|
+
if (Object.keys(result).length === 0) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ReactTestRendererJSON } from 'react-test-renderer';
|
|
2
|
+
import prettyFormat, { NewPlugin, plugins } from 'pretty-format';
|
|
3
|
+
|
|
4
|
+
export type MapPropsFunction = (
|
|
5
|
+
props: Record<string, unknown>,
|
|
6
|
+
node: ReactTestRendererJSON
|
|
7
|
+
) => Record<string, unknown>;
|
|
8
|
+
|
|
9
|
+
export type FormatOptions = {
|
|
10
|
+
mapProps?: MapPropsFunction;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const format = (
|
|
14
|
+
input: ReactTestRendererJSON | ReactTestRendererJSON[],
|
|
15
|
+
options: FormatOptions = {}
|
|
16
|
+
) =>
|
|
17
|
+
prettyFormat(input, {
|
|
18
|
+
plugins: [getCustomPlugin(options.mapProps), plugins.ReactElement],
|
|
19
|
+
highlight: shouldHighlight(),
|
|
20
|
+
printBasicPrototype: false,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const getCustomPlugin = (mapProps?: MapPropsFunction): NewPlugin => {
|
|
24
|
+
return {
|
|
25
|
+
test: (val) => plugins.ReactTestComponent.test(val),
|
|
26
|
+
serialize: (val, config, indentation, depth, refs, printer) => {
|
|
27
|
+
let newVal = val;
|
|
28
|
+
if (mapProps && val.props) {
|
|
29
|
+
newVal = { ...val, props: mapProps(val.props, val) };
|
|
30
|
+
}
|
|
31
|
+
return plugins.ReactTestComponent.serialize(
|
|
32
|
+
newVal,
|
|
33
|
+
config,
|
|
34
|
+
indentation,
|
|
35
|
+
depth,
|
|
36
|
+
refs,
|
|
37
|
+
printer
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
function shouldHighlight() {
|
|
44
|
+
return process?.env?.COLORS !== 'false';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default format;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ReactTestInstance } from 'react-test-renderer';
|
|
2
|
+
|
|
3
|
+
export function getTextContent(
|
|
4
|
+
element: ReactTestInstance | string | null
|
|
5
|
+
): string {
|
|
6
|
+
if (!element) {
|
|
7
|
+
return '';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (typeof element === 'string') {
|
|
11
|
+
return element;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const result: string[] = [];
|
|
15
|
+
element.children?.forEach((child) => {
|
|
16
|
+
result.push(getTextContent(child));
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
return result.join('');
|
|
20
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ReactTestInstance } from 'react-test-renderer';
|
|
3
|
+
import { Switch, Text, TextInput, View } from 'react-native';
|
|
4
|
+
import { configureInternal, getConfig, HostComponentNames } from '../config';
|
|
5
|
+
import { renderWithAct } from '../render-act';
|
|
6
|
+
|
|
7
|
+
const userConfigErrorMessage = `There seems to be an issue with your configuration that prevents React Native Testing Library from working correctly.
|
|
8
|
+
Please check if you are using compatible versions of React Native and React Native Testing Library.`;
|
|
9
|
+
|
|
10
|
+
export function getHostComponentNames(): HostComponentNames {
|
|
11
|
+
let hostComponentNames = getConfig().hostComponentNames;
|
|
12
|
+
if (!hostComponentNames) {
|
|
13
|
+
hostComponentNames = detectHostComponentNames();
|
|
14
|
+
configureInternal({ hostComponentNames });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return hostComponentNames;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function configureHostComponentNamesIfNeeded() {
|
|
21
|
+
const configHostComponentNames = getConfig().hostComponentNames;
|
|
22
|
+
if (configHostComponentNames) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const hostComponentNames = detectHostComponentNames();
|
|
27
|
+
configureInternal({ hostComponentNames });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function detectHostComponentNames(): HostComponentNames {
|
|
31
|
+
try {
|
|
32
|
+
const renderer = renderWithAct(
|
|
33
|
+
<View>
|
|
34
|
+
<Text testID="text">Hello</Text>
|
|
35
|
+
<TextInput testID="textInput" />
|
|
36
|
+
<Switch testID="switch" />
|
|
37
|
+
</View>
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
text: getByTestId(renderer.root, 'text').type as string,
|
|
42
|
+
textInput: getByTestId(renderer.root, 'textInput').type as string,
|
|
43
|
+
switch: getByTestId(renderer.root, 'switch').type as string,
|
|
44
|
+
};
|
|
45
|
+
} catch (error) {
|
|
46
|
+
const errorMessage =
|
|
47
|
+
error && typeof error === 'object' && 'message' in error
|
|
48
|
+
? error.message
|
|
49
|
+
: null;
|
|
50
|
+
|
|
51
|
+
throw new Error(
|
|
52
|
+
`Trying to detect host component names triggered the following error:\n\n${errorMessage}\n\n${userConfigErrorMessage}`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getByTestId(instance: ReactTestInstance, testID: string) {
|
|
58
|
+
const nodes = instance.findAll(
|
|
59
|
+
(node) => typeof node.type === 'string' && node.props.testID === testID
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
if (nodes.length === 0) {
|
|
63
|
+
throw new Error(`Unable to find an element with testID: ${testID}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return nodes[0];
|
|
67
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { matchArrayProp } from '../matchArrayProp';
|
|
2
|
+
|
|
3
|
+
test('returns true given 2 identical prop and matcher', () => {
|
|
4
|
+
expect(matchArrayProp(['banana'], ['banana'])).toEqual(true);
|
|
5
|
+
expect(matchArrayProp(['banana', 'apple'], ['banana', 'apple'])).toEqual(
|
|
6
|
+
true
|
|
7
|
+
);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test('returns true when the prop contains all the values of the matcher', () => {
|
|
11
|
+
expect(
|
|
12
|
+
matchArrayProp(['banana', 'apple', 'orange'], ['banana', 'orange'])
|
|
13
|
+
).toEqual(true);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('returns false when the prop does not contain all the values of the matcher', () => {
|
|
17
|
+
expect(
|
|
18
|
+
matchArrayProp(['banana', 'apple', 'orange'], ['banana', 'pear'])
|
|
19
|
+
).toEqual(false);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('returns false when prop is undefined', () => {
|
|
23
|
+
expect(matchArrayProp(undefined, ['banana'])).toEqual(false);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('returns false when the matcher is an empty list', () => {
|
|
27
|
+
expect(matchArrayProp(['banana'], [])).toEqual(false);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('returns false given 2 different prop and matchers', () => {
|
|
31
|
+
expect(matchArrayProp(['banana', 'apple'], ['banana', 'orange'])).toEqual(
|
|
32
|
+
false
|
|
33
|
+
);
|
|
34
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { matchObjectProp } from '../matchObjectProp';
|
|
2
|
+
|
|
3
|
+
test('returns true given 2 identical objects', () => {
|
|
4
|
+
expect(matchObjectProp({ fruit: 'banana' }, { fruit: 'banana' })).toEqual(
|
|
5
|
+
true
|
|
6
|
+
);
|
|
7
|
+
expect(
|
|
8
|
+
matchObjectProp(
|
|
9
|
+
{ fruit: 'banana', isRipe: true },
|
|
10
|
+
{ fruit: 'banana', isRipe: true }
|
|
11
|
+
)
|
|
12
|
+
).toEqual(true);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('returns false when one of the param is an empty object', () => {
|
|
16
|
+
expect(matchObjectProp({}, { fruit: 'banana' })).toEqual(false);
|
|
17
|
+
expect(matchObjectProp({ fruit: 'banana' }, {})).toEqual(false);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('returns false given an undefined prop', () => {
|
|
21
|
+
expect(matchObjectProp(undefined, { fruit: 'banana' })).toEqual(false);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('returns false given 2 different non empty objects', () => {
|
|
25
|
+
expect(matchObjectProp({ fruit: 'banana' }, { fruits: 'banana' })).toEqual(
|
|
26
|
+
false
|
|
27
|
+
);
|
|
28
|
+
expect(matchObjectProp({ fruit: 'banana' }, { fruit: 'orange' })).toEqual(
|
|
29
|
+
false
|
|
30
|
+
);
|
|
31
|
+
expect(
|
|
32
|
+
matchObjectProp(
|
|
33
|
+
{ fruit: 'banana', isRipe: true },
|
|
34
|
+
{ fruit: 'banana', ripe: true }
|
|
35
|
+
)
|
|
36
|
+
).toEqual(false);
|
|
37
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { matchStringProp } from '../matchStringProp';
|
|
2
|
+
|
|
3
|
+
test.each`
|
|
4
|
+
prop | matcher | expectedResult
|
|
5
|
+
${'hey'} | ${'hey'} | ${true}
|
|
6
|
+
${'hey'} | ${/hey/} | ${true}
|
|
7
|
+
${'hey'} | ${'heyyyy'} | ${false}
|
|
8
|
+
${'hey'} | ${/heyyy/} | ${false}
|
|
9
|
+
${undefined} | ${'hey'} | ${false}
|
|
10
|
+
`(
|
|
11
|
+
'returns $expectedResult given prop $prop and matcher $matcher',
|
|
12
|
+
({ prop, matcher, expectedResult }) => {
|
|
13
|
+
expect(matchStringProp(prop, matcher)).toEqual(expectedResult);
|
|
14
|
+
}
|
|
15
|
+
);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { AccessibilityState } from 'react-native';
|
|
2
|
+
import { ReactTestInstance } from 'react-test-renderer';
|
|
3
|
+
import { accessibilityStateKeys } from '../accessiblity';
|
|
4
|
+
|
|
5
|
+
// This type is the same as AccessibilityState from `react-native` package
|
|
6
|
+
// It is re-declared here due to issues with migration from `@types/react-native` to
|
|
7
|
+
// built in `react-native` types.
|
|
8
|
+
// See: https://github.com/callstack/react-native-testing-library/issues/1351
|
|
9
|
+
export interface AccessibilityStateMatcher {
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
selected?: boolean;
|
|
12
|
+
checked?: boolean | 'mixed';
|
|
13
|
+
busy?: boolean;
|
|
14
|
+
expanded?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Default accessibility state values based on experiments using accessibility
|
|
19
|
+
* inspector/screen reader on iOS and Android.
|
|
20
|
+
*
|
|
21
|
+
* @see https://github.com/callstack/react-native-testing-library/wiki/Accessibility:-State
|
|
22
|
+
*/
|
|
23
|
+
const defaultState: AccessibilityState = {
|
|
24
|
+
disabled: false,
|
|
25
|
+
selected: false,
|
|
26
|
+
checked: undefined,
|
|
27
|
+
busy: false,
|
|
28
|
+
expanded: undefined,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export function matchAccessibilityState(
|
|
32
|
+
node: ReactTestInstance,
|
|
33
|
+
matcher: AccessibilityStateMatcher
|
|
34
|
+
) {
|
|
35
|
+
const state = node.props.accessibilityState;
|
|
36
|
+
return accessibilityStateKeys.every((key) => matchState(state, matcher, key));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function matchState(
|
|
40
|
+
state: AccessibilityState,
|
|
41
|
+
matcher: AccessibilityStateMatcher,
|
|
42
|
+
key: keyof AccessibilityState
|
|
43
|
+
) {
|
|
44
|
+
return (
|
|
45
|
+
matcher[key] === undefined ||
|
|
46
|
+
matcher[key] === (state?.[key] ?? defaultState[key])
|
|
47
|
+
);
|
|
48
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { AccessibilityValue } from 'react-native';
|
|
2
|
+
import { ReactTestInstance } from 'react-test-renderer';
|
|
3
|
+
import { TextMatch } from '../../matches';
|
|
4
|
+
import { matchStringProp } from './matchStringProp';
|
|
5
|
+
|
|
6
|
+
export interface AccessibilityValueMatcher {
|
|
7
|
+
min?: number;
|
|
8
|
+
max?: number;
|
|
9
|
+
now?: number;
|
|
10
|
+
text?: TextMatch;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function matchAccessibilityValue(
|
|
14
|
+
node: ReactTestInstance,
|
|
15
|
+
matcher: AccessibilityValueMatcher
|
|
16
|
+
): boolean {
|
|
17
|
+
const value: AccessibilityValue = node.props.accessibilityValue ?? {};
|
|
18
|
+
return (
|
|
19
|
+
(matcher.min === undefined || matcher.min === value.min) &&
|
|
20
|
+
(matcher.max === undefined || matcher.max === value.max) &&
|
|
21
|
+
(matcher.now === undefined || matcher.now === value.now) &&
|
|
22
|
+
(matcher.text === undefined || matchStringProp(value.text, matcher.text))
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Matches whether given array prop contains the given value, or all given values.
|
|
3
|
+
*
|
|
4
|
+
* @param prop - The array prop to match.
|
|
5
|
+
* @param matcher - The value or values to be included in the array.
|
|
6
|
+
* @returns Whether the array prop contains the given value, or all given values.
|
|
7
|
+
*/
|
|
8
|
+
export function matchArrayProp(
|
|
9
|
+
prop: Array<string> | undefined,
|
|
10
|
+
matcher: string | Array<string>
|
|
11
|
+
): boolean {
|
|
12
|
+
if (!prop || matcher.length === 0) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (typeof matcher === 'string') {
|
|
17
|
+
return prop.includes(matcher);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return matcher.every((e) => prop.includes(e));
|
|
21
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ReactTestInstance } from 'react-test-renderer';
|
|
2
|
+
import { matches, TextMatch, TextMatchOptions } from '../../matches';
|
|
3
|
+
import { findAll } from '../findAll';
|
|
4
|
+
import { matchTextContent } from './matchTextContent';
|
|
5
|
+
|
|
6
|
+
export function matchLabelText(
|
|
7
|
+
root: ReactTestInstance,
|
|
8
|
+
element: ReactTestInstance,
|
|
9
|
+
text: TextMatch,
|
|
10
|
+
options: TextMatchOptions = {}
|
|
11
|
+
) {
|
|
12
|
+
return (
|
|
13
|
+
matchAccessibilityLabel(element, text, options) ||
|
|
14
|
+
matchAccessibilityLabelledBy(
|
|
15
|
+
root,
|
|
16
|
+
element.props.accessibilityLabelledBy,
|
|
17
|
+
text,
|
|
18
|
+
options
|
|
19
|
+
)
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function matchAccessibilityLabel(
|
|
24
|
+
element: ReactTestInstance,
|
|
25
|
+
text: TextMatch,
|
|
26
|
+
options: TextMatchOptions
|
|
27
|
+
) {
|
|
28
|
+
const { exact, normalizer } = options;
|
|
29
|
+
return matches(text, element.props.accessibilityLabel, normalizer, exact);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function matchAccessibilityLabelledBy(
|
|
33
|
+
root: ReactTestInstance,
|
|
34
|
+
nativeId: string | undefined,
|
|
35
|
+
text: TextMatch,
|
|
36
|
+
options: TextMatchOptions
|
|
37
|
+
) {
|
|
38
|
+
if (!nativeId) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
findAll(
|
|
44
|
+
root,
|
|
45
|
+
(node) =>
|
|
46
|
+
typeof node.type === 'string' &&
|
|
47
|
+
node.props.nativeID === nativeId &&
|
|
48
|
+
matchTextContent(node, text, options)
|
|
49
|
+
).length > 0
|
|
50
|
+
);
|
|
51
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* check that each key value pair of the objects match
|
|
3
|
+
* BE CAREFUL it works only for 1 level deep key value pairs
|
|
4
|
+
* won't work for nested objects
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Matches whether given object prop contains all key/value pairs.
|
|
9
|
+
* @param prop - The object prop to match.
|
|
10
|
+
* @param matcher - The key/value pairs to be included in the object.
|
|
11
|
+
* @returns Whether the object prop contains all key/value pairs.
|
|
12
|
+
*/
|
|
13
|
+
export function matchObjectProp<T extends Record<string, unknown>>(
|
|
14
|
+
prop: T | undefined,
|
|
15
|
+
matcher: T
|
|
16
|
+
): boolean {
|
|
17
|
+
if (!prop || Object.keys(matcher).length === 0) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
Object.keys(prop).length !== 0 &&
|
|
23
|
+
Object.keys(matcher).every((key) => prop[key] === matcher[key])
|
|
24
|
+
);
|
|
25
|
+
}
|