@testing-library/react-native 12.1.2 → 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.
Files changed (363) hide show
  1. package/.DS_Store +0 -0
  2. package/.codecov.yml +9 -0
  3. package/.eslintcache +1 -0
  4. package/.eslintignore +2 -0
  5. package/.eslintrc +19 -0
  6. package/.flowconfig +63 -0
  7. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  8. package/.github/ISSUE_TEMPLATE/feature_request.md +14 -0
  9. package/.github/ISSUE_TEMPLATE/question.md +9 -0
  10. package/.github/PULL_REQUEST_TEMPLATE.md +10 -0
  11. package/.github/actions/setup-deps/action.yml +22 -0
  12. package/.github/actions/setup-website-deps/action.yml +22 -0
  13. package/.github/dependabot.yml +10 -0
  14. package/.github/workflows/deploy-website.yml +36 -0
  15. package/.github/workflows/example-apps.yml +25 -0
  16. package/.github/workflows/main.yml +103 -0
  17. package/.gitignore +11 -0
  18. package/.prettierrc.js +5 -0
  19. package/CODE_OF_CONDUCT.md +73 -0
  20. package/CONTRIBUTING.md +64 -0
  21. package/README.md +8 -7
  22. package/babel.config.js +22 -0
  23. package/build/act.js.map +1 -1
  24. package/build/cleanup.js.map +1 -1
  25. package/build/fireEvent.d.ts +9 -1
  26. package/build/fireEvent.js +9 -15
  27. package/build/fireEvent.js.map +1 -1
  28. package/build/flush-micro-tasks.d.ts +19 -0
  29. package/build/flush-micro-tasks.js +36 -0
  30. package/build/flush-micro-tasks.js.map +1 -0
  31. package/build/helpers/accessiblity.js +2 -2
  32. package/build/helpers/accessiblity.js.map +1 -1
  33. package/build/helpers/component-tree.js.map +1 -1
  34. package/build/helpers/deprecation.js.map +1 -1
  35. package/build/helpers/errors.js.map +1 -1
  36. package/build/helpers/findAll.js.map +1 -1
  37. package/build/helpers/format-default.js.map +1 -1
  38. package/build/helpers/format.js.map +1 -1
  39. package/build/helpers/host-component-names.js.map +1 -1
  40. package/build/helpers/matchers/matchLabelText.js.map +1 -1
  41. package/build/helpers/pointer-events.d.ts +9 -0
  42. package/build/helpers/pointer-events.js +25 -0
  43. package/build/helpers/pointer-events.js.map +1 -0
  44. package/build/helpers/stringValidation.js.map +1 -1
  45. package/build/helpers/timers.js.map +1 -1
  46. package/build/index.js +2 -2
  47. package/build/index.js.map +1 -1
  48. package/build/matches.js.map +1 -1
  49. package/build/pure.d.ts +1 -1
  50. package/build/pure.js.map +1 -1
  51. package/build/queries/a11yState.js.map +1 -1
  52. package/build/queries/a11yValue.js.map +1 -1
  53. package/build/queries/displayValue.js.map +1 -1
  54. package/build/queries/hintText.js.map +1 -1
  55. package/build/queries/labelText.js.map +1 -1
  56. package/build/queries/makeQueries.js.map +1 -1
  57. package/build/queries/placeholderText.js.map +1 -1
  58. package/build/queries/role.js.map +1 -1
  59. package/build/queries/testId.js.map +1 -1
  60. package/build/queries/text.js.map +1 -1
  61. package/build/queries/unsafeProps.js.map +1 -1
  62. package/build/render.d.ts +171 -12
  63. package/build/render.js +11 -4
  64. package/build/render.js.map +1 -1
  65. package/build/renderHook.d.ts +3 -6
  66. package/build/renderHook.js +4 -3
  67. package/build/renderHook.js.map +1 -1
  68. package/build/shallow.js.map +1 -1
  69. package/build/test-utils/events.d.ts +10 -0
  70. package/build/test-utils/events.js +27 -0
  71. package/build/test-utils/events.js.map +1 -0
  72. package/build/test-utils/index.d.ts +1 -0
  73. package/build/test-utils/index.js +17 -0
  74. package/build/test-utils/index.js.map +1 -0
  75. package/build/user-event/event-builder/common.d.ts +45 -0
  76. package/build/user-event/event-builder/common.js +58 -0
  77. package/build/user-event/event-builder/common.js.map +1 -0
  78. package/build/user-event/event-builder/index.d.ts +32 -0
  79. package/build/user-event/event-builder/index.js +12 -0
  80. package/build/user-event/event-builder/index.js.map +1 -0
  81. package/build/user-event/index.d.ts +9 -0
  82. package/build/user-event/index.js +16 -0
  83. package/build/user-event/index.js.map +1 -0
  84. package/build/user-event/press/constants.d.ts +2 -0
  85. package/build/user-event/press/constants.js +16 -0
  86. package/build/user-event/press/constants.js.map +1 -0
  87. package/build/user-event/press/index.d.ts +1 -0
  88. package/build/user-event/press/index.js +19 -0
  89. package/build/user-event/press/index.js.map +1 -0
  90. package/build/user-event/press/press.d.ts +7 -0
  91. package/build/user-event/press/press.js +106 -0
  92. package/build/user-event/press/press.js.map +1 -0
  93. package/build/user-event/press/utils/warnAboutRealTimers.d.ts +1 -0
  94. package/build/user-event/press/utils/warnAboutRealTimers.js +14 -0
  95. package/build/user-event/press/utils/warnAboutRealTimers.js.map +1 -0
  96. package/build/user-event/setup/index.d.ts +2 -0
  97. package/build/user-event/setup/index.js +13 -0
  98. package/build/user-event/setup/index.js.map +1 -0
  99. package/build/user-event/setup/setup.d.ts +39 -0
  100. package/build/user-event/setup/setup.js +56 -0
  101. package/build/user-event/setup/setup.js.map +1 -0
  102. package/build/user-event/type/index.d.ts +1 -0
  103. package/build/user-event/type/index.js +13 -0
  104. package/build/user-event/type/index.js.map +1 -0
  105. package/build/user-event/type/type.d.ts +3 -0
  106. package/build/user-event/type/type.js +18 -0
  107. package/build/user-event/type/type.js.map +1 -0
  108. package/build/user-event/utils/events.d.ts +9 -0
  109. package/build/user-event/utils/events.js +44 -0
  110. package/build/user-event/utils/events.js.map +1 -0
  111. package/build/user-event/utils/index.d.ts +2 -0
  112. package/build/user-event/utils/index.js +28 -0
  113. package/build/user-event/utils/index.js.map +1 -0
  114. package/build/user-event/utils/wait.d.ts +2 -0
  115. package/build/user-event/utils/wait.js +14 -0
  116. package/build/user-event/utils/wait.js.map +1 -0
  117. package/build/waitFor.js +3 -3
  118. package/build/waitFor.js.map +1 -1
  119. package/build/waitForElementToBeRemoved.js.map +1 -1
  120. package/examples/basic/.expo-shared/assets.json +4 -0
  121. package/examples/basic/.gitignore +14 -0
  122. package/examples/basic/App.tsx +20 -0
  123. package/examples/basic/README.md +11 -0
  124. package/examples/basic/__tests__/App.test.tsx +119 -0
  125. package/examples/basic/app.json +31 -0
  126. package/examples/basic/assets/adaptive-icon.png +0 -0
  127. package/examples/basic/assets/favicon.png +0 -0
  128. package/examples/basic/assets/icon.png +0 -0
  129. package/examples/basic/assets/splash.png +0 -0
  130. package/examples/basic/babel.config.js +6 -0
  131. package/examples/basic/components/Home.tsx +28 -0
  132. package/examples/basic/components/LoginForm.tsx +138 -0
  133. package/examples/basic/jest-setup.ts +7 -0
  134. package/examples/basic/jest.config.js +5 -0
  135. package/examples/basic/package.json +30 -0
  136. package/examples/basic/tsconfig.json +7 -0
  137. package/examples/react-navigation/README.md +14 -0
  138. package/examples/react-navigation/babel.config.js +4 -0
  139. package/examples/react-navigation/jest-setup.js +11 -0
  140. package/examples/react-navigation/jest.config.js +10 -0
  141. package/examples/react-navigation/package.json +31 -0
  142. package/examples/react-navigation/src/App.js +21 -0
  143. package/examples/react-navigation/src/DrawerNavigator.js +15 -0
  144. package/examples/react-navigation/src/DrawerNavigator.test.js +42 -0
  145. package/examples/react-navigation/src/NativeStackNavigator.js +15 -0
  146. package/examples/react-navigation/src/NativeStackNavigator.test.js +34 -0
  147. package/examples/react-navigation/src/StackNavigator.js +15 -0
  148. package/examples/react-navigation/src/StackNavigator.test.js +34 -0
  149. package/examples/react-navigation/src/TabNavigator.js +15 -0
  150. package/examples/react-navigation/src/TabNavigator.test.js +21 -0
  151. package/examples/react-navigation/src/screens/DetailsScreen.js +43 -0
  152. package/examples/react-navigation/src/screens/DetailsScreen.test.js +27 -0
  153. package/examples/react-navigation/src/screens/DrawerHomeScreen.js +26 -0
  154. package/examples/react-navigation/src/screens/HomeScreen.js +48 -0
  155. package/examples/react-navigation/src/screens/SettingsScreen.js +20 -0
  156. package/examples/react-navigation/src/test-utils.js +12 -0
  157. package/examples/redux/App.js +27 -0
  158. package/examples/redux/actions/todoActions.js +25 -0
  159. package/examples/redux/babel.config.js +6 -0
  160. package/examples/redux/components/AddTodo.js +73 -0
  161. package/examples/redux/components/AddTodo.test.js +27 -0
  162. package/examples/redux/components/TodoElem.js +25 -0
  163. package/examples/redux/components/TodoList.js +29 -0
  164. package/examples/redux/components/TodoList.test.js +34 -0
  165. package/examples/redux/index.js +8 -0
  166. package/examples/redux/jest-setup.js +2 -0
  167. package/examples/redux/jest.config.js +4 -0
  168. package/examples/redux/package.json +23 -0
  169. package/examples/redux/reducers/index.js +6 -0
  170. package/examples/redux/reducers/todoReducer.js +27 -0
  171. package/examples/redux/store.js +10 -0
  172. package/examples/redux/test-utils.js +11 -0
  173. package/experiments-app/.expo/README.md +15 -0
  174. package/experiments-app/.expo/devices.json +3 -0
  175. package/experiments-app/.expo/packager-info.json +9 -0
  176. package/experiments-app/.expo/settings.json +9 -0
  177. package/experiments-app/.gitignore +17 -0
  178. package/experiments-app/.prettierrc.js +5 -0
  179. package/experiments-app/app.json +30 -0
  180. package/experiments-app/assets/adaptive-icon.png +0 -0
  181. package/experiments-app/assets/favicon.png +0 -0
  182. package/experiments-app/assets/icon.png +0 -0
  183. package/experiments-app/assets/splash.png +0 -0
  184. package/experiments-app/babel.config.js +6 -0
  185. package/experiments-app/index.js +4 -0
  186. package/experiments-app/package.json +31 -0
  187. package/experiments-app/src/App.tsx +31 -0
  188. package/experiments-app/src/MainScreen.tsx +51 -0
  189. package/experiments-app/src/experiments.ts +17 -0
  190. package/experiments-app/src/screens/TextInputEventPropagation.tsx +54 -0
  191. package/experiments-app/src/screens/TextInputEvents.tsx +50 -0
  192. package/experiments-app/src/utils/helpers.ts +8 -0
  193. package/experiments-app/tsconfig.json +6 -0
  194. package/experiments-app/yarn.lock +6913 -0
  195. package/flow-typed/npm/jest_v26.x.x.js +1218 -0
  196. package/flow-typed/npm/react-test-renderer_v16.x.x.js +81 -0
  197. package/jest-setup.ts +10 -0
  198. package/package.json +6 -6
  199. package/renovate.json +19 -0
  200. package/scripts/test_react_17 +12 -0
  201. package/src/__tests__/__snapshots__/render-debug.test.tsx.snap +548 -0
  202. package/src/__tests__/__snapshots__/render.test.tsx.snap +39 -0
  203. package/src/__tests__/act.test.tsx +52 -0
  204. package/src/__tests__/auto-cleanup-skip.test.tsx +39 -0
  205. package/src/__tests__/auto-cleanup.test.tsx +50 -0
  206. package/src/__tests__/cleanup.test.tsx +26 -0
  207. package/src/__tests__/config.test.ts +55 -0
  208. package/src/__tests__/fireEvent-textInput.test.tsx +154 -0
  209. package/src/__tests__/fireEvent.test.tsx +485 -0
  210. package/src/__tests__/host-component-names.test.tsx +109 -0
  211. package/src/__tests__/host-text-nesting.test.tsx +90 -0
  212. package/src/__tests__/jest-native.test.tsx +84 -0
  213. package/src/__tests__/questionsBoard.test.tsx +62 -0
  214. package/src/__tests__/react-native-api.test.tsx +126 -0
  215. package/src/__tests__/render-debug.test.tsx +207 -0
  216. package/src/__tests__/render-stringValidation.test.tsx +157 -0
  217. package/src/__tests__/render.test.tsx +256 -0
  218. package/src/__tests__/renderHook.test.tsx +114 -0
  219. package/src/__tests__/screen.test.tsx +66 -0
  220. package/src/__tests__/timerUtils.ts +7 -0
  221. package/src/__tests__/timers.test.ts +27 -0
  222. package/src/__tests__/waitFor.test.tsx +327 -0
  223. package/src/__tests__/waitForElementToBeRemoved.test.tsx +151 -0
  224. package/src/__tests__/within.test.tsx +96 -0
  225. package/src/act.ts +86 -0
  226. package/src/cleanup.ts +15 -0
  227. package/src/config.ts +72 -0
  228. package/src/fireEvent.ts +163 -0
  229. package/src/flush-micro-tasks.ts +30 -0
  230. package/src/helpers/__tests__/accessiblity.test.tsx +373 -0
  231. package/src/helpers/__tests__/component-tree.test.tsx +226 -0
  232. package/src/helpers/__tests__/format-default.tsx +114 -0
  233. package/src/helpers/__tests__/getTextContent.test.tsx +49 -0
  234. package/src/helpers/__tests__/includeHiddenElements.test.tsx +39 -0
  235. package/src/helpers/__tests__/query-name.test.ts +10 -0
  236. package/src/helpers/__tests__/timers.test.ts +8 -0
  237. package/src/helpers/accessiblity.ts +108 -0
  238. package/src/helpers/component-tree.ts +89 -0
  239. package/src/helpers/debugDeep.ts +27 -0
  240. package/src/helpers/debugShallow.ts +22 -0
  241. package/src/helpers/deprecation.ts +53 -0
  242. package/src/helpers/errors.ts +66 -0
  243. package/src/helpers/filterNodeByType.ts +7 -0
  244. package/src/helpers/findAll.ts +68 -0
  245. package/src/helpers/format-default.ts +72 -0
  246. package/src/helpers/format.ts +47 -0
  247. package/src/helpers/getTextContent.ts +20 -0
  248. package/src/helpers/host-component-names.tsx +67 -0
  249. package/src/helpers/matchers/__tests__/matchArrayValue.test.ts +34 -0
  250. package/src/helpers/matchers/__tests__/matchObject.test.ts +37 -0
  251. package/src/helpers/matchers/__tests__/matchStringValue.test.ts +15 -0
  252. package/src/helpers/matchers/accessibilityState.ts +48 -0
  253. package/src/helpers/matchers/accessibilityValue.ts +24 -0
  254. package/src/helpers/matchers/matchArrayProp.ts +21 -0
  255. package/src/helpers/matchers/matchLabelText.ts +51 -0
  256. package/src/helpers/matchers/matchObjectProp.ts +25 -0
  257. package/src/helpers/matchers/matchStringProp.ts +23 -0
  258. package/src/helpers/matchers/matchTextContent.ts +20 -0
  259. package/src/helpers/pointer-events.ts +27 -0
  260. package/src/helpers/query-name.ts +4 -0
  261. package/src/helpers/stringValidation.ts +36 -0
  262. package/src/helpers/timers.ts +98 -0
  263. package/src/index.ts +33 -0
  264. package/src/matches.ts +49 -0
  265. package/src/pure.ts +25 -0
  266. package/src/queries/__tests__/a11yState.test.tsx +439 -0
  267. package/src/queries/__tests__/a11yValue.test.tsx +309 -0
  268. package/src/queries/__tests__/displayValue.test.tsx +221 -0
  269. package/src/queries/__tests__/hintText.test.tsx +177 -0
  270. package/src/queries/__tests__/labelText.test.tsx +242 -0
  271. package/src/queries/__tests__/makeQueries.test.tsx +235 -0
  272. package/src/queries/__tests__/placeholderText.test.tsx +136 -0
  273. package/src/queries/__tests__/role-value.test.tsx +176 -0
  274. package/src/queries/__tests__/role.test.tsx +824 -0
  275. package/src/queries/__tests__/testId.test.tsx +200 -0
  276. package/src/queries/__tests__/text.test.tsx +556 -0
  277. package/src/queries/a11yState.ts +131 -0
  278. package/src/queries/a11yValue.ts +131 -0
  279. package/src/queries/displayValue.ts +78 -0
  280. package/src/queries/hintText.ts +112 -0
  281. package/src/queries/labelText.ts +59 -0
  282. package/src/queries/makeQueries.ts +255 -0
  283. package/src/queries/options.ts +14 -0
  284. package/src/queries/placeholderText.ts +79 -0
  285. package/src/queries/role.ts +132 -0
  286. package/src/queries/testId.ts +71 -0
  287. package/src/queries/text.ts +66 -0
  288. package/src/queries/unsafeProps.ts +76 -0
  289. package/src/queries/unsafeType.ts +73 -0
  290. package/src/react-versions.ts +11 -0
  291. package/src/render-act.ts +19 -0
  292. package/src/render.tsx +183 -0
  293. package/src/renderHook.tsx +56 -0
  294. package/src/screen.ts +123 -0
  295. package/src/shallow.ts +18 -0
  296. package/src/test-utils/events.ts +24 -0
  297. package/src/test-utils/index.ts +1 -0
  298. package/src/user-event/event-builder/common.ts +50 -0
  299. package/src/user-event/event-builder/index.ts +5 -0
  300. package/src/user-event/index.ts +14 -0
  301. package/src/user-event/press/__tests__/longPress.real-timers.test.tsx +115 -0
  302. package/src/user-event/press/__tests__/longPress.test.tsx +157 -0
  303. package/src/user-event/press/__tests__/press.real-timers.test.tsx +318 -0
  304. package/src/user-event/press/__tests__/press.test.tsx +422 -0
  305. package/src/user-event/press/constants.ts +7 -0
  306. package/src/user-event/press/index.ts +1 -0
  307. package/src/user-event/press/press.ts +134 -0
  308. package/src/user-event/press/utils/warnAboutRealTimers.ts +6 -0
  309. package/src/user-event/setup/index.ts +2 -0
  310. package/src/user-event/setup/setup.ts +93 -0
  311. package/src/user-event/type/__tests__/__snapshots__/type.test.tsx.snap +26 -0
  312. package/src/user-event/type/__tests__/type.test.tsx +63 -0
  313. package/src/user-event/type/index.ts +1 -0
  314. package/src/user-event/type/type.ts +20 -0
  315. package/src/user-event/utils/__tests__/wait.test.ts +63 -0
  316. package/src/user-event/utils/events.ts +54 -0
  317. package/src/user-event/utils/index.ts +2 -0
  318. package/src/user-event/utils/wait.ts +15 -0
  319. package/src/waitFor.ts +228 -0
  320. package/src/waitForElementToBeRemoved.ts +42 -0
  321. package/src/within.ts +30 -0
  322. package/tsconfig.json +17 -0
  323. package/tsconfig.release.json +8 -0
  324. package/website/.gitignore +20 -0
  325. package/website/README.md +33 -0
  326. package/website/docker/.dockerignore +3 -0
  327. package/website/docker/Dockerfile +9 -0
  328. package/website/docker/docker-compose.yml +11 -0
  329. package/website/docs/API.md +946 -0
  330. package/website/docs/EslintPLluginTestingLibrary.md +28 -0
  331. package/website/docs/FAQ.md +44 -0
  332. package/website/docs/GettingStarted.md +100 -0
  333. package/website/docs/HowShouldIQuery.md +21 -0
  334. package/website/docs/MigrationV11.md +64 -0
  335. package/website/docs/MigrationV12.md +67 -0
  336. package/website/docs/MigrationV2.md +126 -0
  337. package/website/docs/MigrationV7.md +119 -0
  338. package/website/docs/MigrationV9.md +67 -0
  339. package/website/docs/Queries.md +567 -0
  340. package/website/docs/ReactNavigation.md +371 -0
  341. package/website/docs/ReduxIntegration.md +137 -0
  342. package/website/docs/TestingEnvironment.md +154 -0
  343. package/website/docs/Troubleshooting.md +44 -0
  344. package/website/docs/UnderstandingAct.md +227 -0
  345. package/website/docs/UserEvent.md +66 -0
  346. package/website/docusaurus.config.js +114 -0
  347. package/website/package.json +31 -0
  348. package/website/sidebars.js +20 -0
  349. package/website/src/components/Feature.js +31 -0
  350. package/website/src/css/custom.css +13 -0
  351. package/website/src/css/index.module.css +77 -0
  352. package/website/src/pages/index.js +82 -0
  353. package/website/static/.nojekyll +0 -0
  354. package/website/static/css/custom.css +28 -0
  355. package/website/static/img/hit.png +0 -0
  356. package/website/static/img/locomotive.png +0 -0
  357. package/website/static/img/owl.png +0 -0
  358. package/website/static/img/tools.png +0 -0
  359. package/website/yarn.lock +7669 -0
  360. package/yarn.lock +7765 -0
  361. package/build/flushMicroTasks.d.ts +0 -5
  362. package/build/flushMicroTasks.js +0 -17
  363. package/build/flushMicroTasks.js.map +0 -1
