@testing-library/react-native 14.0.0-rc.0 → 14.0.0-rc.2

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 (322) hide show
  1. package/README.md +1 -6
  2. package/{build → dist}/helpers/accessibility.js +24 -7
  3. package/dist/helpers/accessibility.js.map +1 -0
  4. package/docs/README.md +31 -0
  5. package/docs/api/accessibility.md +26 -0
  6. package/docs/api/async-utilities.md +137 -0
  7. package/docs/api/configuration.md +61 -0
  8. package/docs/api/fire-event.md +165 -0
  9. package/docs/api/jest-matchers.md +198 -0
  10. package/docs/api/other-helpers.md +94 -0
  11. package/docs/api/overview.md +18 -0
  12. package/docs/api/queries.md +500 -0
  13. package/docs/api/render-hook.md +176 -0
  14. package/docs/api/render.md +49 -0
  15. package/docs/api/screen.md +188 -0
  16. package/docs/api/user-event.md +295 -0
  17. package/docs/cookbook/async-events.md +147 -0
  18. package/docs/cookbook/custom-render.md +83 -0
  19. package/docs/cookbook/network-requests.md +375 -0
  20. package/docs/guides/common-mistakes.md +587 -0
  21. package/docs/guides/how-to-query.md +125 -0
  22. package/docs/guides/llm-guidelines.md +228 -0
  23. package/docs/guides/migration-v14.md +553 -0
  24. package/docs/guides/quick-start.md +77 -0
  25. package/docs/guides/testing-environment.md +123 -0
  26. package/docs/guides/troubleshooting.md +61 -0
  27. package/docs/guides/understanding-act.md +207 -0
  28. package/matchers.d.ts +1 -1
  29. package/matchers.js +2 -2
  30. package/package.json +14 -12
  31. package/pure.d.ts +1 -1
  32. package/pure.js +1 -1
  33. package/build/helpers/accessibility.js.map +0 -1
  34. /package/{build → dist}/act.d.ts +0 -0
  35. /package/{build → dist}/act.js +0 -0
  36. /package/{build → dist}/act.js.map +0 -0
  37. /package/{build → dist}/cleanup.d.ts +0 -0
  38. /package/{build → dist}/cleanup.js +0 -0
  39. /package/{build → dist}/cleanup.js.map +0 -0
  40. /package/{build → dist}/config.d.ts +0 -0
  41. /package/{build → dist}/config.js +0 -0
  42. /package/{build → dist}/config.js.map +0 -0
  43. /package/{build → dist}/event-builder/base.d.ts +0 -0
  44. /package/{build → dist}/event-builder/base.js +0 -0
  45. /package/{build → dist}/event-builder/base.js.map +0 -0
  46. /package/{build → dist}/event-builder/common.d.ts +0 -0
  47. /package/{build → dist}/event-builder/common.js +0 -0
  48. /package/{build → dist}/event-builder/common.js.map +0 -0
  49. /package/{build → dist}/event-builder/index.d.ts +0 -0
  50. /package/{build → dist}/event-builder/index.js +0 -0
  51. /package/{build → dist}/event-builder/index.js.map +0 -0
  52. /package/{build → dist}/event-builder/scroll.d.ts +0 -0
  53. /package/{build → dist}/event-builder/scroll.js +0 -0
  54. /package/{build → dist}/event-builder/scroll.js.map +0 -0
  55. /package/{build → dist}/event-builder/text.d.ts +0 -0
  56. /package/{build → dist}/event-builder/text.js +0 -0
  57. /package/{build → dist}/event-builder/text.js.map +0 -0
  58. /package/{build → dist}/event-handler.d.ts +0 -0
  59. /package/{build → dist}/event-handler.js +0 -0
  60. /package/{build → dist}/event-handler.js.map +0 -0
  61. /package/{build → dist}/fire-event.d.ts +0 -0
  62. /package/{build → dist}/fire-event.js +0 -0
  63. /package/{build → dist}/fire-event.js.map +0 -0
  64. /package/{build → dist}/flush-micro-tasks.d.ts +0 -0
  65. /package/{build → dist}/flush-micro-tasks.js +0 -0
  66. /package/{build → dist}/flush-micro-tasks.js.map +0 -0
  67. /package/{build → dist}/helpers/accessibility.d.ts +0 -0
  68. /package/{build → dist}/helpers/component-tree.d.ts +0 -0
  69. /package/{build → dist}/helpers/component-tree.js +0 -0
  70. /package/{build → dist}/helpers/component-tree.js.map +0 -0
  71. /package/{build → dist}/helpers/debug.d.ts +0 -0
  72. /package/{build → dist}/helpers/debug.js +0 -0
  73. /package/{build → dist}/helpers/debug.js.map +0 -0
  74. /package/{build → dist}/helpers/errors.d.ts +0 -0
  75. /package/{build → dist}/helpers/errors.js +0 -0
  76. /package/{build → dist}/helpers/errors.js.map +0 -0
  77. /package/{build → dist}/helpers/find-all.d.ts +0 -0
  78. /package/{build → dist}/helpers/find-all.js +0 -0
  79. /package/{build → dist}/helpers/find-all.js.map +0 -0
  80. /package/{build → dist}/helpers/format-element.d.ts +0 -0
  81. /package/{build → dist}/helpers/format-element.js +0 -0
  82. /package/{build → dist}/helpers/format-element.js.map +0 -0
  83. /package/{build → dist}/helpers/host-component-names.d.ts +0 -0
  84. /package/{build → dist}/helpers/host-component-names.js +0 -0
  85. /package/{build → dist}/helpers/host-component-names.js.map +0 -0
  86. /package/{build → dist}/helpers/logger.d.ts +0 -0
  87. /package/{build → dist}/helpers/logger.js +0 -0
  88. /package/{build → dist}/helpers/logger.js.map +0 -0
  89. /package/{build → dist}/helpers/map-props.d.ts +0 -0
  90. /package/{build → dist}/helpers/map-props.js +0 -0
  91. /package/{build → dist}/helpers/map-props.js.map +0 -0
  92. /package/{build → dist}/helpers/matchers/match-accessibility-state.d.ts +0 -0
  93. /package/{build → dist}/helpers/matchers/match-accessibility-state.js +0 -0
  94. /package/{build → dist}/helpers/matchers/match-accessibility-state.js.map +0 -0
  95. /package/{build → dist}/helpers/matchers/match-accessibility-value.d.ts +0 -0
  96. /package/{build → dist}/helpers/matchers/match-accessibility-value.js +0 -0
  97. /package/{build → dist}/helpers/matchers/match-accessibility-value.js.map +0 -0
  98. /package/{build → dist}/helpers/matchers/match-array-prop.d.ts +0 -0
  99. /package/{build → dist}/helpers/matchers/match-array-prop.js +0 -0
  100. /package/{build → dist}/helpers/matchers/match-array-prop.js.map +0 -0
  101. /package/{build → dist}/helpers/matchers/match-label-text.d.ts +0 -0
  102. /package/{build → dist}/helpers/matchers/match-label-text.js +0 -0
  103. /package/{build → dist}/helpers/matchers/match-label-text.js.map +0 -0
  104. /package/{build → dist}/helpers/matchers/match-object-prop.d.ts +0 -0
  105. /package/{build → dist}/helpers/matchers/match-object-prop.js +0 -0
  106. /package/{build → dist}/helpers/matchers/match-object-prop.js.map +0 -0
  107. /package/{build → dist}/helpers/matchers/match-string-prop.d.ts +0 -0
  108. /package/{build → dist}/helpers/matchers/match-string-prop.js +0 -0
  109. /package/{build → dist}/helpers/matchers/match-string-prop.js.map +0 -0
  110. /package/{build → dist}/helpers/matchers/match-text-content.d.ts +0 -0
  111. /package/{build → dist}/helpers/matchers/match-text-content.js +0 -0
  112. /package/{build → dist}/helpers/matchers/match-text-content.js.map +0 -0
  113. /package/{build → dist}/helpers/object.d.ts +0 -0
  114. /package/{build → dist}/helpers/object.js +0 -0
  115. /package/{build → dist}/helpers/object.js.map +0 -0
  116. /package/{build → dist}/helpers/pointer-events.d.ts +0 -0
  117. /package/{build → dist}/helpers/pointer-events.js +0 -0
  118. /package/{build → dist}/helpers/pointer-events.js.map +0 -0
  119. /package/{build → dist}/helpers/text-content.d.ts +0 -0
  120. /package/{build → dist}/helpers/text-content.js +0 -0
  121. /package/{build → dist}/helpers/text-content.js.map +0 -0
  122. /package/{build → dist}/helpers/text-input.d.ts +0 -0
  123. /package/{build → dist}/helpers/text-input.js +0 -0
  124. /package/{build → dist}/helpers/text-input.js.map +0 -0
  125. /package/{build → dist}/helpers/timers.d.ts +0 -0
  126. /package/{build → dist}/helpers/timers.js +0 -0
  127. /package/{build → dist}/helpers/timers.js.map +0 -0
  128. /package/{build → dist}/helpers/validate-options.d.ts +0 -0
  129. /package/{build → dist}/helpers/validate-options.js +0 -0
  130. /package/{build → dist}/helpers/validate-options.js.map +0 -0
  131. /package/{build → dist}/helpers/wrap-async.d.ts +0 -0
  132. /package/{build → dist}/helpers/wrap-async.js +0 -0
  133. /package/{build → dist}/helpers/wrap-async.js.map +0 -0
  134. /package/{build → dist}/index.d.ts +0 -0
  135. /package/{build → dist}/index.js +0 -0
  136. /package/{build → dist}/index.js.map +0 -0
  137. /package/{build → dist}/matchers/extend-expect.d.ts +0 -0
  138. /package/{build → dist}/matchers/extend-expect.js +0 -0
  139. /package/{build → dist}/matchers/extend-expect.js.map +0 -0
  140. /package/{build → dist}/matchers/index.d.ts +0 -0
  141. /package/{build → dist}/matchers/index.js +0 -0
  142. /package/{build → dist}/matchers/index.js.map +0 -0
  143. /package/{build → dist}/matchers/to-be-busy.d.ts +0 -0
  144. /package/{build → dist}/matchers/to-be-busy.js +0 -0
  145. /package/{build → dist}/matchers/to-be-busy.js.map +0 -0
  146. /package/{build → dist}/matchers/to-be-checked.d.ts +0 -0
  147. /package/{build → dist}/matchers/to-be-checked.js +0 -0
  148. /package/{build → dist}/matchers/to-be-checked.js.map +0 -0
  149. /package/{build → dist}/matchers/to-be-disabled.d.ts +0 -0
  150. /package/{build → dist}/matchers/to-be-disabled.js +0 -0
  151. /package/{build → dist}/matchers/to-be-disabled.js.map +0 -0
  152. /package/{build → dist}/matchers/to-be-empty-element.d.ts +0 -0
  153. /package/{build → dist}/matchers/to-be-empty-element.js +0 -0
  154. /package/{build → dist}/matchers/to-be-empty-element.js.map +0 -0
  155. /package/{build → dist}/matchers/to-be-expanded.d.ts +0 -0
  156. /package/{build → dist}/matchers/to-be-expanded.js +0 -0
  157. /package/{build → dist}/matchers/to-be-expanded.js.map +0 -0
  158. /package/{build → dist}/matchers/to-be-on-the-screen.d.ts +0 -0
  159. /package/{build → dist}/matchers/to-be-on-the-screen.js +0 -0
  160. /package/{build → dist}/matchers/to-be-on-the-screen.js.map +0 -0
  161. /package/{build → dist}/matchers/to-be-partially-checked.d.ts +0 -0
  162. /package/{build → dist}/matchers/to-be-partially-checked.js +0 -0
  163. /package/{build → dist}/matchers/to-be-partially-checked.js.map +0 -0
  164. /package/{build → dist}/matchers/to-be-selected.d.ts +0 -0
  165. /package/{build → dist}/matchers/to-be-selected.js +0 -0
  166. /package/{build → dist}/matchers/to-be-selected.js.map +0 -0
  167. /package/{build → dist}/matchers/to-be-visible.d.ts +0 -0
  168. /package/{build → dist}/matchers/to-be-visible.js +0 -0
  169. /package/{build → dist}/matchers/to-be-visible.js.map +0 -0
  170. /package/{build → dist}/matchers/to-contain-element.d.ts +0 -0
  171. /package/{build → dist}/matchers/to-contain-element.js +0 -0
  172. /package/{build → dist}/matchers/to-contain-element.js.map +0 -0
  173. /package/{build → dist}/matchers/to-have-accessibility-value.d.ts +0 -0
  174. /package/{build → dist}/matchers/to-have-accessibility-value.js +0 -0
  175. /package/{build → dist}/matchers/to-have-accessibility-value.js.map +0 -0
  176. /package/{build → dist}/matchers/to-have-accessible-name.d.ts +0 -0
  177. /package/{build → dist}/matchers/to-have-accessible-name.js +0 -0
  178. /package/{build → dist}/matchers/to-have-accessible-name.js.map +0 -0
  179. /package/{build → dist}/matchers/to-have-display-value.d.ts +0 -0
  180. /package/{build → dist}/matchers/to-have-display-value.js +0 -0
  181. /package/{build → dist}/matchers/to-have-display-value.js.map +0 -0
  182. /package/{build → dist}/matchers/to-have-prop.d.ts +0 -0
  183. /package/{build → dist}/matchers/to-have-prop.js +0 -0
  184. /package/{build → dist}/matchers/to-have-prop.js.map +0 -0
  185. /package/{build → dist}/matchers/to-have-style.d.ts +0 -0
  186. /package/{build → dist}/matchers/to-have-style.js +0 -0
  187. /package/{build → dist}/matchers/to-have-style.js.map +0 -0
  188. /package/{build → dist}/matchers/to-have-text-content.d.ts +0 -0
  189. /package/{build → dist}/matchers/to-have-text-content.js +0 -0
  190. /package/{build → dist}/matchers/to-have-text-content.js.map +0 -0
  191. /package/{build → dist}/matchers/types.d.ts +0 -0
  192. /package/{build → dist}/matchers/types.js +0 -0
  193. /package/{build → dist}/matchers/types.js.map +0 -0
  194. /package/{build → dist}/matchers/utils.d.ts +0 -0
  195. /package/{build → dist}/matchers/utils.js +0 -0
  196. /package/{build → dist}/matchers/utils.js.map +0 -0
  197. /package/{build → dist}/matches.d.ts +0 -0
  198. /package/{build → dist}/matches.js +0 -0
  199. /package/{build → dist}/matches.js.map +0 -0
  200. /package/{build → dist}/native-state.d.ts +0 -0
  201. /package/{build → dist}/native-state.js +0 -0
  202. /package/{build → dist}/native-state.js.map +0 -0
  203. /package/{build → dist}/pure.d.ts +0 -0
  204. /package/{build → dist}/pure.js +0 -0
  205. /package/{build → dist}/pure.js.map +0 -0
  206. /package/{build → dist}/queries/display-value.d.ts +0 -0
  207. /package/{build → dist}/queries/display-value.js +0 -0
  208. /package/{build → dist}/queries/display-value.js.map +0 -0
  209. /package/{build → dist}/queries/hint-text.d.ts +0 -0
  210. /package/{build → dist}/queries/hint-text.js +0 -0
  211. /package/{build → dist}/queries/hint-text.js.map +0 -0
  212. /package/{build → dist}/queries/label-text.d.ts +0 -0
  213. /package/{build → dist}/queries/label-text.js +0 -0
  214. /package/{build → dist}/queries/label-text.js.map +0 -0
  215. /package/{build → dist}/queries/make-queries.d.ts +0 -0
  216. /package/{build → dist}/queries/make-queries.js +0 -0
  217. /package/{build → dist}/queries/make-queries.js.map +0 -0
  218. /package/{build → dist}/queries/options.d.ts +0 -0
  219. /package/{build → dist}/queries/options.js +0 -0
  220. /package/{build → dist}/queries/options.js.map +0 -0
  221. /package/{build → dist}/queries/placeholder-text.d.ts +0 -0
  222. /package/{build → dist}/queries/placeholder-text.js +0 -0
  223. /package/{build → dist}/queries/placeholder-text.js.map +0 -0
  224. /package/{build → dist}/queries/role.d.ts +0 -0
  225. /package/{build → dist}/queries/role.js +0 -0
  226. /package/{build → dist}/queries/role.js.map +0 -0
  227. /package/{build → dist}/queries/test-id.d.ts +0 -0
  228. /package/{build → dist}/queries/test-id.js +0 -0
  229. /package/{build → dist}/queries/test-id.js.map +0 -0
  230. /package/{build → dist}/queries/text.d.ts +0 -0
  231. /package/{build → dist}/queries/text.js +0 -0
  232. /package/{build → dist}/queries/text.js.map +0 -0
  233. /package/{build → dist}/render-hook.d.ts +0 -0
  234. /package/{build → dist}/render-hook.js +0 -0
  235. /package/{build → dist}/render-hook.js.map +0 -0
  236. /package/{build → dist}/render.d.ts +0 -0
  237. /package/{build → dist}/render.js +0 -0
  238. /package/{build → dist}/render.js.map +0 -0
  239. /package/{build → dist}/screen.d.ts +0 -0
  240. /package/{build → dist}/screen.js +0 -0
  241. /package/{build → dist}/screen.js.map +0 -0
  242. /package/{build → dist}/test-utils/console.d.ts +0 -0
  243. /package/{build → dist}/test-utils/console.js +0 -0
  244. /package/{build → dist}/test-utils/console.js.map +0 -0
  245. /package/{build → dist}/test-utils/events.d.ts +0 -0
  246. /package/{build → dist}/test-utils/events.js +0 -0
  247. /package/{build → dist}/test-utils/events.js.map +0 -0
  248. /package/{build → dist}/test-utils/json.d.ts +0 -0
  249. /package/{build → dist}/test-utils/json.js +0 -0
  250. /package/{build → dist}/test-utils/json.js.map +0 -0
  251. /package/{build → dist}/test-utils/react-version-gates.d.ts +0 -0
  252. /package/{build → dist}/test-utils/react-version-gates.js +0 -0
  253. /package/{build → dist}/test-utils/react-version-gates.js.map +0 -0
  254. /package/{build → dist}/test-utils/timers.d.ts +0 -0
  255. /package/{build → dist}/test-utils/timers.js +0 -0
  256. /package/{build → dist}/test-utils/timers.js.map +0 -0
  257. /package/{build → dist}/test-utils/version.d.ts +0 -0
  258. /package/{build → dist}/test-utils/version.js +0 -0
  259. /package/{build → dist}/test-utils/version.js.map +0 -0
  260. /package/{build → dist}/types.d.ts +0 -0
  261. /package/{build → dist}/types.js +0 -0
  262. /package/{build → dist}/types.js.map +0 -0
  263. /package/{build → dist}/user-event/clear.d.ts +0 -0
  264. /package/{build → dist}/user-event/clear.js +0 -0
  265. /package/{build → dist}/user-event/clear.js.map +0 -0
  266. /package/{build → dist}/user-event/index.d.ts +0 -0
  267. /package/{build → dist}/user-event/index.js +0 -0
  268. /package/{build → dist}/user-event/index.js.map +0 -0
  269. /package/{build → dist}/user-event/paste.d.ts +0 -0
  270. /package/{build → dist}/user-event/paste.js +0 -0
  271. /package/{build → dist}/user-event/paste.js.map +0 -0
  272. /package/{build → dist}/user-event/press/index.d.ts +0 -0
  273. /package/{build → dist}/user-event/press/index.js +0 -0
  274. /package/{build → dist}/user-event/press/index.js.map +0 -0
  275. /package/{build → dist}/user-event/press/press.d.ts +0 -0
  276. /package/{build → dist}/user-event/press/press.js +0 -0
  277. /package/{build → dist}/user-event/press/press.js.map +0 -0
  278. /package/{build → dist}/user-event/scroll/index.d.ts +0 -0
  279. /package/{build → dist}/user-event/scroll/index.js +0 -0
  280. /package/{build → dist}/user-event/scroll/index.js.map +0 -0
  281. /package/{build → dist}/user-event/scroll/scroll-to.d.ts +0 -0
  282. /package/{build → dist}/user-event/scroll/scroll-to.js +0 -0
  283. /package/{build → dist}/user-event/scroll/scroll-to.js.map +0 -0
  284. /package/{build → dist}/user-event/scroll/utils.d.ts +0 -0
  285. /package/{build → dist}/user-event/scroll/utils.js +0 -0
  286. /package/{build → dist}/user-event/scroll/utils.js.map +0 -0
  287. /package/{build → dist}/user-event/setup/index.d.ts +0 -0
  288. /package/{build → dist}/user-event/setup/index.js +0 -0
  289. /package/{build → dist}/user-event/setup/index.js.map +0 -0
  290. /package/{build → dist}/user-event/setup/setup.d.ts +0 -0
  291. /package/{build → dist}/user-event/setup/setup.js +0 -0
  292. /package/{build → dist}/user-event/setup/setup.js.map +0 -0
  293. /package/{build → dist}/user-event/type/index.d.ts +0 -0
  294. /package/{build → dist}/user-event/type/index.js +0 -0
  295. /package/{build → dist}/user-event/type/index.js.map +0 -0
  296. /package/{build → dist}/user-event/type/parse-keys.d.ts +0 -0
  297. /package/{build → dist}/user-event/type/parse-keys.js +0 -0
  298. /package/{build → dist}/user-event/type/parse-keys.js.map +0 -0
  299. /package/{build → dist}/user-event/type/type.d.ts +0 -0
  300. /package/{build → dist}/user-event/type/type.js +0 -0
  301. /package/{build → dist}/user-event/type/type.js.map +0 -0
  302. /package/{build → dist}/user-event/utils/content-size.d.ts +0 -0
  303. /package/{build → dist}/user-event/utils/content-size.js +0 -0
  304. /package/{build → dist}/user-event/utils/content-size.js.map +0 -0
  305. /package/{build → dist}/user-event/utils/dispatch-event.d.ts +0 -0
  306. /package/{build → dist}/user-event/utils/dispatch-event.js +0 -0
  307. /package/{build → dist}/user-event/utils/dispatch-event.js.map +0 -0
  308. /package/{build → dist}/user-event/utils/index.d.ts +0 -0
  309. /package/{build → dist}/user-event/utils/index.js +0 -0
  310. /package/{build → dist}/user-event/utils/index.js.map +0 -0
  311. /package/{build → dist}/user-event/utils/wait.d.ts +0 -0
  312. /package/{build → dist}/user-event/utils/wait.js +0 -0
  313. /package/{build → dist}/user-event/utils/wait.js.map +0 -0
  314. /package/{build → dist}/wait-for-element-to-be-removed.d.ts +0 -0
  315. /package/{build → dist}/wait-for-element-to-be-removed.js +0 -0
  316. /package/{build → dist}/wait-for-element-to-be-removed.js.map +0 -0
  317. /package/{build → dist}/wait-for.d.ts +0 -0
  318. /package/{build → dist}/wait-for.js +0 -0
  319. /package/{build → dist}/wait-for.js.map +0 -0
  320. /package/{build → dist}/within.d.ts +0 -0
  321. /package/{build → dist}/within.js +0 -0
  322. /package/{build → dist}/within.js.map +0 -0
