@testing-library/react-native 12.1.3 → 12.2.0

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 (262) hide show
  1. package/.DS_Store +0 -0
  2. package/.eslintcache +1 -1
  3. package/build/fireEvent.js +3 -6
  4. package/build/fireEvent.js.map +1 -1
  5. package/build/helpers/deprecation.js +1 -1
  6. package/build/helpers/deprecation.js.map +1 -1
  7. package/build/helpers/host-component-names.d.ts +3 -0
  8. package/build/helpers/host-component-names.js +8 -0
  9. package/build/helpers/host-component-names.js.map +1 -1
  10. package/build/pure.d.ts +2 -0
  11. package/build/pure.js +7 -0
  12. package/build/pure.js.map +1 -1
  13. package/build/user-event/event-builder/common.d.ts +48 -6
  14. package/build/user-event/event-builder/common.js +37 -20
  15. package/build/user-event/event-builder/common.js.map +1 -1
  16. package/build/user-event/event-builder/index.d.ts +94 -0
  17. package/build/user-event/event-builder/index.js +3 -1
  18. package/build/user-event/event-builder/index.js.map +1 -1
  19. package/build/user-event/event-builder/text-input.d.ts +91 -0
  20. package/build/user-event/event-builder/text-input.js +117 -0
  21. package/build/user-event/event-builder/text-input.js.map +1 -0
  22. package/build/user-event/index.d.ts +4 -2
  23. package/build/user-event/index.js +7 -1
  24. package/build/user-event/index.js.map +1 -1
  25. package/build/user-event/press/index.d.ts +1 -1
  26. package/build/user-event/press/index.js +6 -0
  27. package/build/user-event/press/index.js.map +1 -1
  28. package/build/user-event/press/press.d.ts +3 -3
  29. package/build/user-event/press/press.js +55 -62
  30. package/build/user-event/press/press.js.map +1 -1
  31. package/build/user-event/setup/setup.d.ts +33 -3
  32. package/build/user-event/setup/setup.js +14 -1
  33. package/build/user-event/setup/setup.js.map +1 -1
  34. package/build/user-event/type/index.d.ts +1 -1
  35. package/build/user-event/type/index.js +6 -0
  36. package/build/user-event/type/index.js.map +1 -1
  37. package/build/user-event/type/parseKeys.d.ts +1 -0
  38. package/build/user-event/type/parseKeys.js +40 -0
  39. package/build/user-event/type/parseKeys.js.map +1 -0
  40. package/build/user-event/type/type.d.ts +5 -1
  41. package/build/user-event/type/type.js +66 -8
  42. package/build/user-event/type/type.js.map +1 -1
  43. package/build/user-event/utils/content-size.d.ts +15 -0
  44. package/build/user-event/utils/content-size.js +26 -0
  45. package/build/user-event/utils/content-size.js.map +1 -0
  46. package/build/user-event/utils/{events.d.ts → dispatch-event.d.ts} +2 -2
  47. package/build/user-event/utils/dispatch-event.js +36 -0
  48. package/build/user-event/utils/dispatch-event.js.map +1 -0
  49. package/build/user-event/utils/index.d.ts +4 -1
  50. package/build/user-event/utils/index.js +37 -4
  51. package/build/user-event/utils/index.js.map +1 -1
  52. package/build/user-event/utils/text-range.d.ts +5 -0
  53. package/build/user-event/utils/text-range.js +13 -0
  54. package/build/user-event/utils/text-range.js.map +1 -0
  55. package/build/user-event/utils/warn-about-real-timers.d.ts +1 -0
  56. package/build/user-event/utils/warn-about-real-timers.js +20 -0
  57. package/build/user-event/utils/warn-about-real-timers.js.map +1 -0
  58. package/coverage/clover.xml +1176 -0
  59. package/coverage/coverage-final.json +70 -0
  60. package/coverage/lcov-report/base.css +224 -0
  61. package/coverage/lcov-report/block-navigation.js +87 -0
  62. package/coverage/lcov-report/favicon.png +0 -0
  63. package/coverage/lcov-report/index.html +266 -0
  64. package/coverage/lcov-report/prettify.css +1 -0
  65. package/coverage/lcov-report/prettify.js +2 -0
  66. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  67. package/coverage/lcov-report/sorter.js +196 -0
  68. package/coverage/lcov-report/src/act.ts.html +343 -0
  69. package/coverage/lcov-report/src/cleanup.ts.html +130 -0
  70. package/coverage/lcov-report/src/config.ts.html +301 -0
  71. package/coverage/lcov-report/src/fireEvent.ts.html +559 -0
  72. package/coverage/lcov-report/src/flushMicroTasks.ts.html +124 -0
  73. package/coverage/lcov-report/src/helpers/accessiblity.ts.html +412 -0
  74. package/coverage/lcov-report/src/helpers/component-tree.ts.html +352 -0
  75. package/coverage/lcov-report/src/helpers/debugDeep.ts.html +166 -0
  76. package/coverage/lcov-report/src/helpers/debugShallow.ts.html +151 -0
  77. package/coverage/lcov-report/src/helpers/deprecation.ts.html +244 -0
  78. package/coverage/lcov-report/src/helpers/errors.ts.html +283 -0
  79. package/coverage/lcov-report/src/helpers/filterNodeByType.ts.html +106 -0
  80. package/coverage/lcov-report/src/helpers/findAll.ts.html +289 -0
  81. package/coverage/lcov-report/src/helpers/format-default.ts.html +301 -0
  82. package/coverage/lcov-report/src/helpers/format.ts.html +226 -0
  83. package/coverage/lcov-report/src/helpers/getTextContent.ts.html +145 -0
  84. package/coverage/lcov-report/src/helpers/host-component-names.tsx.html +286 -0
  85. package/coverage/lcov-report/src/helpers/index.html +326 -0
  86. package/coverage/lcov-report/src/helpers/matchers/accessibilityState.ts.html +229 -0
  87. package/coverage/lcov-report/src/helpers/matchers/accessibilityValue.ts.html +157 -0
  88. package/coverage/lcov-report/src/helpers/matchers/index.html +206 -0
  89. package/coverage/lcov-report/src/helpers/matchers/matchArrayProp.ts.html +148 -0
  90. package/coverage/lcov-report/src/helpers/matchers/matchLabelText.ts.html +238 -0
  91. package/coverage/lcov-report/src/helpers/matchers/matchObjectProp.ts.html +160 -0
  92. package/coverage/lcov-report/src/helpers/matchers/matchStringProp.ts.html +154 -0
  93. package/coverage/lcov-report/src/helpers/matchers/matchTextContent.ts.html +145 -0
  94. package/coverage/lcov-report/src/helpers/query-name.ts.html +97 -0
  95. package/coverage/lcov-report/src/helpers/stringValidation.ts.html +193 -0
  96. package/coverage/lcov-report/src/helpers/timers.ts.html +382 -0
  97. package/coverage/lcov-report/src/index.html +356 -0
  98. package/coverage/lcov-report/src/index.ts.html +184 -0
  99. package/coverage/lcov-report/src/matches.ts.html +232 -0
  100. package/coverage/lcov-report/src/pure.ts.html +157 -0
  101. package/coverage/lcov-report/src/queries/a11yState.ts.html +478 -0
  102. package/coverage/lcov-report/src/queries/a11yValue.ts.html +478 -0
  103. package/coverage/lcov-report/src/queries/displayValue.ts.html +319 -0
  104. package/coverage/lcov-report/src/queries/hintText.ts.html +421 -0
  105. package/coverage/lcov-report/src/queries/index.html +281 -0
  106. package/coverage/lcov-report/src/queries/labelText.ts.html +262 -0
  107. package/coverage/lcov-report/src/queries/makeQueries.ts.html +850 -0
  108. package/coverage/lcov-report/src/queries/placeholderText.ts.html +322 -0
  109. package/coverage/lcov-report/src/queries/role.ts.html +481 -0
  110. package/coverage/lcov-report/src/queries/testId.ts.html +298 -0
  111. package/coverage/lcov-report/src/queries/text.ts.html +283 -0
  112. package/coverage/lcov-report/src/queries/unsafeProps.ts.html +313 -0
  113. package/coverage/lcov-report/src/queries/unsafeType.ts.html +304 -0
  114. package/coverage/lcov-report/src/react-versions.ts.html +118 -0
  115. package/coverage/lcov-report/src/render-act.ts.html +142 -0
  116. package/coverage/lcov-report/src/render.tsx.html +592 -0
  117. package/coverage/lcov-report/src/renderHook.tsx.html +262 -0
  118. package/coverage/lcov-report/src/screen.ts.html +454 -0
  119. package/coverage/lcov-report/src/shallow.ts.html +139 -0
  120. package/coverage/lcov-report/src/test-utils/events.ts.html +145 -0
  121. package/coverage/lcov-report/src/test-utils/index.html +131 -0
  122. package/coverage/lcov-report/src/test-utils/index.ts.html +88 -0
  123. package/coverage/lcov-report/src/user-event/event-builder/common.ts.html +229 -0
  124. package/coverage/lcov-report/src/user-event/event-builder/index.html +146 -0
  125. package/coverage/lcov-report/src/user-event/event-builder/index.ts.html +106 -0
  126. package/coverage/lcov-report/src/user-event/event-builder/test-input.ts.html +343 -0
  127. package/coverage/lcov-report/src/user-event/event-builder/text-input.ts.html +343 -0
  128. package/coverage/lcov-report/src/user-event/index.html +116 -0
  129. package/coverage/lcov-report/src/user-event/index.ts.html +121 -0
  130. package/coverage/lcov-report/src/user-event/press/index.html +131 -0
  131. package/coverage/lcov-report/src/user-event/press/index.ts.html +88 -0
  132. package/coverage/lcov-report/src/user-event/press/press.ts.html +133 -0
  133. package/coverage/lcov-report/src/user-event/setup/index.html +131 -0
  134. package/coverage/lcov-report/src/user-event/setup/index.ts.html +91 -0
  135. package/coverage/lcov-report/src/user-event/setup/setup.ts.html +358 -0
  136. package/coverage/lcov-report/src/user-event/type/index.html +146 -0
  137. package/coverage/lcov-report/src/user-event/type/index.ts.html +88 -0
  138. package/coverage/lcov-report/src/user-event/type/parseKeys.ts.html +208 -0
  139. package/coverage/lcov-report/src/user-event/type/type.ts.html +484 -0
  140. package/coverage/lcov-report/src/user-event/utils/content-size.ts.html +160 -0
  141. package/coverage/lcov-report/src/user-event/utils/dispatch-event.ts.html +367 -0
  142. package/coverage/lcov-report/src/user-event/utils/events.ts.html +247 -0
  143. package/coverage/lcov-report/src/user-event/utils/index.html +176 -0
  144. package/coverage/lcov-report/src/user-event/utils/index.ts.html +97 -0
  145. package/coverage/lcov-report/src/user-event/utils/text-range.ts.html +118 -0
  146. package/coverage/lcov-report/src/user-event/utils/wait.ts.html +130 -0
  147. package/coverage/lcov-report/src/waitFor.ts.html +772 -0
  148. package/coverage/lcov-report/src/waitForElementToBeRemoved.ts.html +211 -0
  149. package/coverage/lcov-report/src/within.ts.html +175 -0
  150. package/coverage/lcov.info +2614 -0
  151. package/examples/.DS_Store +0 -0
  152. package/examples/basic/.expo/README.md +17 -0
  153. package/examples/basic/.expo/devices.json +3 -0
  154. package/examples/basic/.expo/packager-info.json +4 -0
  155. package/examples/basic/.expo/settings.json +8 -0
  156. package/examples/basic/package.json +7 -7
  157. package/examples/basic/yarn-error.log +8083 -0
  158. package/examples/basic/yarn.lock +8878 -0
  159. package/examples/react-navigation/README.md +2 -0
  160. package/examples/react-navigation/package.json +5 -5
  161. package/examples/react-navigation/yarn.lock +5610 -0
  162. package/examples/redux/README.md +5 -0
  163. package/examples/redux/package.json +7 -7
  164. package/examples/redux/yarn-error.log +8083 -0
  165. package/examples/redux/yarn.lock +8423 -0
  166. package/experiments-app/.expo/settings.json +2 -1
  167. package/experiments-app/src/screens/TextInputEvents.tsx +10 -0
  168. package/package.json +1 -1
  169. package/src/.DS_Store +0 -0
  170. package/src/__tests__/.DS_Store +0 -0
  171. package/src/__tests__/act.test.tsx +4 -0
  172. package/src/fireEvent.ts +2 -6
  173. package/src/helpers/deprecation.ts +1 -1
  174. package/src/helpers/host-component-names.tsx +8 -0
  175. package/src/pure.ts +2 -0
  176. package/src/user-event/event-builder/common.ts +35 -19
  177. package/src/user-event/event-builder/index.ts +2 -0
  178. package/src/user-event/event-builder/text-input.ts +86 -0
  179. package/src/user-event/index.ts +6 -3
  180. package/src/user-event/press/__tests__/longPress.real-timers.test.tsx +4 -2
  181. package/src/user-event/press/__tests__/press.real-timers.test.tsx +4 -2
  182. package/src/user-event/press/__tests__/press.test.tsx +40 -5
  183. package/src/user-event/press/index.ts +1 -1
  184. package/src/user-event/press/press.ts +93 -58
  185. package/src/user-event/setup/setup.ts +39 -5
  186. package/src/user-event/type/__tests__/__snapshots__/type-managed.test.tsx.snap +339 -0
  187. package/src/user-event/type/__tests__/__snapshots__/type.test.tsx.snap +644 -2
  188. package/src/user-event/type/__tests__/parseKeys.test.ts +23 -0
  189. package/src/user-event/type/__tests__/type-managed.test.tsx +121 -0
  190. package/src/user-event/type/__tests__/type.test.tsx +300 -27
  191. package/src/user-event/type/index.ts +1 -1
  192. package/src/user-event/type/parseKeys.ts +41 -0
  193. package/src/user-event/type/type.ts +125 -10
  194. package/src/user-event/utils/__tests__/dispatch-event.test.tsx +41 -0
  195. package/src/user-event/utils/content-size.ts +25 -0
  196. package/src/user-event/utils/dispatch-event.ts +38 -0
  197. package/src/user-event/utils/index.ts +4 -1
  198. package/src/user-event/utils/text-range.ts +11 -0
  199. package/src/user-event/{press/utils/warnAboutRealTimers.ts → utils/warn-about-real-timers.ts} +8 -1
  200. package/website/.DS_Store +0 -0
  201. package/website/.docusaurus/DONT-EDIT-THIS-FOLDER +5 -0
  202. package/website/.docusaurus/client-modules.js +6 -0
  203. package/website/.docusaurus/codeTranslations.json +1 -0
  204. package/website/.docusaurus/docusaurus-plugin-content-blog/default/blog-post-list-prop-default.json +4 -0
  205. package/website/.docusaurus/docusaurus-plugin-content-blog/default/plugin-route-context-module-100.json +4 -0
  206. package/website/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json +4 -0
  207. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-api-md-c82.json +27 -0
  208. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-eslint-p-llugin-testing-library-md-d24.json +27 -0
  209. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-faq-md-ad8.json +27 -0
  210. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-getting-started-md-8a6.json +23 -0
  211. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-how-should-i-query-md-f2d.json +27 -0
  212. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-migration-v-11-md-add.json +27 -0
  213. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-migration-v-12-md-14f.json +27 -0
  214. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-migration-v-2-md-698.json +27 -0
  215. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-migration-v-7-md-6bb.json +27 -0
  216. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-migration-v-9-md-f69.json +27 -0
  217. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-queries-md-7ad.json +27 -0
  218. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-react-navigation-md-1bd.json +27 -0
  219. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-redux-integration-md-77b.json +23 -0
  220. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-testing-environment-md-1c6.json +27 -0
  221. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-troubleshooting-md-01d.json +27 -0
  222. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-understanding-act-md-aa9.json +27 -0
  223. package/website/.docusaurus/docusaurus-plugin-content-docs/default/site-docs-user-event-md-501.json +27 -0
  224. package/website/.docusaurus/docusaurus-plugin-content-docs/default/version-current-metadata-prop-751.json +268 -0
  225. package/website/.docusaurus/docusaurus-plugin-content-docs/react-native-testing-library-docs-route-96e.json +115 -0
  226. package/website/.docusaurus/docusaurus-plugin-content-docs/site-docs-api-md-c82.json +19 -0
  227. package/website/.docusaurus/docusaurus-plugin-content-docs/site-docs-eslint-p-llugin-testing-library-md-d24.json +19 -0
  228. package/website/.docusaurus/docusaurus-plugin-content-docs/site-docs-faq-md-ad8.json +19 -0
  229. package/website/.docusaurus/docusaurus-plugin-content-docs/site-docs-getting-started-md-8a6.json +15 -0
  230. package/website/.docusaurus/docusaurus-plugin-content-docs/site-docs-how-should-i-query-md-f2d.json +19 -0
  231. package/website/.docusaurus/docusaurus-plugin-content-docs/site-docs-migration-v-11-md-add.json +19 -0
  232. package/website/.docusaurus/docusaurus-plugin-content-docs/site-docs-migration-v-2-md-698.json +19 -0
  233. package/website/.docusaurus/docusaurus-plugin-content-docs/site-docs-migration-v-7-md-6bb.json +19 -0
  234. package/website/.docusaurus/docusaurus-plugin-content-docs/site-docs-migration-v-9-md-f69.json +19 -0
  235. package/website/.docusaurus/docusaurus-plugin-content-docs/site-docs-queries-md-7ad.json +19 -0
  236. package/website/.docusaurus/docusaurus-plugin-content-docs/site-docs-react-navigation-md-1bd.json +19 -0
  237. package/website/.docusaurus/docusaurus-plugin-content-docs/site-docs-redux-integration-md-77b.json +15 -0
  238. package/website/.docusaurus/docusaurus-plugin-content-docs/site-docs-troubleshooting-md-01d.json +19 -0
  239. package/website/.docusaurus/docusaurus-plugin-content-docs/site-docs-understanding-act-md-aa9.json +19 -0
  240. package/website/.docusaurus/docusaurus-plugin-content-pages/default/plugin-route-context-module-100.json +4 -0
  241. package/website/.docusaurus/docusaurus-plugin-debug/default/docusaurus-debug-all-content-673.json +623 -0
  242. package/website/.docusaurus/docusaurus-plugin-debug/default/plugin-route-context-module-100.json +4 -0
  243. package/website/.docusaurus/docusaurus-theme-search-algolia/default/plugin-route-context-module-100.json +4 -0
  244. package/website/.docusaurus/docusaurus.config.js +267 -0
  245. package/website/.docusaurus/docusaurus.config.mjs +365 -0
  246. package/website/.docusaurus/globalData.json +113 -0
  247. package/website/.docusaurus/i18n.json +17 -0
  248. package/website/.docusaurus/registry.js +35 -0
  249. package/website/.docusaurus/routes.js +162 -0
  250. package/website/.docusaurus/routesChunkNames.json +133 -0
  251. package/website/.docusaurus/site-metadata.json +36 -0
  252. package/website/docs/API.md +19 -25
  253. package/website/docs/UserEvent.md +86 -9
  254. package/website/sidebars.js +1 -1
  255. package/yarn-error.log +10613 -0
  256. package/build/user-event/press/utils/warnAboutRealTimers.d.ts +0 -1
  257. package/build/user-event/press/utils/warnAboutRealTimers.js +0 -14
  258. package/build/user-event/press/utils/warnAboutRealTimers.js.map +0 -1
  259. package/build/user-event/utils/events.js +0 -44
  260. package/build/user-event/utils/events.js.map +0 -1
  261. package/experiments-app/.expo/packager-info.json +0 -9
  262. package/src/user-event/utils/events.ts +0 -54