@@ -0,0 +1,422 @@
1
+ import * as React from 'react';
2
+ import {
3
+ Pressable,
4
+ Text,
5
+ TextInput,
6
+ TouchableHighlight,
7
+ TouchableOpacity,
8
+ View,
9
+ } from 'react-native';
10
+ import { createEventLogger, getEventsName } from '../../../test-utils';
11
+ import { render, screen } from '../../..';
12
+ import { userEvent } from '../..';
13
+
14
+ describe('userEvent.press with fake timers', () => {
15
+ beforeEach(() => {
16
+ jest.useFakeTimers();
17
+ jest.setSystemTime(0);
18
+ });
19
+
20
+ test('calls onPressIn, onPress and onPressOut prop of touchable', async () => {
21
+ const { events, logEvent } = createEventLogger();
22
+ const user = userEvent.setup();
23
+
24
+ render(
25
+ <Pressable
26
+ onPress={logEvent('press')}
27
+ onPressIn={logEvent('pressIn')}
28
+ onPressOut={logEvent('pressOut')}
29
+ onLongPress={logEvent('longPress')}
30
+ testID="pressable"
31
+ />
32
+ );
33
+ await user.press(screen.getByTestId('pressable'));
34
+
35
+ expect(events).toMatchInlineSnapshot(`
36
+ [
37
+ {
38
+ "name": "pressIn",
39
+ "payload": {
40
+ "currentTarget": {
41
+ "measure": [MockFunction] {
42
+ "calls": [
43
+ [
44
+ [Function],
45
+ ],
46
+ [
47
+ [Function],
48
+ ],
49
+ ],
50
+ "results": [
51
+ {
52
+ "type": "return",
53
+ "value": undefined,
54
+ },
55
+ {
56
+ "type": "return",
57
+ "value": undefined,
58
+ },
59
+ ],
60
+ },
61
+ },
62
+ "dispatchConfig": {
63
+ "registrationName": "onResponderGrant",
64
+ },
65
+ "nativeEvent": {
66
+ "changedTouches": [],
67
+ "identifier": 0,
68
+ "locationX": 0,
69
+ "locationY": 0,
70
+ "pageX": 0,
71
+ "pageY": 0,
72
+ "target": 0,
73
+ "timestamp": 0,
74
+ "touches": [],
75
+ },
76
+ "persist": [MockFunction] {
77
+ "calls": [
78
+ [],
79
+ ],
80
+ "results": [
81
+ {
82
+ "type": "return",
83
+ "value": undefined,
84
+ },
85
+ ],
86
+ },
87
+ },
88
+ },
89
+ {
90
+ "name": "press",
91
+ "payload": {
92
+ "currentTarget": {
93
+ "measure": [MockFunction],
94
+ },
95
+ "dispatchConfig": {
96
+ "registrationName": "onResponderRelease",
97
+ },
98
+ "nativeEvent": {
99
+ "changedTouches": [],
100
+ "identifier": 0,
101
+ "locationX": 0,
102
+ "locationY": 0,
103
+ "pageX": 0,
104
+ "pageY": 0,
105
+ "target": 0,
106
+ "timestamp": 0,
107
+ "touches": [],
108
+ },
109
+ "persist": [MockFunction] {
110
+ "calls": [
111
+ [],
112
+ ],
113
+ "results": [
114
+ {
115
+ "type": "return",
116
+ "value": undefined,
117
+ },
118
+ ],
119
+ },
120
+ },
121
+ },
122
+ {
123
+ "name": "pressOut",
124
+ "payload": {
125
+ "currentTarget": {
126
+ "measure": [MockFunction],
127
+ },
128
+ "dispatchConfig": {
129
+ "registrationName": "onResponderRelease",
130
+ },
131
+ "nativeEvent": {
132
+ "changedTouches": [],
133
+ "identifier": 0,
134
+ "locationX": 0,
135
+ "locationY": 0,
136
+ "pageX": 0,
137
+ "pageY": 0,
138
+ "target": 0,
139
+ "timestamp": 0,
140
+ "touches": [],
141
+ },
142
+ "persist": [MockFunction] {
143
+ "calls": [
144
+ [],
145
+ ],
146
+ "results": [
147
+ {
148
+ "type": "return",
149
+ "value": undefined,
150
+ },
151
+ ],
152
+ },
153
+ },
154
+ },
155
+ ]
156
+ `);
157
+ });
158
+
159
+ test('does not trigger event when pressable is disabled', async () => {
160
+ const { events, logEvent } = createEventLogger();
161
+ const user = userEvent.setup();
162
+
163
+ render(
164
+ <Pressable
165
+ disabled
166
+ onPress={logEvent('press')}
167
+ onPressIn={logEvent('pressIn')}
168
+ onPressOut={logEvent('pressOut')}
169
+ onLongPress={logEvent('longPress')}
170
+ testID="pressable"
171
+ />
172
+ );
173
+ await user.press(screen.getByTestId('pressable'));
174
+
175
+ expect(events).toEqual([]);
176
+ });
177
+
178
+ test('does not call press when pointer events is none', async () => {
179
+ const { events, logEvent } = createEventLogger();
180
+ const user = userEvent.setup();
181
+
182
+ render(
183
+ <Pressable
184
+ onPress={logEvent('press')}
185
+ onPressIn={logEvent('pressIn')}
186
+ onPressOut={logEvent('pressOut')}
187
+ onLongPress={logEvent('longPress')}
188
+ testID="pressable"
189
+ pointerEvents="none"
190
+ />
191
+ );
192
+ await user.press(screen.getByTestId('pressable'));
193
+
194
+ expect(events).toEqual([]);
195
+ });
196
+
197
+ test('does not call press when pointer events is box-none', async () => {
198
+ const { events, logEvent } = createEventLogger();
199
+ const user = userEvent.setup();
200
+
201
+ render(
202
+ <Pressable
203
+ onPress={logEvent('press')}
204
+ onPressIn={logEvent('pressIn')}
205
+ onPressOut={logEvent('pressOut')}
206
+ onLongPress={logEvent('longPress')}
207
+ testID="pressable"
208
+ pointerEvents="box-none"
209
+ />
210
+ );
211
+ await user.press(screen.getByTestId('pressable'));
212
+
213
+ expect(events).toEqual([]);
214
+ });
215
+
216
+ test('does not call press when parent has pointer events box-only', async () => {
217
+ const { events, logEvent } = createEventLogger();
218
+ const user = userEvent.setup();
219
+
220
+ render(
221
+ <View pointerEvents="box-only">
222
+ <Pressable
223
+ onPress={logEvent('press')}
224
+ onPressIn={logEvent('pressIn')}
225
+ onPressOut={logEvent('pressOut')}
226
+ onLongPress={logEvent('longPress')}
227
+ testID="pressable"
228
+ />
229
+ </View>
230
+ );
231
+ await user.press(screen.getByTestId('pressable'));
232
+
233
+ expect(events).toEqual([]);
234
+ });
235
+
236
+ test('calls press when pressable has pointer events box-only', async () => {
237
+ const { events, logEvent } = createEventLogger();
238
+ const user = userEvent.setup();
239
+
240
+ render(
241
+ <Pressable
242
+ onPress={logEvent('press')}
243
+ onPressIn={logEvent('pressIn')}
244
+ onPressOut={logEvent('pressOut')}
245
+ onLongPress={logEvent('longPress')}
246
+ testID="pressable"
247
+ pointerEvents="box-only"
248
+ />
249
+ );
250
+ await user.press(screen.getByTestId('pressable'));
251
+
252
+ expect(getEventsName(events)).toEqual(['pressIn', 'press', 'pressOut']);
253
+ });
254
+
255
+ test('crawls up in the tree to find an element that responds to touch events', async () => {
256
+ const mockOnPress = jest.fn();
257
+
258
+ render(
259
+ <Pressable onPress={mockOnPress}>
260
+ <Text>press me</Text>
261
+ </Pressable>
262
+ );
263
+ await userEvent.press(screen.getByText('press me'));
264
+
265
+ expect(mockOnPress).toHaveBeenCalled();
266
+ });
267
+
268
+ test('does not call onLongPress', async () => {
269
+ const mockOnLongPress = jest.fn();
270
+
271
+ render(
272
+ <Pressable onLongPress={mockOnLongPress}>
273
+ <Text>press me</Text>
274
+ </Pressable>
275
+ );
276
+ await userEvent.press(screen.getByText('press me'));
277
+
278
+ expect(mockOnLongPress).not.toHaveBeenCalled();
279
+ });
280
+
281
+ test('works on TouchableOpacity', async () => {
282
+ const mockOnPress = jest.fn();
283
+
284
+ render(
285
+ <TouchableOpacity onPress={mockOnPress}>
286
+ <Text>press me</Text>
287
+ </TouchableOpacity>
288
+ );
289
+ await userEvent.press(screen.getByText('press me'));
290
+
291
+ expect(mockOnPress).toHaveBeenCalled();
292
+ });
293
+
294
+ test('works on TouchableHighlight', async () => {
295
+ const mockOnPress = jest.fn();
296
+
297
+ render(
298
+ <TouchableHighlight onPress={mockOnPress}>
299
+ <Text>press me</Text>
300
+ </TouchableHighlight>
301
+ );
302
+ await userEvent.press(screen.getByText('press me'));
303
+
304
+ expect(mockOnPress).toHaveBeenCalled();
305
+ });
306
+
307
+ test('works on Text', async () => {
308
+ const { events, logEvent } = createEventLogger();
309
+
310
+ render(
311
+ <Text
312
+ onPress={logEvent('press')}
313
+ onPressIn={logEvent('pressIn')}
314
+ onPressOut={logEvent('pressOut')}
315
+ onLongPress={logEvent('longPress')}
316
+ >
317
+ press me
318
+ </Text>
319
+ );
320
+ await userEvent.press(screen.getByText('press me'));
321
+
322
+ expect(getEventsName(events)).toEqual(['pressIn', 'press', 'pressOut']);
323
+ });
324
+
325
+ test('doesnt trigger on disabled Text', async () => {
326
+ const { events, logEvent } = createEventLogger();
327
+
328
+ render(
329
+ <Text
330
+ onPress={logEvent('press')}
331
+ onPressIn={logEvent('pressIn')}
332
+ onPressOut={logEvent('pressOut')}
333
+ onLongPress={logEvent('longPress')}
334
+ disabled
335
+ >
336
+ press me
337
+ </Text>
338
+ );
339
+ await userEvent.press(screen.getByText('press me'));
340
+
341
+ expect(events).toEqual([]);
342
+ });
343
+
344
+ test('doesnt trigger on Text with disabled pointer events', async () => {
345
+ const { events, logEvent } = createEventLogger();
346
+
347
+ render(
348
+ <View pointerEvents="box-only">
349
+ <Text
350
+ onPress={logEvent('press')}
351
+ onPressIn={logEvent('pressIn')}
352
+ onPressOut={logEvent('pressOut')}
353
+ onLongPress={logEvent('longPress')}
354
+ >
355
+ press me
356
+ </Text>
357
+ </View>
358
+ );
359
+ await userEvent.press(screen.getByText('press me'));
360
+
361
+ expect(events).toEqual([]);
362
+ });
363
+
364
+ test('works on TetInput', async () => {
365
+ const { events, logEvent } = createEventLogger();
366
+
367
+ render(
368
+ <TextInput
369
+ placeholder="email"
370
+ onPressIn={logEvent('pressIn')}
371
+ onPressOut={logEvent('pressOut')}
372
+ />
373
+ );
374
+ await userEvent.press(screen.getByPlaceholderText('email'));
375
+
376
+ expect(getEventsName(events)).toEqual(['pressIn', 'pressOut']);
377
+ });
378
+
379
+ test('does not call onPressIn and onPressOut on non editable TetInput', async () => {
380
+ const { events, logEvent } = createEventLogger();
381
+
382
+ render(
383
+ <TextInput
384
+ placeholder="email"
385
+ editable={false}
386
+ onPressIn={logEvent('pressIn')}
387
+ onPressOut={logEvent('pressOut')}
388
+ />
389
+ );
390
+ await userEvent.press(screen.getByPlaceholderText('email'));
391
+ expect(events).toEqual([]);
392
+ });
393
+
394
+ test('does not call onPressIn and onPressOut on TetInput with pointer events disabled', async () => {
395
+ const { events, logEvent } = createEventLogger();
396
+
397
+ render(
398
+ <TextInput
399
+ placeholder="email"
400
+ pointerEvents="box-none"
401
+ onPressIn={logEvent('pressIn')}
402
+ onPressOut={logEvent('pressOut')}
403
+ />
404
+ );
405
+ await userEvent.press(screen.getByPlaceholderText('email'));
406
+ expect(events).toEqual([]);
407
+ });
408
+
409
+ test('press is accessible directly in userEvent', async () => {
410
+ const mockOnPress = jest.fn();
411
+
412
+ render(
413
+ <Pressable onPress={mockOnPress}>
414
+ <Text>press me</Text>
415
+ </Pressable>
416
+ );
417
+
418
+ await userEvent.press(screen.getByText('press me'));
419
+
420
+ expect(mockOnPress).toHaveBeenCalled();
421
+ });
422
+ });
@@ -0,0 +1,7 @@
1
+ // These are constants defined in the React Native repo
2
+
3
+ // Used to define the delay before calling onPressOut after a press
4
+ export const DEFAULT_MIN_PRESS_DURATION = 130;
5
+
6
+ // Default minimum press duration to trigger a long press
7
+ export const DEFAULT_LONG_PRESS_DELAY_MS = 500;
@@ -0,0 +1 @@
1
+ export { press, longPress } from './press';
@@ -0,0 +1,134 @@
1
+ import { ReactTestInstance } from 'react-test-renderer';
2
+ import { EventBuilder } from '../event-builder';
3
+ import { UserEventInstance } from '../setup';
4
+ import { wait } from '../utils';
5
+ import act from '../../act';
6
+ import { getHostParent } from '../../helpers/component-tree';
7
+ import { filterNodeByType } from '../../helpers/filterNodeByType';
8
+ import { isPointerEventEnabled } from '../../helpers/pointer-events';
9
+ import { getHostComponentNames } from '../../helpers/host-component-names';
10
+ import { jestFakeTimersAreEnabled } from '../../helpers/timers';
11
+ import { DEFAULT_MIN_PRESS_DURATION } from './constants';
12
+ import { warnAboutRealTimers } from './utils/warnAboutRealTimers';
13
+
14
+ export type PressOptions = {
15
+ duration: number;
16
+ };
17
+
18
+ export async function press(
19
+ this: UserEventInstance,
20
+ element: ReactTestInstance
21
+ ): Promise<void> {
22
+ await basePress(this.config, element);
23
+ }
24
+
25
+ export async function longPress(
26
+ this: UserEventInstance,
27
+ element: ReactTestInstance,
28
+ options: PressOptions = { duration: 500 }
29
+ ): Promise<void> {
30
+ await basePress(this.config, element, options);
31
+ }
32
+
33
+ const basePress = async (
34
+ config: UserEventInstance['config'],
35
+ element: ReactTestInstance,
36
+ options: PressOptions = { duration: 0 }
37
+ ): Promise<void> => {
38
+ // Text and TextInput components are mocked in React Native preset so the mock
39
+ // doesn't implement the pressability class
40
+ // Thus we need to call the props directly on the host component
41
+ if (isEnabledHostText(element) || isEnabledTextInput(element)) {
42
+ await triggerMockPressEvent(config, element, options);
43
+ return;
44
+ }
45
+
46
+ if (isEnabledTouchResponder(element)) {
47
+ await triggerPressEvent(config, element, options);
48
+ return;
49
+ }
50
+
51
+ const hostParentElement = getHostParent(element);
52
+ if (!hostParentElement) {
53
+ return;
54
+ }
55
+
56
+ await basePress(config, hostParentElement, options);
57
+ };
58
+
59
+ const triggerPressEvent = async (
60
+ config: UserEventInstance['config'],
61
+ element: ReactTestInstance,
62
+ options: PressOptions = { duration: 0 }
63
+ ) => {
64
+ const areFakeTimersEnabled = jestFakeTimersAreEnabled();
65
+ if (!areFakeTimersEnabled) {
66
+ warnAboutRealTimers();
67
+ }
68
+
69
+ await wait(config);
70
+
71
+ await act(async () => {
72
+ element.props.onResponderGrant({
73
+ ...EventBuilder.Common.touch(),
74
+ dispatchConfig: { registrationName: 'onResponderGrant' },
75
+ });
76
+
77
+ await wait(config, options.duration);
78
+
79
+ element.props.onResponderRelease({
80
+ ...EventBuilder.Common.touch(),
81
+ dispatchConfig: { registrationName: 'onResponderRelease' },
82
+ });
83
+
84
+ if (DEFAULT_MIN_PRESS_DURATION - options.duration > 0) {
85
+ await wait(config, DEFAULT_MIN_PRESS_DURATION - options.duration);
86
+ }
87
+ });
88
+ };
89
+
90
+ const isEnabledTouchResponder = (element: ReactTestInstance) => {
91
+ return (
92
+ isPointerEventEnabled(element) &&
93
+ element.props.onStartShouldSetResponder?.()
94
+ );
95
+ };
96
+
97
+ const isEnabledHostText = (element: ReactTestInstance) => {
98
+ return (
99
+ filterNodeByType(element, getHostComponentNames().text) &&
100
+ isPointerEventEnabled(element) &&
101
+ !element.props.disabled &&
102
+ element.props.onPress
103
+ );
104
+ };
105
+
106
+ const isEnabledTextInput = (element: ReactTestInstance) => {
107
+ return (
108
+ filterNodeByType(element, getHostComponentNames().textInput) &&
109
+ isPointerEventEnabled(element) &&
110
+ element.props.editable !== false
111
+ );
112
+ };
113
+
114
+ const triggerMockPressEvent = async (
115
+ config: UserEventInstance['config'],
116
+ element: ReactTestInstance,
117
+ options: PressOptions = { duration: 0 }
118
+ ) => {
119
+ const { onPressIn, onPress, onPressOut } = element.props;
120
+ await wait(config);
121
+ if (onPressIn) {
122
+ onPressIn(EventBuilder.Common.touch());
123
+ }
124
+ if (onPress) {
125
+ onPress(EventBuilder.Common.touch());
126
+ }
127
+ await wait(config, options.duration);
128
+ if (onPressOut) {
129
+ if (DEFAULT_MIN_PRESS_DURATION - options.duration > 0) {
130
+ await wait(config, DEFAULT_MIN_PRESS_DURATION - options.duration);
131
+ }
132
+ onPressOut(EventBuilder.Common.touch());
133
+ }
134
+ };
@@ -0,0 +1,6 @@
1
+ export const warnAboutRealTimers = () => {
2
+ // eslint-disable-next-line no-console
3
+ console.warn(`It is recommended to use userEvent with fake timers
4
+ Some events involve duration so your tests may take a long time to run.
5
+ For instance calling userEvent.longPress with real timers will take 500 ms.`);
6
+ };
@@ -0,0 +1,2 @@
1
+ export type { UserEventConfig, UserEventInstance } from './setup';
2
+ export { setup } from './setup';
@@ -0,0 +1,93 @@
1
+ import { ReactTestInstance } from 'react-test-renderer';
2
+ import { jestFakeTimersAreEnabled } from '../../helpers/timers';
3
+ import { press, longPress } from '../press';
4
+ import { type } from '../type';
5
+ import { PressOptions } from '../press/press';
6
+
7
+ export interface UserEventSetupOptions {
8
+ /**
9
+ * Between some subsequent inputs like typing a series of characters
10
+ * the code execution is delayed per `setTimeout` for (at least) `delay` seconds.
11
+ * This moves the next changes at least to next macro task
12
+ * and allows other (asynchronous) code to run between events.
13
+ *
14
+ * `null` prevents `setTimeout` from being called.
15
+ *
16
+ * @default 0
17
+ */
18
+ delay?: number;
19
+
20
+ /**
21
+ * Function to be called to advance fake timers. Setting it is necessary for
22
+ * fake timers to work.
23
+ *
24
+ * @example jest.advanceTimersByTime
25
+ */
26
+ advanceTimers?: (delay: number) => Promise<void> | void;
27
+ }
28
+
29
+ /**
30
+ * This functions allow wait to work correctly under both real and fake Jest timers.
31
+ */
32
+ function universalJestAdvanceTimersBy(ms: number) {
33
+ if (jestFakeTimersAreEnabled()) {
34
+ return jest.advanceTimersByTime(ms);
35
+ } else {
36
+ return Promise.resolve();
37
+ }
38
+ }
39
+
40
+ const defaultOptions: Required<UserEventSetupOptions> = {
41
+ delay: 0,
42
+ advanceTimers: universalJestAdvanceTimersBy,
43
+ };
44
+
45
+ /**
46
+ * Creates a new instance of user event instance with the given options.
47
+ *
48
+ * @param options
49
+ * @returns
50
+ */
51
+ export function setup(options?: UserEventSetupOptions) {
52
+ const config = createConfig(options);
53
+ const instance = createInstance(config);
54
+ return instance;
55
+ }
56
+
57
+ export interface UserEventConfig {
58
+ delay: number;
59
+ advanceTimers: (delay: number) => Promise<void> | void;
60
+ }
61
+
62
+ function createConfig(options?: UserEventSetupOptions): UserEventConfig {
63
+ return {
64
+ ...defaultOptions,
65
+ ...options,
66
+ };
67
+ }
68
+
69
+ export interface UserEventInstance {
70
+ config: UserEventConfig;
71
+ press: (element: ReactTestInstance) => Promise<void>;
72
+ longPress: (
73
+ element: ReactTestInstance,
74
+ options?: PressOptions
75
+ ) => Promise<void>;
76
+ type: (element: ReactTestInstance, text: string) => Promise<void>;
77
+ }
78
+
79
+ function createInstance(config: UserEventConfig): UserEventInstance {
80
+ const instance = {
81
+ config,
82
+ } as UserEventInstance;
83
+
84
+ // We need to bind these functions, as they access the config through 'this.config'.
85
+ const api = {
86
+ press: press.bind(instance),
87
+ longPress: longPress.bind(instance),
88
+ type: type.bind(instance),
89
+ };
90
+
91
+ Object.assign(instance, api);
92
+ return instance;
93
+ }
@@ -0,0 +1,26 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`user.type() dispatches required events 1`] = `
4
+ [
5
+ {
6
+ "name": "focus",
7
+ "payload": {
8
+ "nativeEvent": {
9
+ "target": 0,
10
+ },
11
+ },
12
+ },
13
+ {
14
+ "name": "changeText",
15
+ "payload": "Hello World!",
16
+ },
17
+ {
18
+ "name": "blur",
19
+ "payload": {
20
+ "nativeEvent": {
21
+ "target": 0,
22
+ },
23
+ },
24
+ },
25
+ ]
26
+ `;