package/README.md CHANGED
@@ -12,11 +12,6 @@
12
12
  [![MIT License][license-badge]][license]
13
13
  [![Sponsored by Callstack][callstack-badge]][callstack]
14
14
 
15
- > [!WARNING]
16
- > **Beta Version:** This version (v14) is currently in beta. APIs and behavior may change before the stable release. Please report any issues you encounter.
17
- >
18
- > For stable version (v13) see [README-v13.md](./README-v13.md).
19
-
20
15
  ## The problem
21
16
 
22
17
  You want to write maintainable tests for your React Native components. Your tests should avoid implementation details and focus on giving you confidence. They should remain maintainable so refactors (changes to implementation but not functionality) don't break your tests and slow you and your team down.
@@ -34,7 +29,7 @@ This project is inspired by [React Testing Library](https://github.com/testing-l
34
29
  Open a Terminal in your project's folder and run:
35
30
 
36
31
  ```sh
37
- npm install --save-dev @testing-library/react-native@alpha
32
+ npm install --save-dev @testing-library/react-native
38
33
  ```
39
34
 
40
35
  This library has a `peerDependencies` listing for [Test Renderer](https://github.com/mdjastrzebski/test-renderer). Make sure to install it as a dev dependency:
@@ -140,14 +140,17 @@ function computeAriaModal(instance) {
140
140
  return instance.props['aria-modal'] ?? instance.props.accessibilityViewIsModal;
141
141
  }
142
142
  function computeAriaLabel(instance) {
143
- const labelElementId = instance.props['aria-labelledby'] ?? instance.props.accessibilityLabelledBy;
144
- if (labelElementId) {
143
+ const labelElementIds = getAriaLabelledByIds(instance);
144
+ if (labelElementIds.length > 0) {
145
145
  const container = (0, _componentTree.getContainerInstance)(instance);
146
- const labelInstance = (0, _findAll.findAll)(container, node => (0, _componentTree.isTestInstance)(node) && node.props.nativeID === labelElementId, {
147
- includeHiddenElements: true
148
- });
149
- if (labelInstance.length > 0) {
150
- return (0, _textContent.getTextContent)(labelInstance[0]);
146
+ const labelTexts = labelElementIds.map(labelElementId => {
147
+ const labelInstance = (0, _findAll.findAll)(container, node => (0, _componentTree.isTestInstance)(node) && node.props.nativeID === labelElementId, {
148
+ includeHiddenElements: true
149
+ });
150
+ return labelInstance.length > 0 ? (0, _textContent.getTextContent)(labelInstance[0]) : undefined;
151
+ }).filter(labelText => labelText !== undefined);
152
+ if (labelTexts.length > 0) {
153
+ return labelTexts.join(' ').trim().replace(/\s+/g, ' ');
151
154
  }
152
155
  }
153
156
  const explicitLabel = instance.props['aria-label'] ?? instance.props.accessibilityLabel;
@@ -161,6 +164,20 @@ function computeAriaLabel(instance) {
161
164
  }
162
165
  return undefined;
163
166
  }
167
+ function getAriaLabelledByIds(instance) {
168
+ const ariaLabelledBy = instance.props['aria-labelledby'];
169
+ if (typeof ariaLabelledBy === 'string') {
170
+ return [ariaLabelledBy];
171
+ }
172
+ const accessibilityLabelledBy = instance.props.accessibilityLabelledBy;
173
+ if (Array.isArray(accessibilityLabelledBy)) {
174
+ return accessibilityLabelledBy;
175
+ }
176
+ if (typeof accessibilityLabelledBy === 'string') {
177
+ return [accessibilityLabelledBy];
178
+ }
179
+ return [];
180
+ }
164
181
 
165
182
  // See: https://github.com/callstack/react-native-testing-library/wiki/Accessibility:-State#busy-state
166
183
  function computeAriaBusy({
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accessibility.js","names":["_reactNative","require","_componentTree","_findAll","_hostComponentNames","_textContent","_textInput","accessibilityStateKeys","exports","accessibilityValueKeys","isHiddenFromAccessibility","instance","cache","current","isCurrentSubtreeInaccessible","get","undefined","isSubtreeInaccessible","set","parent","isInaccessible","props","accessibilityElementsHidden","importantForAccessibility","flatStyle","StyleSheet","flatten","style","display","hostSiblings","getInstanceSiblings","some","sibling","computeAriaModal","isAccessibilityElement","isHostImage","alt","accessible","isHostText","isHostTextInput","isHostSwitch","getRole","explicitRole","role","accessibilityRole","normalizeRole","accessibilityViewIsModal","computeAriaLabel","labelElementIds","getAriaLabelledByIds","length","container","getContainerInstance","labelTexts","map","labelElementId","labelInstance","findAll","node","isTestInstance","nativeID","includeHiddenElements","getTextContent","filter","labelText","join","trim","replace","explicitLabel","accessibilityLabel","ariaLabelledBy","accessibilityLabelledBy","Array","isArray","computeAriaBusy","accessibilityState","busy","computeAriaChecked","value","rolesSupportingCheckedState","checked","computeAriaDisabled","isEditableTextInput","disabled","computeAriaExpanded","expanded","computeAriaSelected","selected","computeAriaValue","accessibilityValue","ariaValueMax","ariaValueMin","ariaValueNow","ariaValueText","max","min","now","text","computeAccessibleName","options","label","placeholder","root","parts","child","children","push","childLabel","checkbox","radio","switch"],"sources":["../../src/helpers/accessibility.ts"],"sourcesContent":["import type { AccessibilityRole, AccessibilityState, AccessibilityValue, Role } from 'react-native';\nimport { StyleSheet } from 'react-native';\nimport type { TestInstance } from 'test-renderer';\n\nimport { getContainerInstance, getInstanceSiblings, isTestInstance } from './component-tree';\nimport { findAll } from './find-all';\nimport { isHostImage, isHostSwitch, isHostText, isHostTextInput } from './host-component-names';\nimport { getTextContent } from './text-content';\nimport { isEditableTextInput } from './text-input';\n\ntype IsInaccessibleOptions = {\n cache?: WeakMap<TestInstance, boolean>;\n};\n\nexport const accessibilityStateKeys: (keyof AccessibilityState)[] = [\n 'disabled',\n 'selected',\n 'checked',\n 'busy',\n 'expanded',\n];\n\nexport const accessibilityValueKeys: (keyof AccessibilityValue)[] = ['min', 'max', 'now', 'text'];\n\nexport function isHiddenFromAccessibility(\n instance: TestInstance | null,\n { cache }: IsInaccessibleOptions = {},\n): boolean {\n if (instance == null) {\n return true;\n }\n\n let current: TestInstance | null = instance;\n while (current) {\n let isCurrentSubtreeInaccessible = cache?.get(current);\n\n if (isCurrentSubtreeInaccessible === undefined) {\n isCurrentSubtreeInaccessible = isSubtreeInaccessible(current);\n cache?.set(current, isCurrentSubtreeInaccessible);\n }\n\n if (isCurrentSubtreeInaccessible) {\n return true;\n }\n\n current = current.parent;\n }\n\n return false;\n}\n\n/** RTL-compatibility alias for `isHiddenFromAccessibility` */\nexport const isInaccessible = isHiddenFromAccessibility;\n\nfunction isSubtreeInaccessible(instance: TestInstance): boolean {\n // See: https://reactnative.dev/docs/accessibility#aria-hidden\n if (instance.props['aria-hidden']) {\n return true;\n }\n\n // iOS: accessibilityElementsHidden\n // See: https://reactnative.dev/docs/accessibility#accessibilityelementshidden-ios\n if (instance.props.accessibilityElementsHidden) {\n return true;\n }\n\n // Android: importantForAccessibility\n // See: https://reactnative.dev/docs/accessibility#importantforaccessibility-android\n if (instance.props.importantForAccessibility === 'no-hide-descendants') {\n return true;\n }\n\n // Note that `opacity: 0` is not treated as inaccessible on iOS\n const flatStyle = StyleSheet.flatten(instance.props.style) ?? {};\n if (flatStyle.display === 'none') return true;\n\n // iOS: accessibilityViewIsModal or aria-modal\n // See: https://reactnative.dev/docs/accessibility#accessibilityviewismodal-ios\n const hostSiblings = getInstanceSiblings(instance);\n if (hostSiblings.some((sibling) => computeAriaModal(sibling))) {\n return true;\n }\n\n return false;\n}\n\nexport function isAccessibilityElement(instance: TestInstance | null): boolean {\n if (instance == null) {\n return false;\n }\n\n // https://github.com/facebook/react-native/blob/8dabed60f456e76a9e53273b601446f34de41fb5/packages/react-native/Libraries/Image/Image.ios.js#L172\n if (isHostImage(instance) && instance.props.alt !== undefined) {\n return true;\n }\n\n if (instance.props.accessible !== undefined) {\n return instance.props.accessible;\n }\n\n return isHostText(instance) || isHostTextInput(instance) || isHostSwitch(instance);\n}\n\n/**\n * Returns the accessibility role for given element. It will return explicit\n * role from either `role` or `accessibilityRole` props if set.\n *\n * If explicit role is not available, it would try to return default element\n * role:\n * - `text` for `Text` elements\n *\n * In all other cases this functions returns `none`.\n *\n * @param instance\n * @returns\n */\nexport function getRole(instance: TestInstance): Role | AccessibilityRole {\n const explicitRole = instance.props.role ?? instance.props.accessibilityRole;\n if (explicitRole) {\n return normalizeRole(explicitRole);\n }\n\n if (isHostText(instance)) {\n return 'text';\n }\n\n // Note: host Image elements report \"image\" role in screen reader only on Android, but not on iOS.\n // It's better to require explicit role for Image elements.\n\n return 'none';\n}\n\n/**\n * There are some duplications between (ARIA) `Role` and `AccessibilityRole` types.\n * Resolve them by using ARIA `Role` type where possible.\n *\n * @param role Role to normalize\n * @returns Normalized role\n */\nexport function normalizeRole(role: string): Role | AccessibilityRole {\n if (role === 'image') {\n return 'img';\n }\n\n return role as Role | AccessibilityRole;\n}\n\nexport function computeAriaModal(instance: TestInstance): boolean | undefined {\n return instance.props['aria-modal'] ?? instance.props.accessibilityViewIsModal;\n}\n\nexport function computeAriaLabel(instance: TestInstance): string | undefined {\n const labelElementIds = getAriaLabelledByIds(instance);\n if (labelElementIds.length > 0) {\n const container = getContainerInstance(instance);\n const labelTexts = labelElementIds\n .map((labelElementId) => {\n const labelInstance = findAll(\n container,\n (node) => isTestInstance(node) && node.props.nativeID === labelElementId,\n { includeHiddenElements: true },\n );\n\n return labelInstance.length > 0 ? getTextContent(labelInstance[0]) : undefined;\n })\n .filter((labelText): labelText is string => labelText !== undefined);\n\n if (labelTexts.length > 0) {\n return labelTexts.join(' ').trim().replace(/\\s+/g, ' ');\n }\n }\n\n const explicitLabel = instance.props['aria-label'] ?? instance.props.accessibilityLabel;\n if (explicitLabel) {\n return explicitLabel;\n }\n\n //https://github.com/facebook/react-native/blob/8dabed60f456e76a9e53273b601446f34de41fb5/packages/react-native/Libraries/Image/Image.ios.js#L173\n if (isHostImage(instance) && instance.props.alt) {\n return instance.props.alt;\n }\n\n return undefined;\n}\n\nfunction getAriaLabelledByIds(instance: TestInstance): string[] {\n const ariaLabelledBy = instance.props['aria-labelledby'];\n if (typeof ariaLabelledBy === 'string') {\n return [ariaLabelledBy];\n }\n\n const accessibilityLabelledBy = instance.props.accessibilityLabelledBy;\n if (Array.isArray(accessibilityLabelledBy)) {\n return accessibilityLabelledBy;\n }\n\n if (typeof accessibilityLabelledBy === 'string') {\n return [accessibilityLabelledBy];\n }\n\n return [];\n}\n\n// See: https://github.com/callstack/react-native-testing-library/wiki/Accessibility:-State#busy-state\nexport function computeAriaBusy({ props }: TestInstance): boolean {\n return props['aria-busy'] ?? props.accessibilityState?.busy ?? false;\n}\n\n// See: https://github.com/callstack/react-native-testing-library/wiki/Accessibility:-State#checked-state\nexport function computeAriaChecked(instance: TestInstance): AccessibilityState['checked'] {\n const { props } = instance;\n\n if (isHostSwitch(instance)) {\n return props.value;\n }\n\n const role = getRole(instance);\n if (!rolesSupportingCheckedState[role]) {\n return undefined;\n }\n\n return props['aria-checked'] ?? props.accessibilityState?.checked;\n}\n\n// See: https://github.com/callstack/react-native-testing-library/wiki/Accessibility:-State#disabled-state\nexport function computeAriaDisabled(instance: TestInstance): boolean {\n if (isHostTextInput(instance) && !isEditableTextInput(instance)) {\n return true;\n }\n\n const { props } = instance;\n\n if (isHostText(instance) && props.disabled) {\n return true;\n }\n\n return props['aria-disabled'] ?? props.accessibilityState?.disabled ?? false;\n}\n\n// See: https://github.com/callstack/react-native-testing-library/wiki/Accessibility:-State#expanded-state\nexport function computeAriaExpanded({ props }: TestInstance): boolean | undefined {\n return props['aria-expanded'] ?? props.accessibilityState?.expanded;\n}\n\n// See: https://github.com/callstack/react-native-testing-library/wiki/Accessibility:-State#selected-state\nexport function computeAriaSelected({ props }: TestInstance): boolean {\n return props['aria-selected'] ?? props.accessibilityState?.selected ?? false;\n}\n\nexport function computeAriaValue(instance: TestInstance): AccessibilityValue {\n const {\n accessibilityValue,\n 'aria-valuemax': ariaValueMax,\n 'aria-valuemin': ariaValueMin,\n 'aria-valuenow': ariaValueNow,\n 'aria-valuetext': ariaValueText,\n } = instance.props;\n\n return {\n max: ariaValueMax ?? accessibilityValue?.max,\n min: ariaValueMin ?? accessibilityValue?.min,\n now: ariaValueNow ?? accessibilityValue?.now,\n text: ariaValueText ?? accessibilityValue?.text,\n };\n}\n\ntype ComputeAccessibleNameOptions = {\n root?: boolean;\n};\n\nexport function computeAccessibleName(\n instance: TestInstance,\n options?: ComputeAccessibleNameOptions,\n): string | undefined {\n const label = computeAriaLabel(instance);\n if (label) {\n return label;\n }\n\n if (isHostTextInput(instance) && instance.props.placeholder && options?.root !== false) {\n return instance.props.placeholder;\n }\n\n const parts = [];\n for (const child of instance.children) {\n if (typeof child === 'string') {\n if (child) {\n parts.push(child);\n }\n } else {\n const childLabel = computeAccessibleName(child, { root: false });\n if (childLabel) {\n parts.push(childLabel);\n }\n }\n }\n\n return parts.join(' ');\n}\n\ntype RoleSupportMap = Partial<Record<Role | AccessibilityRole, true>>;\n\nexport const rolesSupportingCheckedState: RoleSupportMap = {\n checkbox: true,\n radio: true,\n switch: true,\n};\n"],"mappings":"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","ignoreList":[]}
package/docs/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # React Native Testing Library package docs
2
+
3
+ These markdown files are bundled with the npm package for coding agents. They describe the installed package version.
4
+
5
+ Start with [LLM Guidelines](./guides/llm-guidelines.md) for rules overview, or use the included page list below to load specific references.
6
+
7
+ ## Included pages
8
+
9
+ - [LLM Guidelines](./guides/llm-guidelines.md) - Quick rules for agents writing RNTL tests.
10
+ - [Quick Start](./guides/quick-start.md) - Installation and setup basics.
11
+ - [How to Query](./guides/how-to-query.md) - Query priority and selection guidance.
12
+ - [Common Mistakes](./guides/common-mistakes.md) - Common anti-patterns and preferred alternatives.
13
+ - [Troubleshooting](./guides/troubleshooting.md) - Common integration and runtime issues.
14
+ - [Testing Environment](./guides/testing-environment.md) - How RNTL simulates React Native under tests.
15
+ - [Understanding act](./guides/understanding-act.md) - How act warnings happen and how to resolve them.
16
+ - [Migration to 14.x](./guides/migration-v14.md) - Breaking changes and upgrade steps for RNTL v14.
17
+ - [API Overview](./api/overview.md) - Top-level API map.
18
+ - [render](./api/render.md) - Rendering components in tests.
19
+ - [screen](./api/screen.md) - Recommended global query surface.
20
+ - [Queries](./api/queries.md) - Query variants and predicates.
21
+ - [Jest Matchers](./api/jest-matchers.md) - Built-in RNTL assertions.
22
+ - [User Event](./api/user-event.md) - Realistic user interactions.
23
+ - [Fire Event](./api/fire-event.md) - Low-level event triggering.
24
+ - [Async Utilities](./api/async-utilities.md) - Async queries and wait helpers.
25
+ - [renderHook](./api/render-hook.md) - Testing custom hooks.
26
+ - [Configuration](./api/configuration.md) - Runtime configuration options.
27
+ - [Accessibility](./api/accessibility.md) - Accessibility helpers and hidden elements.
28
+ - [Other Helpers](./api/other-helpers.md) - within, act, cleanup, and related helpers.
29
+ - [Custom Render](./cookbook/custom-render.md) - Reusable render wrappers.
30
+ - [Async Events](./cookbook/async-events.md) - Testing async interactions.
31
+ - [Network Requests](./cookbook/network-requests.md) - Testing components that make network requests.
@@ -0,0 +1,26 @@
1
+ # Accessibility
2
+
3
+ ## `isHiddenFromAccessibility`
4
+
5
+ ```ts
6
+ function isHiddenFromAccessibility(instance: TestInstance | null): boolean {}
7
+ ```
8
+
9
+ Also available as `isInaccessible()` alias for React Testing Library compatibility.
10
+
11
+ Checks if given element is hidden from assistive technology, e.g. screen readers.
12
+
13
+ > [!NOTE]
14
+ > Like [`isInaccessible`](https://testing-library.com/docs/dom-testing-library/api-accessibility/#isinaccessible) function from DOM Testing Library this function considers both accessibility elements and presentational elements (regular `View`s) to be accessible, unless they are hidden in terms of host platform.
15
+ >
16
+ > This covers only part of [ARIA notion of Accessibility Tree](https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion), as ARIA excludes both hidden and presentational elements from the Accessibility Tree.
17
+
18
+ For the scope of this function, element is inaccessible when it, or any of its ancestors, meets any of the following conditions:
19
+
20
+ - it has `display: none` style
21
+ - it has [`aria-hidden`](https://reactnative.dev/docs/accessibility#aria-hidden) prop set to `true`
22
+ - it has [`accessibilityElementsHidden`](https://reactnative.dev/docs/accessibility#accessibilityelementshidden-ios) prop set to `true`
23
+ - it has [`importantForAccessibility`](https://reactnative.dev/docs/accessibility#importantforaccessibility-android) prop set to `no-hide-descendants`
24
+ - it has sibling host element with either [`aria-modal`](https://reactnative.dev/docs/accessibility#aria-modal-ios) or [`accessibilityViewIsModal`](https://reactnative.dev/docs/accessibility#accessibilityviewismodal-ios) prop set to `true`
25
+
26
+ Specifying `accessible={false}`, `role="none"`, `accessibilityRole="none"`, or `importantForAccessibility="no"` props does not cause the element to become inaccessible.
@@ -0,0 +1,137 @@
1
+ # Async utilities
2
+
3
+ ## `findBy*` queries
4
+
5
+ The `findBy*` queries are used to find elements that are not instantly available but will be added as a result of some asynchronous action. Learn more details [here](./queries.md#find-by).
6
+
7
+ ## `waitFor`
8
+
9
+ ```tsx
10
+ function waitFor<T>(
11
+ expectation: () => T,
12
+ options?: {
13
+ timeout?: number;
14
+ interval?: number;
15
+ onTimeout?: (error: Error) => Error;
16
+ },
17
+ ): Promise<T>;
18
+ ```
19
+
20
+ Waits for the `expectation` callback to pass. `waitFor` runs the callback multiple times until timeout is reached, as specified by the `timeout` and `interval` options. The callback must throw an error when the expectation is not met. Returning any value, including a falsy one, is treated as meeting the expectation, and the callback result is returned to the caller.
21
+
22
+ ```tsx
23
+ await waitFor(() => expect(mockFunction).toHaveBeenCalledWith());
24
+ ```
25
+
26
+ `waitFor` executes the `expectation` callback every `interval` (default: 50 ms) until `timeout` (default: 1000 ms) is reached. Execution stops as soon as the callback doesn't throw an error, and the callback's return value is returned to the caller. If timeout is reached, `waitFor` re-throws the final error thrown by `expectation`.
27
+
28
+ ```tsx
29
+ // ❌ `waitFor` will return immediately because callback does not throw
30
+ await waitFor(() => false);
31
+ ```
32
+
33
+ `waitFor` is an async function so you need to `await` the result to pause test execution.
34
+
35
+ ```jsx
36
+ // ❌ missing `await`: `waitFor` will just return Promise that will be rejected when the timeout is reached
37
+ waitFor(() => expect(1).toBe(2));
38
+ ```
39
+
40
+ > [!NOTE]
41
+ > You can enforce awaiting `waitFor` by using the [await-async-utils](https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/await-async-utils.md) rule from [eslint-plugin-testing-library](https://github.com/testing-library/eslint-plugin-testing-library).
42
+
43
+ Since `waitFor` runs the `expectation` callback multiple times, [avoid performing side effects](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#performing-side-effects-in-waitfor) in `waitFor`.
44
+
45
+ ```jsx
46
+ await waitFor(async () => {
47
+ // ❌ button will be pressed on each waitFor iteration
48
+ await fireEvent.press(screen.getByText('press me'));
49
+ expect(mockOnPress).toHaveBeenCalled();
50
+ });
51
+ ```
52
+
53
+ > [!NOTE]
54
+ > Avoiding side effects in `expectation` callback can be partially enforced with the [`no-wait-for-side-effects` rule](https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-wait-for-side-effects.md).
55
+
56
+ Use a [single assertion per `waitFor`](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#having-multiple-assertions-in-a-single-waitfor-callback) for consistency and faster failing tests. For multiple assertions, use separate `waitFor` calls. Often you won't need to wrap the second assertion in `waitFor` since the first one waits for the asynchronous change.
57
+
58
+ `waitFor` checks whether Jest fake timers are enabled and adapts its behavior in such case. The following snippet is a simplified version of how it behaves when fake timers are enabled:
59
+
60
+ ```tsx
61
+ let fakeTimeRemaining = timeout;
62
+ let lastError;
63
+
64
+ while (fakeTimeRemaining > 0) {
65
+ fakeTimeRemaining = fakeTimeRemaining - interval;
66
+ jest.advanceTimersByTime(interval);
67
+ try {
68
+ // resolve
69
+ return expectation();
70
+ } catch (error) {
71
+ lastError = error;
72
+ }
73
+ }
74
+
75
+ // reject
76
+ throw lastError;
77
+ ```
78
+
79
+ In the following example we test that a function is called after 10 seconds using fake timers. With fake timers, the test doesn't depend on real time passing, making it faster and more reliable. We don't need to advance fake timers through Jest's API because `waitFor` handles this.
80
+
81
+ ```tsx
82
+ // in component
83
+ setTimeout(() => {
84
+ someFunction();
85
+ }, 10000);
86
+
87
+ // in test
88
+ jest.useFakeTimers();
89
+
90
+ await waitFor(
91
+ () => {
92
+ expect(someFunction).toHaveBeenCalledWith();
93
+ },
94
+ { timeout: 10000 },
95
+ );
96
+ ```
97
+
98
+ > [!NOTE]
99
+ > If you receive warnings related to `act()` function consult our [Understanding Act](../guides/understanding-act.md) function document.
100
+
101
+ ### Options
102
+
103
+ - `timeout`: How long to wait for, in ms. Defaults to 1000 ms (configured by `asyncUtilTimeout` option).
104
+ - `interval`: How often to check, in ms. Defaults to 50 ms.
105
+ - `onTimeout`: Callback to transform the error before it's thrown. Useful for debugging, e.g., `onTimeout: () => { screen.debug(); }`.
106
+
107
+ ## `waitForElementToBeRemoved`
108
+
109
+ ```ts
110
+ function waitForElementToBeRemoved<T>(
111
+ expectation: () => T,
112
+ options?: {
113
+ timeout?: number;
114
+ interval?: number;
115
+ onTimeout?: (error: Error) => Error;
116
+ },
117
+ ): Promise<T>;
118
+ ```
119
+
120
+ Waits for non-deterministic periods of time until queried element is removed or times out. `waitForElementToBeRemoved` periodically calls `expectation` every `interval` milliseconds to determine whether the element has been removed or not.
121
+
122
+ ```jsx
123
+ import { render, screen, waitForElementToBeRemoved } from '@testing-library/react-native';
124
+
125
+ test('waiting for an Banana to be removed', async () => {
126
+ await render(<Banana />);
127
+
128
+ await waitForElementToBeRemoved(() => screen.getByText('Banana ready'));
129
+ });
130
+ ```
131
+
132
+ This method expects that the element is initially present in the render tree and then is removed from it. If the element is not present when you call this method it throws an error.
133
+
134
+ You can use any of `getBy`, `getAllBy`, `queryBy` and `queryAllBy` queries for `expectation` parameter.
135
+
136
+ > [!NOTE]
137
+ > If you receive warnings related to `act()` function consult our [Understanding Act](../guides/understanding-act.md) function document.
@@ -0,0 +1,61 @@
1
+ # Configuration
2
+
3
+ ## `configure`
4
+
5
+ ```ts
6
+ type Config = {
7
+ /** Default timeout, in ms, for `waitFor` and `findBy*` queries. */
8
+ asyncUtilTimeout: number;
9
+
10
+ /** Default value for `includeHiddenElements` query option. */
11
+ defaultIncludeHiddenElements: boolean;
12
+
13
+ /** Default options for `debug` helper. */
14
+ defaultDebugOptions?: Partial<DebugOptions>;
15
+ };
16
+
17
+ type ConfigAliasOptions = {
18
+ /** RTL-compatibility alias for `defaultIncludeHiddenElements`. */
19
+ defaultHidden: boolean;
20
+ };
21
+
22
+ function configure(options: Partial<Config & ConfigAliasOptions>) {}
23
+ ```
24
+
25
+ ### `asyncUtilTimeout` option
26
+
27
+ Default timeout, in ms, for async helper functions (`waitFor`, `waitForElementToBeRemoved`) and `findBy*` queries. Defaults to 1000 ms.
28
+
29
+ ### `defaultIncludeHiddenElements` option
30
+
31
+ Default value for [includeHiddenElements](./queries.md#includehiddenelements-option) query option for all queries. The default value is set to `false`, so all queries will not match [elements hidden from accessibility](#ishiddenfromaccessibility). This is because the users of the app would not be able to see such elements.
32
+
33
+ This option is also available as `defaultHidden` alias for compatibility with [React Testing Library](https://testing-library.com/docs/dom-testing-library/api-configuration/#defaulthidden).
34
+
35
+ ### `defaultDebugOptions` option
36
+
37
+ Default [debug options](#debug) to be used when calling `debug()`. These default options will be overridden by the ones you specify directly when calling `debug()`.
38
+
39
+ ## `resetToDefaults()`
40
+
41
+ ```ts
42
+ function resetToDefaults() {}
43
+ ```
44
+
45
+ ## Environment variables
46
+
47
+ ### `RNTL_SKIP_AUTO_CLEANUP`
48
+
49
+ Set to `true` to disable automatic `cleanup()` after each test. It works the same as importing `react-native-testing-library/dont-cleanup-after-each` or using `react-native-testing-library/pure`.
50
+
51
+ ```shell
52
+ $ RNTL_SKIP_AUTO_CLEANUP=true jest
53
+ ```
54
+
55
+ ### `RNTL_SKIP_AUTO_DETECT_FAKE_TIMERS`
56
+
57
+ Set to `true` to disable auto-detection of fake timers. This might be useful in rare cases when you want to use non-Jest fake timers. See [issue #886](https://github.com/callstack/react-native-testing-library/issues/886) for more details.
58
+
59
+ ```shell
60
+ $ RNTL_SKIP_AUTO_DETECT_FAKE_TIMERS=true jest
61
+ ```
@@ -0,0 +1,165 @@
1
+ # Fire Event API
2
+
3
+ ## `fireEvent`
4
+
5
+ > [!NOTE]
6
+ > For common events like `press` or `type`, use the [User Event API](./user-event.md). It simulates events more realistically by emitting a sequence of events with proper event objects that mimic React Native runtime behavior.
7
+ >
8
+ > Use Fire Event for cases not supported by User Event and for triggering event handlers on composite components.
9
+
10
+ ```ts
11
+ function fireEvent(instance: TestInstance, eventName: string, ...data: unknown[]): Promise<unknown>;
12
+ ```
13
+
14
+ The `fireEvent` API triggers event handlers on both host and composite components. It traverses the component tree bottom-up from the passed element to find an enabled event handler named `onXxx` where `xxx` is the event name.
15
+
16
+ Unlike User Event, this API does not automatically pass event object to event handler, this is responsibility of the user to construct such object.
17
+
18
+ The base `fireEvent(instance, eventName, ...data)` API can pass multiple custom arguments to the handler. Convenience helpers such as `fireEvent.press` and `fireEvent.scroll` are different: they create a default event object and accept one optional object to merge into it.
19
+
20
+ This function uses async `act` internally to execute all pending React updates during event handling.
21
+
22
+ ```jsx
23
+ import { render, screen, fireEvent } from '@testing-library/react-native';
24
+
25
+ test('fire changeText event', async () => {
26
+ const onEventMock = jest.fn();
27
+ await render(
28
+ // MyComponent renders TextInput which has a placeholder 'Enter details'
29
+ // and with `onChangeText` bound to handleChangeText
30
+ <MyComponent handleChangeText={onEventMock} />,
31
+ );
32
+
33
+ await fireEvent(screen.getByPlaceholderText('change'), 'onChangeText', 'ab');
34
+ expect(onEventMock).toHaveBeenCalledWith('ab');
35
+ });
36
+ ```
37
+
38
+ > [!NOTE]
39
+ > `fireEvent` performs checks that should prevent events firing on disabled elements.
40
+
41
+ An example using `fireEvent` with native events that aren't already aliased by the `fireEvent` api.
42
+
43
+ ```jsx
44
+ import { TextInput, View } from 'react-native';
45
+ import { fireEvent, render, screen } from '@testing-library/react-native';
46
+
47
+ const onBlurMock = jest.fn();
48
+
49
+ await render(
50
+ <View>
51
+ <TextInput placeholder="my placeholder" onBlur={onBlurMock} />
52
+ </View>,
53
+ );
54
+
55
+ // you can omit the `on` prefix
56
+ await fireEvent(screen.getByPlaceholderText('my placeholder'), 'blur');
57
+ ```
58
+
59
+ FireEvent exposes convenience methods for common events like: `press`, `changeText`, `scroll`.
60
+
61
+ ### `fireEvent.press`
62
+
63
+ > [!NOTE]
64
+ > Use the User Event [`press()`](./user-event.md#press) helper instead. It simulates press interactions more realistically, including pressable support.
65
+
66
+ ```tsx
67
+ fireEvent.press: (
68
+ instance: TestInstance,
69
+ eventProps?: Record<string, unknown>,
70
+ ) => Promise<void>
71
+ ```
72
+
73
+ Builds a press event object, merges `eventProps` into it, and invokes the `press` handler on the element or nearest eligible parent.
74
+
75
+ ```jsx
76
+ import { View, Text, TouchableOpacity } from 'react-native';
77
+ import { render, screen, fireEvent } from '@testing-library/react-native';
78
+
79
+ const onPressMock = jest.fn();
80
+ const eventData = {
81
+ nativeEvent: {
82
+ pageX: 20,
83
+ pageY: 30,
84
+ },
85
+ };
86
+
87
+ await render(
88
+ <View>
89
+ <TouchableOpacity onPress={onPressMock}>
90
+ <Text>Press me</Text>
91
+ </TouchableOpacity>
92
+ </View>,
93
+ );
94
+
95
+ await fireEvent.press(screen.getByText('Press me'), eventData);
96
+ expect(onPressMock).toHaveBeenCalledWith(expect.objectContaining(eventData));
97
+ ```
98
+
99
+ ### `fireEvent.changeText`
100
+
101
+ > [!NOTE]
102
+ > Use the User Event [`type()`](./user-event.md#type) helper instead. It simulates text change interactions more realistically, including key-by-key typing, element focus, and other editing events.
103
+
104
+ ```tsx
105
+ fireEvent.changeText: (
106
+ instance: TestInstance,
107
+ text: string,
108
+ ) => Promise<void>
109
+ ```
110
+
111
+ Invokes `changeText` event handler on the element or parent element in the tree.
112
+
113
+ ```jsx
114
+ import { View, TextInput } from 'react-native';
115
+ import { render, screen, fireEvent } from '@testing-library/react-native';
116
+
117
+ const onChangeTextMock = jest.fn();
118
+ const CHANGE_TEXT = 'content';
119
+
120
+ await render(
121
+ <View>
122
+ <TextInput placeholder="Enter data" onChangeText={onChangeTextMock} />
123
+ </View>,
124
+ );
125
+
126
+ await fireEvent.changeText(screen.getByPlaceholderText('Enter data'), CHANGE_TEXT);
127
+ ```
128
+
129
+ ### `fireEvent.scroll`
130
+
131
+ > [!NOTE]
132
+ > Prefer [`user.scrollTo`](./user-event.md#scrollto) over `fireEvent.scroll` for `ScrollView`, `FlatList`, and `SectionList` components. User Event simulates events more realistically based on React Native runtime behavior.
133
+
134
+ ```tsx
135
+ fireEvent.scroll: (
136
+ instance: TestInstance,
137
+ eventProps?: Record<string, unknown>,
138
+ ) => Promise<void>
139
+ ```
140
+
141
+ Builds a scroll event object, merges `eventProps` into it, and invokes the `scroll` handler on the element or nearest eligible parent.
142
+
143
+ #### On a `ScrollView`
144
+
145
+ ```jsx
146
+ import { ScrollView, Text } from 'react-native';
147
+ import { render, screen, fireEvent } from '@testing-library/react-native';
148
+
149
+ const onScrollMock = jest.fn();
150
+ const eventData = {
151
+ nativeEvent: {
152
+ contentOffset: {
153
+ y: 200,
154
+ },
155
+ },
156
+ };
157
+
158
+ await render(
159
+ <ScrollView testID="scroll-view" onScroll={onScrollMock}>
160
+ <Text>Content</Text>
161
+ </ScrollView>,
162
+ );
163
+
164
+ await fireEvent.scroll(screen.getByTestId('scroll-view'), eventData);
165
+ ```