@@ -5,5 +5,6 @@
5
5
  "minify": false,
6
6
  "urlRandomness": null,
7
7
  "https": false,
8
- "scheme": null
8
+ "scheme": null,
9
+ "devClient": false
9
10
  }
@@ -7,7 +7,12 @@ const handlePressOut = buildEventLogger('pressOut');
7
7
  const handleFocus = buildEventLogger('focus');
8
8
  const handleBlur = buildEventLogger('blur');
9
9
  const handleChange = buildEventLogger('change');
10
+ const handleEndEditing = buildEventLogger('endEditing');
10
11
  const handleSubmitEditing = buildEventLogger('submitEditing');
12
+ const handleKeyPress = buildEventLogger('keyPress');
13
+ const handleTextInput = buildEventLogger('textInput');
14
+ const handleSelectionChange = buildEventLogger('selectionChange');
15
+ const handleContentSizeChange = buildEventLogger('contentSizeChange');
11
16
 
12
17
  export function TextInputEvents() {
13
18
  const [value, setValue] = React.useState('');
@@ -29,7 +34,12 @@ export function TextInputEvents() {
29
34
  onFocus={handleFocus}
30
35
  onBlur={handleBlur}
31
36
  onChange={handleChange}
37
+ onEndEditing={handleEndEditing}
32
38
  onSubmitEditing={handleSubmitEditing}
39
+ onKeyPress={handleKeyPress}
40
+ onTextInput={handleTextInput}
41
+ onSelectionChange={handleSelectionChange}
42
+ onContentSizeChange={handleContentSizeChange}
33
43
  />
34
44
  </SafeAreaView>
35
45
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testing-library/react-native",
3
- "version": "12.1.3",
3
+ "version": "12.2.0",
4
4
  "description": "Simple and complete React Native testing utilities that encourage good testing practices.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
package/src/.DS_Store ADDED
Binary file
Binary file
@@ -50,3 +50,7 @@ test('should be able to await act', async () => {
50
50
  const result = await act(async () => {});
51
51
  expect(result).toBe(undefined);
52
52
  });
53
+
54
+ test('should be able to await act when promise rejects', async () => {
55
+ await expect(act(async () => Promise.reject('error'))).rejects.toBe('error');
56
+ });
package/src/fireEvent.ts CHANGED
@@ -7,16 +7,12 @@ import {
7
7
  ScrollViewProps,
8
8
  } from 'react-native';
9
9
  import act from './act';
10
- import { isHostElement } from './helpers/component-tree';
11
- import { getHostComponentNames } from './helpers/host-component-names';
12
10
  import { isPointerEventEnabled } from './helpers/pointer-events';
11
+ import { isHostElement } from './helpers/component-tree';
12
+ import { isHostTextInput } from './helpers/host-component-names';
13
13
 
14
14
  type EventHandler = (...args: unknown[]) => unknown;
15
15
 
16
- const isHostTextInput = (element?: ReactTestInstance) => {
17
- return element?.type === getHostComponentNames().textInput;
18
- };
19
-
20
16
  export function isTouchResponder(element: ReactTestInstance) {
21
17
  if (!isHostElement(element)) {
22
18
  return false;
@@ -37,7 +37,7 @@ function deprecateQuery<QueryFn extends (...args: any) => any>(
37
37
 
38
38
  const warned: { [functionName: string]: boolean } = {};
39
39
 
40
- // istambul ignore next: Occasionally used
40
+ /* istanbul ignore next: occasionally used */
41
41
  export function printDeprecationWarning(functionName: string) {
42
42
  if (warned[functionName]) {
43
43
  return;
@@ -65,3 +65,11 @@ function getByTestId(instance: ReactTestInstance, testID: string) {
65
65
 
66
66
  return nodes[0];
67
67
  }
68
+
69
+ export function isHostText(element?: ReactTestInstance) {
70
+ return element?.type === getHostComponentNames().text;
71
+ }
72
+
73
+ export function isHostTextInput(element?: ReactTestInstance) {
74
+ return element?.type === getHostComponentNames().textInput;
75
+ }
package/src/pure.ts CHANGED
@@ -14,6 +14,7 @@ export {
14
14
  export { getDefaultNormalizer } from './matches';
15
15
  export { renderHook } from './renderHook';
16
16
  export { screen } from './screen';
17
+ export { userEvent } from './user-event';
17
18
 
18
19
  export type {
19
20
  RenderOptions,
@@ -23,3 +24,4 @@ export type {
23
24
  } from './render';
24
25
  export type { RenderHookOptions, RenderHookResult } from './renderHook';
25
26
  export type { Config } from './config';
27
+ export type { UserEventConfig } from './user-event';
@@ -1,24 +1,40 @@
1
+ /**
2
+ * Experimental values:
3
+ * - iOS: `{"changedTouches": [[Circular]], "identifier": 1, "locationX": 253, "locationY": 30.333328247070312, "pageX": 273, "pageY": 141.3333282470703, "target": 75, "timestamp": 875928682.0450834, "touches": [[Circular]]}`
4
+ * - Android: `{"changedTouches": [[Circular]], "identifier": 0, "locationX": 160, "locationY": 40.3636360168457, "pageX": 180, "pageY": 140.36363220214844, "target": 53, "targetSurface": -1, "timestamp": 10290805, "touches": [[Circular]]}`
5
+ */
6
+ function touch() {
7
+ return {
8
+ persist: jest.fn(),
9
+ currentTarget: { measure: jest.fn() },
10
+ nativeEvent: {
11
+ changedTouches: [],
12
+ identifier: 0,
13
+ locationX: 0,
14
+ locationY: 0,
15
+ pageX: 0,
16
+ pageY: 0,
17
+ target: 0,
18
+ timestamp: Date.now(),
19
+ touches: [],
20
+ },
21
+ };
22
+ }
23
+
1
24
  export const CommonEventBuilder = {
2
- /**
3
- * Experimental values:
4
- * - iOS: `{"changedTouches": [[Circular]], "identifier": 1, "locationX": 253, "locationY": 30.333328247070312, "pageX": 273, "pageY": 141.3333282470703, "target": 75, "timestamp": 875928682.0450834, "touches": [[Circular]]}`
5
- * - Android: `{"changedTouches": [[Circular]], "identifier": 0, "locationX": 160, "locationY": 40.3636360168457, "pageX": 180, "pageY": 140.36363220214844, "target": 53, "targetSurface": -1, "timestamp": 10290805, "touches": [[Circular]]}`
6
- */
7
- touch: () => {
25
+ touch,
26
+
27
+ responderGrant: () => {
8
28
  return {
9
- persist: jest.fn(),
10
- currentTarget: { measure: jest.fn() },
11
- nativeEvent: {
12
- changedTouches: [],
13
- identifier: 0,
14
- locationX: 0,
15
- locationY: 0,
16
- pageX: 0,
17
- pageY: 0,
18
- target: 0,
19
- timestamp: Date.now(),
20
- touches: [],
21
- },
29
+ ...touch(),
30
+ dispatchConfig: { registrationName: 'onResponderGrant' },
31
+ };
32
+ },
33
+
34
+ responderRelease: () => {
35
+ return {
36
+ ...touch(),
37
+ dispatchConfig: { registrationName: 'onResponderRelease' },
22
38
  };
23
39
  },
24
40
 
@@ -1,5 +1,7 @@
1
1
  import { CommonEventBuilder } from './common';
2
+ import { TextInputEventBuilder } from './text-input';
2
3
 
3
4
  export const EventBuilder = {
4
5
  Common: CommonEventBuilder,
6
+ TextInput: TextInputEventBuilder,
5
7
  };
@@ -0,0 +1,86 @@
1
+ import { ContentSize } from '../utils/content-size';
2
+ import { TextRange } from '../utils/text-range';
3
+
4
+ export const TextInputEventBuilder = {
5
+ /**
6
+ * Experimental values:
7
+ * - iOS: `{"eventCount": 4, "target": 75, "text": "Test"}`
8
+ * - Android: `{"eventCount": 6, "target": 53, "text": "Tes"}`
9
+ */
10
+ change: (text: string) => {
11
+ return {
12
+ nativeEvent: { text, target: 0, eventCount: 0 },
13
+ };
14
+ },
15
+
16
+ /**
17
+ * Experimental values:
18
+ * - iOS: `{"eventCount": 3, "key": "a", "target": 75}`
19
+ * - Android: `{"key": "a"}`
20
+ */
21
+ keyPress: (key: string) => {
22
+ return {
23
+ nativeEvent: { key },
24
+ };
25
+ },
26
+
27
+ /**
28
+ * Experimental values:
29
+ * - iOS: `{"eventCount": 4, "target": 75, "text": "Test"}`
30
+ * - Android: `{"target": 53, "text": "Test"}`
31
+ */
32
+ submitEditing: (text: string) => {
33
+ return {
34
+ nativeEvent: { text, target: 0 },
35
+ };
36
+ },
37
+
38
+ /**
39
+ * Experimental values:
40
+ * - iOS: `{"eventCount": 4, "target": 75, "text": "Test"}`
41
+ * - Android: `{"target": 53, "text": "Test"}`
42
+ */
43
+ endEditing: (text: string) => {
44
+ return {
45
+ nativeEvent: { text, target: 0 },
46
+ };
47
+ },
48
+
49
+ /**
50
+ * Experimental values:
51
+ * - iOS: `{"selection": {"end": 4, "start": 4}, "target": 75}`
52
+ * - Android: `{"selection": {"end": 4, "start": 4}}`
53
+ */
54
+ selectionChange: ({ start, end }: TextRange) => {
55
+ return {
56
+ nativeEvent: { selection: { start, end } },
57
+ };
58
+ },
59
+
60
+ /**
61
+ * Experimental values:
62
+ * - iOS: `{"eventCount": 2, "previousText": "Te", "range": {"end": 2, "start": 2}, "target": 75, "text": "s"}`
63
+ * - Android: `{"previousText": "Te", "range": {"end": 2, "start": 0}, "target": 53, "text": "Tes"}`
64
+ */
65
+ textInput: (text: string, previousText: string) => {
66
+ return {
67
+ nativeEvent: {
68
+ text,
69
+ previousText,
70
+ range: { start: text.length, end: text.length },
71
+ target: 0,
72
+ },
73
+ };
74
+ },
75
+
76
+ /**
77
+ * Experimental values:
78
+ * - iOS: `{"contentSize": {"height": 21.666666666666668, "width": 11.666666666666666}, "target": 75}`
79
+ * - Android: `{"contentSize": {"height": 61.45454406738281, "width": 352.7272644042969}, "target": 53}`
80
+ */
81
+ contentSizeChange: ({ width, height }: ContentSize) => {
82
+ return {
83
+ nativeEvent: { contentSize: { width, height }, target: 0 },
84
+ };
85
+ },
86
+ };
@@ -1,6 +1,9 @@
1
1
  import { ReactTestInstance } from 'react-test-renderer';
2
2
  import { setup } from './setup';
3
- import { PressOptions } from './press/press';
3
+ import { PressOptions } from './press';
4
+ import { TypeOptions } from './type';
5
+
6
+ export { UserEventConfig } from './setup';
4
7
 
5
8
  export const userEvent = {
6
9
  setup,
@@ -9,6 +12,6 @@ export const userEvent = {
9
12
  press: (element: ReactTestInstance) => setup().press(element),
10
13
  longPress: (element: ReactTestInstance, options?: PressOptions) =>
11
14
  setup().longPress(element, options),
12
- type: (element: ReactTestInstance, text: string) =>
13
- setup().type(element, text),
15
+ type: (element: ReactTestInstance, text: string, options?: TypeOptions) =>
16
+ setup().type(element, text, options),
14
17
  };
@@ -2,13 +2,15 @@ import React from 'react';
2
2
  import { Pressable, Text } from 'react-native';
3
3
  import { render, screen } from '../../../pure';
4
4
  import { userEvent } from '../..';
5
- import * as WarnAboutRealTimers from '../utils/warnAboutRealTimers';
5
+ import * as WarnAboutRealTimers from '../../utils/warn-about-real-timers';
6
6
 
7
7
  describe('userEvent.longPress with real timers', () => {
8
8
  beforeEach(() => {
9
9
  jest.useRealTimers();
10
10
  jest.restoreAllMocks();
11
- jest.spyOn(WarnAboutRealTimers, 'warnAboutRealTimers').mockImplementation();
11
+ jest
12
+ .spyOn(WarnAboutRealTimers, 'warnAboutRealTimersIfNeeded')
13
+ .mockImplementation();
12
14
  });
13
15
 
14
16
  test('calls onLongPress if the delayLongPress is the default one', async () => {
@@ -10,13 +10,15 @@ import {
10
10
  import { createEventLogger, getEventsName } from '../../../test-utils';
11
11
  import { render, screen } from '../../..';
12
12
  import { userEvent } from '../..';
13
- import * as WarnAboutRealTimers from '../utils/warnAboutRealTimers';
13
+ import * as WarnAboutRealTimers from '../../utils/warn-about-real-timers';
14
14
 
15
15
  describe('userEvent.press with real timers', () => {
16
16
  beforeEach(() => {
17
17
  jest.useRealTimers();
18
18
  jest.restoreAllMocks();
19
- jest.spyOn(WarnAboutRealTimers, 'warnAboutRealTimers').mockImplementation();
19
+ jest
20
+ .spyOn(WarnAboutRealTimers, 'warnAboutRealTimersIfNeeded')
21
+ .mockImplementation();
20
22
  });
21
23
 
22
24
  test('calls onPressIn, onPress and onPressOut prop of touchable', async () => {
@@ -304,7 +304,7 @@ describe('userEvent.press with fake timers', () => {
304
304
  expect(mockOnPress).toHaveBeenCalled();
305
305
  });
306
306
 
307
- test('works on Text', async () => {
307
+ test('press works on Text', async () => {
308
308
  const { events, logEvent } = createEventLogger();
309
309
 
310
310
  render(
@@ -317,11 +317,29 @@ describe('userEvent.press with fake timers', () => {
317
317
  press me
318
318
  </Text>
319
319
  );
320
- await userEvent.press(screen.getByText('press me'));
321
320
 
321
+ await userEvent.press(screen.getByText('press me'));
322
322
  expect(getEventsName(events)).toEqual(['pressIn', 'press', 'pressOut']);
323
323
  });
324
324
 
325
+ test('longPress works 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
+ >
335
+ press me
336
+ </Text>
337
+ );
338
+
339
+ await userEvent.longPress(screen.getByText('press me'));
340
+ expect(getEventsName(events)).toEqual(['pressIn', 'longPress', 'pressOut']);
341
+ });
342
+
325
343
  test('doesnt trigger on disabled Text', async () => {
326
344
  const { events, logEvent } = createEventLogger();
327
345
 
@@ -361,7 +379,7 @@ describe('userEvent.press with fake timers', () => {
361
379
  expect(events).toEqual([]);
362
380
  });
363
381
 
364
- test('works on TetInput', async () => {
382
+ test('press works on TextInput', async () => {
365
383
  const { events, logEvent } = createEventLogger();
366
384
 
367
385
  render(
@@ -371,12 +389,27 @@ describe('userEvent.press with fake timers', () => {
371
389
  onPressOut={logEvent('pressOut')}
372
390
  />
373
391
  );
392
+
374
393
  await userEvent.press(screen.getByPlaceholderText('email'));
394
+ expect(getEventsName(events)).toEqual(['pressIn', 'pressOut']);
395
+ });
396
+
397
+ test('longPress works on TextInput', async () => {
398
+ const { events, logEvent } = createEventLogger();
399
+
400
+ render(
401
+ <TextInput
402
+ placeholder="email"
403
+ onPressIn={logEvent('pressIn')}
404
+ onPressOut={logEvent('pressOut')}
405
+ />
406
+ );
375
407
 
408
+ await userEvent.longPress(screen.getByPlaceholderText('email'));
376
409
  expect(getEventsName(events)).toEqual(['pressIn', 'pressOut']);
377
410
  });
378
411
 
379
- test('does not call onPressIn and onPressOut on non editable TetInput', async () => {
412
+ test('does not call onPressIn and onPressOut on non editable TextInput', async () => {
380
413
  const { events, logEvent } = createEventLogger();
381
414
 
382
415
  render(
@@ -387,11 +420,12 @@ describe('userEvent.press with fake timers', () => {
387
420
  onPressOut={logEvent('pressOut')}
388
421
  />
389
422
  );
423
+
390
424
  await userEvent.press(screen.getByPlaceholderText('email'));
391
425
  expect(events).toEqual([]);
392
426
  });
393
427
 
394
- test('does not call onPressIn and onPressOut on TetInput with pointer events disabled', async () => {
428
+ test('does not call onPressIn and onPressOut on TextInput with pointer events disabled', async () => {
395
429
  const { events, logEvent } = createEventLogger();
396
430
 
397
431
  render(
@@ -402,6 +436,7 @@ describe('userEvent.press with fake timers', () => {
402
436
  onPressOut={logEvent('pressOut')}
403
437
  />
404
438
  );
439
+
405
440
  await userEvent.press(screen.getByPlaceholderText('email'));
406
441
  expect(events).toEqual([]);
407
442
  });
@@ -1 +1 @@
1
- export { press, longPress } from './press';
1
+ export { PressOptions, press, longPress } from './press';
@@ -1,50 +1,63 @@
1
1
  import { ReactTestInstance } from 'react-test-renderer';
2
- import { EventBuilder } from '../event-builder';
3
- import { UserEventInstance } from '../setup';
4
- import { wait } from '../utils';
5
2
  import act from '../../act';
6
3
  import { getHostParent } from '../../helpers/component-tree';
7
- import { filterNodeByType } from '../../helpers/filterNodeByType';
8
4
  import { isPointerEventEnabled } from '../../helpers/pointer-events';
9
- import { getHostComponentNames } from '../../helpers/host-component-names';
10
- import { jestFakeTimersAreEnabled } from '../../helpers/timers';
5
+ import {
6
+ isHostText,
7
+ isHostTextInput,
8
+ } from '../../helpers/host-component-names';
9
+ import { EventBuilder } from '../event-builder';
10
+ import { UserEventConfig, UserEventInstance } from '../setup';
11
+ import { dispatchEvent, wait, warnAboutRealTimersIfNeeded } from '../utils';
11
12
  import { DEFAULT_MIN_PRESS_DURATION } from './constants';
12
- import { warnAboutRealTimers } from './utils/warnAboutRealTimers';
13
13
 
14
- export type PressOptions = {
15
- duration: number;
16
- };
14
+ export interface PressOptions {
15
+ duration?: number;
16
+ }
17
17
 
18
18
  export async function press(
19
19
  this: UserEventInstance,
20
20
  element: ReactTestInstance
21
21
  ): Promise<void> {
22
- await basePress(this.config, element);
22
+ await basePress(this.config, element, {
23
+ type: 'press',
24
+ duration: 0,
25
+ });
23
26
  }
24
27
 
25
28
  export async function longPress(
26
29
  this: UserEventInstance,
27
30
  element: ReactTestInstance,
28
- options: PressOptions = { duration: 500 }
31
+ options?: PressOptions
29
32
  ): Promise<void> {
30
- await basePress(this.config, element, options);
33
+ await basePress(this.config, element, {
34
+ type: 'longPress',
35
+ duration: options?.duration ?? 500,
36
+ });
37
+ }
38
+
39
+ interface BasePressOptions {
40
+ type: 'press' | 'longPress';
41
+ duration: number;
31
42
  }
32
43
 
33
44
  const basePress = async (
34
- config: UserEventInstance['config'],
45
+ config: UserEventConfig,
35
46
  element: ReactTestInstance,
36
- options: PressOptions = { duration: 0 }
47
+ options: BasePressOptions
37
48
  ): 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);
49
+ if (isPressableText(element)) {
50
+ await emitTextPressEvents(config, element, options);
51
+ return;
52
+ }
53
+
54
+ if (isEnabledTextInput(element)) {
55
+ await emitTextInputPressEvents(config, element, options);
43
56
  return;
44
57
  }
45
58
 
46
59
  if (isEnabledTouchResponder(element)) {
47
- await triggerPressEvent(config, element, options);
60
+ await emitPressablePressEvents(config, element, options);
48
61
  return;
49
62
  }
50
63
 
@@ -56,31 +69,33 @@ const basePress = async (
56
69
  await basePress(config, hostParentElement, options);
57
70
  };
58
71
 
59
- const triggerPressEvent = async (
60
- config: UserEventInstance['config'],
72
+ const emitPressablePressEvents = async (
73
+ config: UserEventConfig,
61
74
  element: ReactTestInstance,
62
- options: PressOptions = { duration: 0 }
75
+ options: BasePressOptions
63
76
  ) => {
64
- const areFakeTimersEnabled = jestFakeTimersAreEnabled();
65
- if (!areFakeTimersEnabled) {
66
- warnAboutRealTimers();
67
- }
77
+ warnAboutRealTimersIfNeeded();
68
78
 
69
79
  await wait(config);
70
80
 
71
81
  await act(async () => {
72
- element.props.onResponderGrant({
73
- ...EventBuilder.Common.touch(),
74
- dispatchConfig: { registrationName: 'onResponderGrant' },
75
- });
82
+ dispatchEvent(
83
+ element,
84
+ 'responderGrant',
85
+ EventBuilder.Common.responderGrant()
86
+ );
76
87
 
77
88
  await wait(config, options.duration);
78
89
 
79
- element.props.onResponderRelease({
80
- ...EventBuilder.Common.touch(),
81
- dispatchConfig: { registrationName: 'onResponderRelease' },
82
- });
90
+ dispatchEvent(
91
+ element,
92
+ 'responderRelease',
93
+ EventBuilder.Common.responderRelease()
94
+ );
83
95
 
96
+ // React Native will wait for minimal delay of DEFAULT_MIN_PRESS_DURATION
97
+ // before emitting the `pressOut` event. We need to wait here, so that
98
+ // `press()` function does not return before that.
84
99
  if (DEFAULT_MIN_PRESS_DURATION - options.duration > 0) {
85
100
  await wait(config, DEFAULT_MIN_PRESS_DURATION - options.duration);
86
101
  }
@@ -94,41 +109,61 @@ const isEnabledTouchResponder = (element: ReactTestInstance) => {
94
109
  );
95
110
  };
96
111
 
97
- const isEnabledHostText = (element: ReactTestInstance) => {
112
+ const isPressableText = (element: ReactTestInstance) => {
113
+ const hasPressEventHandler = Boolean(
114
+ element.props.onPress ||
115
+ element.props.onLongPress ||
116
+ element.props.onPressIn ||
117
+ element.props.onPressOut
118
+ );
119
+
98
120
  return (
99
- filterNodeByType(element, getHostComponentNames().text) &&
121
+ isHostText(element) &&
100
122
  isPointerEventEnabled(element) &&
101
123
  !element.props.disabled &&
102
- element.props.onPress
124
+ hasPressEventHandler
103
125
  );
104
126
  };
105
127
 
106
128
  const isEnabledTextInput = (element: ReactTestInstance) => {
107
129
  return (
108
- filterNodeByType(element, getHostComponentNames().textInput) &&
130
+ isHostTextInput(element) &&
109
131
  isPointerEventEnabled(element) &&
110
132
  element.props.editable !== false
111
133
  );
112
134
  };
113
135
 
114
- const triggerMockPressEvent = async (
115
- config: UserEventInstance['config'],
136
+ /**
137
+ * Dispatches a press event sequence for Text.
138
+ */
139
+ async function emitTextPressEvents(
140
+ config: UserEventConfig,
116
141
  element: ReactTestInstance,
117
- options: PressOptions = { duration: 0 }
118
- ) => {
119
- const { onPressIn, onPress, onPressOut } = element.props;
142
+ options: BasePressOptions
143
+ ) {
120
144
  await wait(config);
121
- if (onPressIn) {
122
- onPressIn(EventBuilder.Common.touch());
123
- }
124
- if (onPress) {
125
- onPress(EventBuilder.Common.touch());
126
- }
145
+ dispatchEvent(element, 'pressIn', EventBuilder.Common.touch());
146
+
147
+ // Emit either `press` or `longPress`.
148
+ dispatchEvent(element, options.type, EventBuilder.Common.touch());
149
+
127
150
  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
- };
151
+ dispatchEvent(element, 'pressOut', EventBuilder.Common.touch());
152
+ }
153
+
154
+ /**
155
+ * Dispatches a press event sequence for TextInput.
156
+ */
157
+ async function emitTextInputPressEvents(
158
+ config: UserEventConfig,
159
+ element: ReactTestInstance,
160
+ options: BasePressOptions
161
+ ) {
162
+ await wait(config);
163
+ dispatchEvent(element, 'pressIn', EventBuilder.Common.touch());
164
+
165
+ // Note: TextInput does not have `onPress`/`onLongPress` props.
166
+
167
+ await wait(config, options.duration);
168
+ dispatchEvent(element, 'pressOut', EventBuilder.Common.touch());
169
+ }