From 1922d67c9239e53ec5112684bc2f3ea8f1639565 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 15 Jan 2026 17:20:52 +0000 Subject: [PATCH] deploy: bf946b07cfabd3516618e840b8236bf3c6f4a9be --- 12.x/cookbook/advanced/network-requests.html | 2 +- 12.x/cookbook/basics/async-tests.html | 2 +- 12.x/cookbook/basics/custom-render.html | 2 +- 12.x/cookbook/index.html | 2 +- 12.x/cookbook/state-management/jotai.html | 2 +- 12.x/docs/advanced/testing-env.html | 2 +- 12.x/docs/advanced/understanding-act.html | 2 +- 12.x/docs/api.html | 2 +- 12.x/docs/api/events/fire-event.html | 2 +- 12.x/docs/api/events/user-event.html | 2 +- 12.x/docs/api/jest-matchers.html | 2 +- 12.x/docs/api/misc/accessibility.html | 2 +- 12.x/docs/api/misc/async.html | 2 +- 12.x/docs/api/misc/config.html | 2 +- 12.x/docs/api/misc/other.html | 2 +- 12.x/docs/api/misc/render-hook.html | 2 +- 12.x/docs/api/queries.html | 2 +- 12.x/docs/api/render.html | 2 +- 12.x/docs/api/screen.html | 2 +- 12.x/docs/guides/community-resources.html | 2 +- 12.x/docs/guides/faq.html | 2 +- 12.x/docs/guides/how-to-query.html | 2 +- 12.x/docs/guides/troubleshooting.html | 2 +- 12.x/docs/migration/jest-matchers.html | 2 +- 12.x/docs/migration/previous/v11.html | 2 +- 12.x/docs/migration/previous/v2.html | 2 +- 12.x/docs/migration/previous/v7.html | 2 +- 12.x/docs/migration/previous/v9.html | 2 +- 12.x/docs/migration/v12.html | 2 +- 12.x/docs/start/intro.html | 2 +- 12.x/docs/start/quick-start.html | 2 +- 12.x/index.html | 2 +- 14.x/cookbook/advanced/network-requests.html | 8 +- .../{async-tests.html => async-events.html} | 17 +- 14.x/cookbook/basics/custom-render.html | 23 +- 14.x/cookbook/index.html | 6 +- 14.x/cookbook/state-management/jotai.html | 33 +- 14.x/docs/advanced/testing-env.html | 48 +- .../advanced/third-party-integration.html | 4 +- 14.x/docs/advanced/understanding-act.html | 125 ++-- 14.x/docs/api.html | 6 +- 14.x/docs/api/events/fire-event.html | 22 +- 14.x/docs/api/events/user-event.html | 37 +- 14.x/docs/api/jest-matchers.html | 10 +- 14.x/docs/api/misc/accessibility.html | 8 +- 14.x/docs/api/misc/async.html | 39 +- 14.x/docs/api/misc/config.html | 26 +- 14.x/docs/api/misc/other.html | 34 +- 14.x/docs/api/misc/render-hook.html | 26 +- 14.x/docs/api/queries.html | 56 +- 14.x/docs/api/render.html | 23 +- 14.x/docs/api/screen.html | 17 +- 14.x/docs/guides/community-resources.html | 4 +- 14.x/docs/guides/faq.html | 4 +- 14.x/docs/guides/how-to-query.html | 8 +- 14.x/docs/guides/react-19.html | 67 -- 14.x/docs/guides/troubleshooting.html | 21 +- 14.x/docs/migration/jest-matchers.html | 8 +- 14.x/docs/migration/previous/v11.html | 40 -- 14.x/docs/migration/previous/v12.html | 53 -- 14.x/docs/migration/previous/v7.html | 87 --- 14.x/docs/migration/previous/v9.html | 49 -- 14.x/docs/migration/v11.html | 40 ++ 14.x/docs/migration/v12.html | 53 ++ 14.x/docs/migration/v13.html | 6 +- 14.x/docs/migration/v14.html | 618 +++++++----------- 14.x/docs/migration/{previous => }/v2.html | 6 +- 14.x/docs/migration/v7.html | 87 +++ 14.x/docs/migration/v9.html | 49 ++ 14.x/docs/start/intro.html | 8 +- 14.x/docs/start/quick-start.html | 16 +- 14.x/index.html | 2 +- 404.html | 2 +- cookbook/advanced/network-requests.html | 2 +- cookbook/basics/async-tests.html | 2 +- cookbook/basics/custom-render.html | 2 +- cookbook/index.html | 2 +- cookbook/state-management/jotai.html | 2 +- docs/advanced/testing-env.html | 2 +- docs/advanced/third-party-integration.html | 2 +- docs/advanced/understanding-act.html | 2 +- docs/api.html | 2 +- docs/api/events/fire-event.html | 2 +- docs/api/events/user-event.html | 2 +- docs/api/jest-matchers.html | 2 +- docs/api/misc/accessibility.html | 2 +- docs/api/misc/async.html | 2 +- docs/api/misc/config.html | 2 +- docs/api/misc/other.html | 2 +- docs/api/misc/render-hook.html | 2 +- docs/api/queries.html | 2 +- docs/api/render.html | 2 +- docs/api/screen.html | 2 +- docs/guides/community-resources.html | 2 +- docs/guides/faq.html | 2 +- docs/guides/how-to-query.html | 2 +- docs/guides/react-19.html | 2 +- docs/guides/troubleshooting.html | 2 +- docs/migration/jest-matchers.html | 2 +- docs/migration/previous/v11.html | 2 +- docs/migration/previous/v12.html | 2 +- docs/migration/previous/v2.html | 2 +- docs/migration/previous/v7.html | 2 +- docs/migration/previous/v9.html | 2 +- docs/migration/v13.html | 2 +- docs/start/intro.html | 2 +- docs/start/quick-start.html | 2 +- index.html | 2 +- static/js/2179.4246b248.js | 6 + ...CENSE.txt => 2179.4246b248.js.LICENSE.txt} | 0 static/js/2179.d9a2a7b5.js | 6 - static/js/async/1020.21bafcda.js | 1 + static/js/async/1020.73a20fe8.js | 1 - .../{1290.46b49369.js => 1290.0ea47608.js} | 2 +- static/js/async/2473.225dd9ca.js | 1 - static/js/async/2473.f2ef5a90.js | 1 + static/js/async/3012.5460a8c5.js | 1 + static/js/async/3012.ef6a5af6.js | 1 - static/js/async/3014.29020a96.js | 1 + static/js/async/3014.b9747eed.js | 1 - static/js/async/3241.a9f68d86.js | 1 + static/js/async/3241.c2e74d2b.js | 1 - .../{6409.f3bad53c.js => 3655.55ec9075.js} | 2 +- static/js/async/3748.c600a55e.js | 1 - static/js/async/3815.f906da67.js | 1 + static/js/async/3828.a2961b5a.js | 1 - static/js/async/3858.22f98cfe.js | 1 + static/js/async/3858.3ac4becb.js | 1 - static/js/async/435.2768959d.js | 1 - static/js/async/435.be1e8f69.js | 1 + .../{8756.26448bca.js => 4672.f3cfc7e3.js} | 2 +- .../{1954.b9b89bd7.js => 4682.ee73a00b.js} | 2 +- static/js/async/4804.a2b409b6.js | 1 + static/js/async/4880.2c547bd2.js | 1 - static/js/async/4880.9cbeb824.js | 1 + .../{5263.45dcebf3.js => 5263.56b1ffda.js} | 2 +- static/js/async/5469.0ad2c8f8.js | 1 - static/js/async/5469.b9ad09f3.js | 1 + static/js/async/5658.226b400a.js | 1 - static/js/async/5658.743a1577.js | 1 + static/js/async/5820.39680a91.js | 1 + static/js/async/5820.a37ee32a.js | 1 - static/js/async/5828.0039d489.js | 1 - .../{6096.ce7732dc.js => 6096.2960907a.js} | 2 +- static/js/async/6600.1553f10d.js | 1 - static/js/async/6600.4d7575ff.js | 1 + static/js/async/7308.0db453da.js | 1 + static/js/async/7308.4752c501.js | 1 - .../{7487.674a4463.js => 7487.e74875d7.js} | 2 +- static/js/async/7635.2687c10f.js | 1 - static/js/async/7635.d7bc6016.js | 1 + static/js/async/7804.6a170ee3.js | 1 + static/js/async/7804.c61ebcac.js | 1 - static/js/async/7839.7405d445.js | 1 + static/js/async/7839.a9c6f362.js | 1 - static/js/async/8217.708b7f26.js | 1 + static/js/async/8369.4316ad1f.js | 1 - static/js/async/8369.889c5b23.js | 1 + static/js/async/8425.4bf9e9ab.js | 1 - static/js/async/8425.d29d5475.js | 1 + static/js/async/9498.a8b08324.js | 1 - static/js/index.3586d87d.js | 1 - static/js/index.c5a92868.js | 1 + ...3.json => search_index.13_x.d3d9e1fa.json} | 2 +- static/search_index.14_x.760cea39.json | 1 - static/search_index.14_x.e3d4eafe.json | 1 + 166 files changed, 900 insertions(+), 1105 deletions(-) rename 14.x/cookbook/basics/{async-tests.html => async-events.html} (76%) delete mode 100644 14.x/docs/guides/react-19.html delete mode 100644 14.x/docs/migration/previous/v11.html delete mode 100644 14.x/docs/migration/previous/v12.html delete mode 100644 14.x/docs/migration/previous/v7.html delete mode 100644 14.x/docs/migration/previous/v9.html create mode 100644 14.x/docs/migration/v11.html create mode 100644 14.x/docs/migration/v12.html rename 14.x/docs/migration/{previous => }/v2.html (56%) create mode 100644 14.x/docs/migration/v7.html create mode 100644 14.x/docs/migration/v9.html create mode 100644 static/js/2179.4246b248.js rename static/js/{2179.d9a2a7b5.js.LICENSE.txt => 2179.4246b248.js.LICENSE.txt} (100%) delete mode 100644 static/js/2179.d9a2a7b5.js create mode 100644 static/js/async/1020.21bafcda.js delete mode 100644 static/js/async/1020.73a20fe8.js rename static/js/async/{1290.46b49369.js => 1290.0ea47608.js} (56%) delete mode 100644 static/js/async/2473.225dd9ca.js create mode 100644 static/js/async/2473.f2ef5a90.js create mode 100644 static/js/async/3012.5460a8c5.js delete mode 100644 static/js/async/3012.ef6a5af6.js create mode 100644 static/js/async/3014.29020a96.js delete mode 100644 static/js/async/3014.b9747eed.js create mode 100644 static/js/async/3241.a9f68d86.js delete mode 100644 static/js/async/3241.c2e74d2b.js rename static/js/async/{6409.f3bad53c.js => 3655.55ec9075.js} (93%) delete mode 100644 static/js/async/3748.c600a55e.js create mode 100644 static/js/async/3815.f906da67.js delete mode 100644 static/js/async/3828.a2961b5a.js create mode 100644 static/js/async/3858.22f98cfe.js delete mode 100644 static/js/async/3858.3ac4becb.js delete mode 100644 static/js/async/435.2768959d.js create mode 100644 static/js/async/435.be1e8f69.js rename static/js/async/{8756.26448bca.js => 4672.f3cfc7e3.js} (87%) rename static/js/async/{1954.b9b89bd7.js => 4682.ee73a00b.js} (90%) create mode 100644 static/js/async/4804.a2b409b6.js delete mode 100644 static/js/async/4880.2c547bd2.js create mode 100644 static/js/async/4880.9cbeb824.js rename static/js/async/{5263.45dcebf3.js => 5263.56b1ffda.js} (56%) delete mode 100644 static/js/async/5469.0ad2c8f8.js create mode 100644 static/js/async/5469.b9ad09f3.js delete mode 100644 static/js/async/5658.226b400a.js create mode 100644 static/js/async/5658.743a1577.js create mode 100644 static/js/async/5820.39680a91.js delete mode 100644 static/js/async/5820.a37ee32a.js delete mode 100644 static/js/async/5828.0039d489.js rename static/js/async/{6096.ce7732dc.js => 6096.2960907a.js} (58%) delete mode 100644 static/js/async/6600.1553f10d.js create mode 100644 static/js/async/6600.4d7575ff.js create mode 100644 static/js/async/7308.0db453da.js delete mode 100644 static/js/async/7308.4752c501.js rename static/js/async/{7487.674a4463.js => 7487.e74875d7.js} (83%) delete mode 100644 static/js/async/7635.2687c10f.js create mode 100644 static/js/async/7635.d7bc6016.js create mode 100644 static/js/async/7804.6a170ee3.js delete mode 100644 static/js/async/7804.c61ebcac.js create mode 100644 static/js/async/7839.7405d445.js delete mode 100644 static/js/async/7839.a9c6f362.js create mode 100644 static/js/async/8217.708b7f26.js delete mode 100644 static/js/async/8369.4316ad1f.js create mode 100644 static/js/async/8369.889c5b23.js delete mode 100644 static/js/async/8425.4bf9e9ab.js create mode 100644 static/js/async/8425.d29d5475.js delete mode 100644 static/js/async/9498.a8b08324.js delete mode 100644 static/js/index.3586d87d.js create mode 100644 static/js/index.c5a92868.js rename static/{search_index.13_x.2b902103.json => search_index.13_x.d3d9e1fa.json} (99%) delete mode 100644 static/search_index.14_x.760cea39.json create mode 100644 static/search_index.14_x.e3d4eafe.json diff --git a/12.x/cookbook/advanced/network-requests.html b/12.x/cookbook/advanced/network-requests.html index 5affba22..8e05c2ab 100644 --- a/12.x/cookbook/advanced/network-requests.html +++ b/12.x/cookbook/advanced/network-requests.html @@ -6,7 +6,7 @@ Network Requests - React Native Testing Library - +

Network Requests

diff --git a/12.x/cookbook/basics/async-tests.html b/12.x/cookbook/basics/async-tests.html index 2f8ee75f..e3de2a5f 100644 --- a/12.x/cookbook/basics/async-tests.html +++ b/12.x/cookbook/basics/async-tests.html @@ -6,7 +6,7 @@ Async tests - React Native Testing Library - +

Async tests

diff --git a/12.x/cookbook/basics/custom-render.html b/12.x/cookbook/basics/custom-render.html index 88422708..c18255e9 100644 --- a/12.x/cookbook/basics/custom-render.html +++ b/12.x/cookbook/basics/custom-render.html @@ -6,7 +6,7 @@ Custom `render` function - React Native Testing Library - +

Custom render function

diff --git a/12.x/cookbook/index.html b/12.x/cookbook/index.html index 3ada49a1..de4d2870 100644 --- a/12.x/cookbook/index.html +++ b/12.x/cookbook/index.html @@ -6,7 +6,7 @@ Introduction - React Native Testing Library - +

Introduction

diff --git a/12.x/cookbook/state-management/jotai.html b/12.x/cookbook/state-management/jotai.html index 169a84a3..2d98db3b 100644 --- a/12.x/cookbook/state-management/jotai.html +++ b/12.x/cookbook/state-management/jotai.html @@ -6,7 +6,7 @@ Jotai - React Native Testing Library - +

Jotai

diff --git a/12.x/docs/advanced/testing-env.html b/12.x/docs/advanced/testing-env.html index 92101d6b..28493d58 100644 --- a/12.x/docs/advanced/testing-env.html +++ b/12.x/docs/advanced/testing-env.html @@ -6,7 +6,7 @@ Testing environment - React Native Testing Library - +

Testing environment

diff --git a/12.x/docs/advanced/understanding-act.html b/12.x/docs/advanced/understanding-act.html index 44e1fcbc..bbc9c741 100644 --- a/12.x/docs/advanced/understanding-act.html +++ b/12.x/docs/advanced/understanding-act.html @@ -6,7 +6,7 @@ Understanding `act` function - React Native Testing Library - +

Understanding act function

diff --git a/12.x/docs/api.html b/12.x/docs/api.html index 82d6b50b..356f4fa9 100644 --- a/12.x/docs/api.html +++ b/12.x/docs/api.html @@ -6,7 +6,7 @@ API Overview - React Native Testing Library - +

API Overview

diff --git a/12.x/docs/api/events/fire-event.html b/12.x/docs/api/events/fire-event.html index dceec5ae..dd82436e 100644 --- a/12.x/docs/api/events/fire-event.html +++ b/12.x/docs/api/events/fire-event.html @@ -6,7 +6,7 @@ Fire Event API - React Native Testing Library - +

Fire Event API

diff --git a/12.x/docs/api/events/user-event.html b/12.x/docs/api/events/user-event.html index 4ff0d638..975f2497 100644 --- a/12.x/docs/api/events/user-event.html +++ b/12.x/docs/api/events/user-event.html @@ -6,7 +6,7 @@ User Event interactions - React Native Testing Library - +

User Event interactions

diff --git a/12.x/docs/api/jest-matchers.html b/12.x/docs/api/jest-matchers.html index 8d7f36bb..289bf5d7 100644 --- a/12.x/docs/api/jest-matchers.html +++ b/12.x/docs/api/jest-matchers.html @@ -6,7 +6,7 @@ Jest matchers - React Native Testing Library - +

Jest matchers

diff --git a/12.x/docs/api/misc/accessibility.html b/12.x/docs/api/misc/accessibility.html index 7a8106a9..0816777c 100644 --- a/12.x/docs/api/misc/accessibility.html +++ b/12.x/docs/api/misc/accessibility.html @@ -6,7 +6,7 @@ Accessibility - React Native Testing Library - +

Accessibility

diff --git a/12.x/docs/api/misc/async.html b/12.x/docs/api/misc/async.html index b917ff07..433ef589 100644 --- a/12.x/docs/api/misc/async.html +++ b/12.x/docs/api/misc/async.html @@ -6,7 +6,7 @@ Async utilities - React Native Testing Library - +

Async utilities

diff --git a/12.x/docs/api/misc/config.html b/12.x/docs/api/misc/config.html index 4e9d5551..7f04aaac 100644 --- a/12.x/docs/api/misc/config.html +++ b/12.x/docs/api/misc/config.html @@ -6,7 +6,7 @@ Configuration - React Native Testing Library - +

Configuration

diff --git a/12.x/docs/api/misc/other.html b/12.x/docs/api/misc/other.html index a949661e..405ad407 100644 --- a/12.x/docs/api/misc/other.html +++ b/12.x/docs/api/misc/other.html @@ -6,7 +6,7 @@ Other helpers - React Native Testing Library - +

Other helpers

diff --git a/12.x/docs/api/misc/render-hook.html b/12.x/docs/api/misc/render-hook.html index fccde241..ab912e7c 100644 --- a/12.x/docs/api/misc/render-hook.html +++ b/12.x/docs/api/misc/render-hook.html @@ -6,7 +6,7 @@ `renderHook` function - React Native Testing Library - +

renderHook function

diff --git a/12.x/docs/api/queries.html b/12.x/docs/api/queries.html index 3001b025..11db89ff 100644 --- a/12.x/docs/api/queries.html +++ b/12.x/docs/api/queries.html @@ -6,7 +6,7 @@ Queries - React Native Testing Library - +

Queries

diff --git a/12.x/docs/api/render.html b/12.x/docs/api/render.html index 79c6ec73..6ff98c51 100644 --- a/12.x/docs/api/render.html +++ b/12.x/docs/api/render.html @@ -6,7 +6,7 @@ `render` function - React Native Testing Library - +

render function

diff --git a/12.x/docs/api/screen.html b/12.x/docs/api/screen.html index 41372407..9a5be764 100644 --- a/12.x/docs/api/screen.html +++ b/12.x/docs/api/screen.html @@ -6,7 +6,7 @@ `screen` object - React Native Testing Library - +

screen object

diff --git a/12.x/docs/guides/community-resources.html b/12.x/docs/guides/community-resources.html index 2ebbac4d..73774014 100644 --- a/12.x/docs/guides/community-resources.html +++ b/12.x/docs/guides/community-resources.html @@ -6,7 +6,7 @@ Community resources - React Native Testing Library - +

Community resources

diff --git a/12.x/docs/guides/faq.html b/12.x/docs/guides/faq.html index ec67ea4d..24d11642 100644 --- a/12.x/docs/guides/faq.html +++ b/12.x/docs/guides/faq.html @@ -6,7 +6,7 @@ FAQ - React Native Testing Library - +

FAQ

diff --git a/12.x/docs/guides/how-to-query.html b/12.x/docs/guides/how-to-query.html index c5bb6b68..c577fe97 100644 --- a/12.x/docs/guides/how-to-query.html +++ b/12.x/docs/guides/how-to-query.html @@ -6,7 +6,7 @@ How should I query? - React Native Testing Library - +

How should I query?

diff --git a/12.x/docs/guides/troubleshooting.html b/12.x/docs/guides/troubleshooting.html index 5a48d5f9..1b4dcc55 100644 --- a/12.x/docs/guides/troubleshooting.html +++ b/12.x/docs/guides/troubleshooting.html @@ -6,7 +6,7 @@ Troubleshooting - React Native Testing Library - +

Troubleshooting

diff --git a/12.x/docs/migration/jest-matchers.html b/12.x/docs/migration/jest-matchers.html index 777f3713..51d2c8fd 100644 --- a/12.x/docs/migration/jest-matchers.html +++ b/12.x/docs/migration/jest-matchers.html @@ -6,7 +6,7 @@ Migration to built-in Jest matchers - React Native Testing Library - +

Migration to built-in Jest matchers

diff --git a/12.x/docs/migration/previous/v11.html b/12.x/docs/migration/previous/v11.html index 9d2f7b41..83137d8d 100644 --- a/12.x/docs/migration/previous/v11.html +++ b/12.x/docs/migration/previous/v11.html @@ -6,7 +6,7 @@ Migration to 11.x - React Native Testing Library - +

Migration to 11.x

diff --git a/12.x/docs/migration/previous/v2.html b/12.x/docs/migration/previous/v2.html index 4041d6c4..b6df7215 100644 --- a/12.x/docs/migration/previous/v2.html +++ b/12.x/docs/migration/previous/v2.html @@ -6,7 +6,7 @@ Migration to 2.x - React Native Testing Library - +

Migration to 2.x

diff --git a/12.x/docs/migration/previous/v7.html b/12.x/docs/migration/previous/v7.html index 31a2bfd5..b0d53ef8 100644 --- a/12.x/docs/migration/previous/v7.html +++ b/12.x/docs/migration/previous/v7.html @@ -6,7 +6,7 @@ Migration to 7.x - React Native Testing Library - +

Migration to 7.x

diff --git a/12.x/docs/migration/previous/v9.html b/12.x/docs/migration/previous/v9.html index 84f7ca92..e71e78d3 100644 --- a/12.x/docs/migration/previous/v9.html +++ b/12.x/docs/migration/previous/v9.html @@ -6,7 +6,7 @@ Migration to 9.x - React Native Testing Library - +

Migration to 9.x

diff --git a/12.x/docs/migration/v12.html b/12.x/docs/migration/v12.html index 866b0375..2f08d384 100644 --- a/12.x/docs/migration/v12.html +++ b/12.x/docs/migration/v12.html @@ -6,7 +6,7 @@ Migration to 12.x - React Native Testing Library - +

Migration to 12.x

diff --git a/12.x/docs/start/intro.html b/12.x/docs/start/intro.html index 0587d7bf..abdc6ebd 100644 --- a/12.x/docs/start/intro.html +++ b/12.x/docs/start/intro.html @@ -6,7 +6,7 @@ Introduction - React Native Testing Library - +

Introduction

diff --git a/12.x/docs/start/quick-start.html b/12.x/docs/start/quick-start.html index edb529c3..cf00cebe 100644 --- a/12.x/docs/start/quick-start.html +++ b/12.x/docs/start/quick-start.html @@ -6,7 +6,7 @@ Quick Start - React Native Testing Library - +

Quick Start

diff --git a/12.x/index.html b/12.x/index.html index 2e968c46..43c64853 100644 --- a/12.x/index.html +++ b/12.x/index.html @@ -6,7 +6,7 @@ React Native Testing Library - +

React Native

Testing Library

Helps you to write better tests with less effort.

✨

Maintainable

Write maintainable tests for your React Native apps.

βœ…

Reliable

Promotes testing public APIs and avoiding implementation details.

❀️

Community Driven

Supported by React Native community and its core contributors.

Copyright Β© 2026 Callstack Open Source
diff --git a/14.x/cookbook/advanced/network-requests.html b/14.x/cookbook/advanced/network-requests.html index 861b5701..21e631bd 100644 --- a/14.x/cookbook/advanced/network-requests.html +++ b/14.x/cookbook/advanced/network-requests.html @@ -6,10 +6,10 @@ Network Requests - React Native Testing Library - + -

Network Requests

+

Network Requests

Introduction

Mocking network requests is an essential part of testing React Native applications. By mocking network @@ -221,7 +221,7 @@ Please be minded that the MSW's setup guide is potentially incomplete and m describe('PhoneBook', () => { it('fetches all contacts and favorites successfully and renders lists in sections correctly', async () => { - render(<PhoneBook />); + await render(<PhoneBook />); await waitForElementToBeRemoved(() => screen.getByText(/users data not quite there yet/i)); expect(await screen.findByText('Name: Mrs Ida Kristensen')).toBeOnTheScreen(); @@ -290,7 +290,7 @@ More info can be found in ... it('fails to fetch all contacts and renders error message', async () => { mockServerFailureForGetAllContacts(); - render(<PhoneBook />); + await render(<PhoneBook />); await waitForElementToBeRemoved(() => screen.getByText(/users data not quite there yet/i)); expect( diff --git a/14.x/cookbook/basics/async-tests.html b/14.x/cookbook/basics/async-events.html similarity index 76% rename from 14.x/cookbook/basics/async-tests.html rename to 14.x/cookbook/basics/async-events.html index f3f6a36d..687ee657 100644 --- a/14.x/cookbook/basics/async-tests.html +++ b/14.x/cookbook/basics/async-events.html @@ -5,20 +5,21 @@ - Async tests - React Native Testing Library - + Async Events - React Native Testing Library + -

Async tests

+

Async Events

Summary

-

Typically, you would write synchronous tests, as they are simple and get the work done. However, there are cases when using asynchronous (async) tests might be necessary or beneficial. The two most common cases are:

+

In RNTL v14, all tests are async since render(), fireEvent(), and other core APIs return Promises. Beyond the basic async APIs, there are additional async utilities for handling events that complete over time:

    -
  1. Testing Code with asynchronous operations: When your code relies on asynchronous operations, such as network calls or database queries, async tests are essential. Even though you should mock these network calls, the mock should act similarly to the actual behavior and hence by async.
  2. -
  3. UserEvent API: Using the User Event API in your tests creates more realistic event handling. These interactions introduce delays (even though these are typically event-loop ticks with 0 ms delays), requiring async tests to handle the timing correctly.
  4. +
  5. Waiting for elements to appear: Use findBy* queries when elements appear after some delay (e.g., after data fetching).
  6. +
  7. Waiting for conditions: Use waitFor() to wait for arbitrary conditions to be met.
  8. +
  9. Waiting for elements to disappear: Use waitForElementToBeRemoved() when elements should be removed after some action.
-

Using async tests whenΒ needed ensures your testsΒ areΒ reliable andΒ simulateΒ real-world conditionsΒ accurately.

+

These utilities help you write reliable tests that properly handle timing in your application.

Example

-

Consider a basic asynchronous test for a user signing in with correct credentials:

+

Consider a test for a user signing in with correct credentials:

test('User can sign in with correct credentials', async () => {
   // Typical test setup
   const user = userEvent.setup();
diff --git a/14.x/cookbook/basics/custom-render.html b/14.x/cookbook/basics/custom-render.html
index aecdb4d1..3c36a4ce 100644
--- a/14.x/cookbook/basics/custom-render.html
+++ b/14.x/cookbook/basics/custom-render.html
@@ -6,10 +6,10 @@
     
     
     Custom `render` function - React Native Testing Library
-  
+  
 
   
-    

Custom render function

+

Custom render function

Summary

RNTL exposes the render function as the primary entry point for tests. If you make complex, repeating setups for your tests, consider creating a custom render function. The idea is to encapsulate common setup steps and test wiring inside a render function suitable for your tests.

Example

@@ -47,20 +47,25 @@

More info

Additional params

A custom render function might accept additional parameters to allow for setting up different start conditions for a test, e.g., the initial state for global state management.

-
SomeScreen.test.tsx
test('renders SomeScreen for logged in user', () => {
-  renderScreen(<SomeScreen />, { state: loggedInState });
+
SomeScreen.test.tsx
test('renders SomeScreen for logged in user', async () => {
+  await renderScreen(<SomeScreen />, { state: loggedInState });
   // ...
 });

Multiple functions

Depending on the situation, you may declare more than one custom render function. For example, you have one function for testing application flows and a second for testing individual screens.

test-utils.tsx
function renderNavigator(ui, options);
 function renderScreen(ui, options);
-

Async function

-

Make it async if you want to put some async setup in your custom render function.

-
SomeScreen.test.tsx
test('renders SomeScreen', async () => {
-  await renderWithAsync(<SomeScreen />);
+

Async setup

+

Since render is async, your custom render function should be marked as async and use await render(). This pattern also makes it easy to add additional async setup if needed:

+
SomeScreen.test.tsx
async function renderWithData<T>(ui: React.ReactElement<T>) {
+  const data = await fetchTestData();
+  return await render(<DataProvider value={data}>{ui}</DataProvider>);
+}
+
+test('renders SomeScreen', async () => {
+  await renderWithData(<SomeScreen />);
   // ...
-});
+});
diff --git a/14.x/cookbook/index.html b/14.x/cookbook/index.html index 14463f16..5ec876d5 100644 --- a/14.x/cookbook/index.html +++ b/14.x/cookbook/index.html @@ -6,10 +6,10 @@ Introduction - React Native Testing Library - + -

Introduction

+

Introduction

Welcome to the React Native Testing Library (RNTL) Cookbook! This app is your go-to resource for learning how to effectively test React Native applications. It provides a collection of best practices, ready-made recipes, and tips & tricks to @@ -32,7 +32,7 @@ recipes in action.

What's Next?

Join the conversation on GitHub here to discuss -ideas, ask questions, or provide feedback.

+ideas, ask questions, or provide feedback.

diff --git a/14.x/cookbook/state-management/jotai.html b/14.x/cookbook/state-management/jotai.html index 6534c650..22e9db36 100644 --- a/14.x/cookbook/state-management/jotai.html +++ b/14.x/cookbook/state-management/jotai.html @@ -6,10 +6,10 @@ Jotai - React Native Testing Library - + -

Jotai

+

Jotai

Introduction

Jotai is a global state management library for React that uses an atomic approach to optimize renders and solve issues like extra re-renders and the need for memoization. It scales from simple @@ -66,17 +66,17 @@ component has a list of tasks, a text input for typing new task name and a butto

We can test our TaskList component using React Native Testing Library's (RNTL) regular render function. Although it is sufficient to test the empty state of the TaskList component, it is not enough to test the component with initial tasks present in the list.

-
status-management/jotai/__tests__/TaskList.test.tsx
import * as React from 'react';
+
state-management/jotai/__tests__/TaskList.test.tsx
import * as React from 'react';
 import { render, screen, userEvent } from '@testing-library/react-native';
 import { renderWithAtoms } from './test-utils';
-import { TaskList } from './TaskList';
-import { newTaskTitleAtom, tasksAtom } from './state';
-import { Task } from './types';
+import { TaskList } from '../TaskList';
+import { newTaskTitleAtom, tasksAtom } from '../state';
+import { Task } from '../types';
 
 jest.useFakeTimers();
 
-test('renders an empty task list', () => {
-  render(<TaskList />);
+test('renders an empty task list', async () => {
+  await render(<TaskList />);
   expect(screen.getByText(/no tasks, start by adding one/i)).toBeOnTheScreen();
 });

Custom Render Function to populate Jotai Atoms with Initial Values

@@ -84,7 +84,7 @@ enough to test the component with initial tasks present in the list.

initial values. We can create a custom render function that uses Jotai's useHydrateAtoms hook to hydrate the atoms with initial values. This function will accept the initial atoms and their corresponding values as an argument.

-
status-management/jotai/test-utils.tsx
import * as React from 'react';
+
state-management/jotai/__tests__/test-utils.tsx
import * as React from 'react';
 import { render } from '@testing-library/react-native';
 import { useHydrateAtoms } from 'jotai/utils';
 import { PrimitiveAtom } from 'jotai/vanilla/atom';
@@ -103,14 +103,14 @@ corresponding values as an argument.

* @param options - The render options including the initial atom values. * @returns The render result from `@testing-library/react-native`. */ -export const renderWithAtoms = <T,>( +export async function renderWithAtoms<T>( component: React.ReactElement, options: RenderWithAtomsOptions -) => { - return render( +) { + return await render( <HydrateAtomsWrapper initialValues={options.initialValues}>{component}</HydrateAtomsWrapper> ); -}; +} export type HydrateAtomsWrapperProps = React.PropsWithChildren<{ initialValues: AtomInitialValueTuple<unknown>[]; @@ -132,11 +132,10 @@ corresponding values as an argument.

We can now use the renderWithAtoms function to render the TaskList component with initial tasks. The initialValues property will contain the tasksAtom, newTaskTitleAtom and their initial values. We can then test the component to ensure that the initial tasks are rendered correctly.

INFO

In our test, we populated only one atom and its initial value, but you can add other Jotai atoms and their corresponding values to the initialValues array as needed.

-
status-management/jotai/__tests__/TaskList.test.tsx
=======
-const INITIAL_TASKS: Task[] = [{ id: '1', title: 'Buy bread' }];
+
state-management/jotai/__tests__/TaskList.test.tsx
const INITIAL_TASKS: Task[] = [{ id: '1', title: 'Buy bread' }];
 
 test('renders a to do list with 1 items initially, and adds a new item', async () => {
-  renderWithAtoms(<TaskList />, {
+  await renderWithAtoms(<TaskList />, {
     initialValues: [
       [tasksAtom, INITIAL_TASKS],
       [newTaskTitleAtom, ''],
@@ -179,7 +178,7 @@ we have a set of functions to get tasks and set tasks, which change the state of
 the initial to-do items in the store and then checking if the functions work as expected.
 No special setup is required to test these functions, as store.set is available by default by
 Jotai.

-
state-management/jotai/__tests__/TaskList.test.tsx
import { addTask, getAllTasks, store, tasksAtom } from './state';
+
state-management/jotai/__tests__/TaskList.test.tsx
import { addTask, getAllTasks, store, tasksAtom } from '../state';
 
 //...
 
diff --git a/14.x/docs/advanced/testing-env.html b/14.x/docs/advanced/testing-env.html
index 792c0dff..3aec1ac3 100644
--- a/14.x/docs/advanced/testing-env.html
+++ b/14.x/docs/advanced/testing-env.html
@@ -6,10 +6,10 @@
     
     
     Testing environment - React Native Testing Library
-  
+  
 
   
-    

Testing environment

+

Testing environment

INFO

This document is intended for a more advanced audience who want to understand the internals of our testing environment better, e.g., to contribute to the codebase. You should be able to write integration or component tests without reading this.

@@ -40,7 +40,7 @@

It's worth noting that the React Testing Library (web one) works a bit differently. While RTL also runs in Jest, it has access to a simulated browser DOM environment from the jsdom package, which allows it to use a regular React DOM renderer. Unfortunately, there is no similar React Native runtime environment package. This is probably because while the browser environment is well-defined and highly standardized, the React Native environment constantly evolves in sync with the evolution of underlying OS-es. Maintaining such an environment would require duplicating countless React Native behaviors and keeping them in sync as React Native develops.

Element tree

-

Calling the render() function creates an element tree. This is done internally by invoking the renderer's create() method from Test Renderer. The output tree represents your React Native component tree, and each node of that tree is an "instance" of some React component (to be more precise, each node represents a React fiber, and only class components have instances, while function components store the hook state using fibers).

+

Calling the render() function creates an element tree. This is done internally by invoking the createRoot() function from Test Renderer. The output tree represents your React Native component tree, containing only host elements. Each node of that tree corresponds to a host component that would have a counterpart in the native view hierarchy.

These tree elements are represented by HostElement type from Test Renderer:

interface HostElement {
   type: ElementType;
@@ -52,42 +52,32 @@
 }

For more details, see the Test Renderer documentation.

Host and composite components

-

One of the most important aspects of the element tree is that it is composed of both host and composite components:

+

To understand RNTL's element tree, it's important to know the difference between host and composite components in React Native:

    -
  • Host components will have direct counterparts in the native view tree. Typical examples are <View>, <Text> , <TextInput>, and <Image> from React Native. You can think of these as an analog of <div>, <span> etc on the Web. You can also create custom host views as native modules or import them from 3rd party libraries, like React Navigation or React Native Gesture Handler.
  • +
  • Host components have direct counterparts in the native view tree. Typical examples are <View>, <Text>, <TextInput>, and <Image> from React Native. You can think of these as an analog of <div>, <span> etc on the Web. You can also create custom host views as native modules or import them from 3rd party libraries, like React Navigation or React Native Gesture Handler.
  • Composite components are React code organization units that exist only on the JavaScript side of your app. Typical examples are components you create (function and class components), components imported from React Native (View, Text, etc.), or 3rd party packages.

That might initially sound confusing since we put React Native's View in both categories. There are two View components: composite and host. The relation between them is as follows:

    -
  • composite View is the type imported from the react-native package. It is a JavaScript component that renders the host View as its only child in the element tree.
  • -
  • host View, which you do not render directly. React Native takes the props you pass to the composite View, does some processing on them and passes them to the host View.
  • +
  • Composite View is the type imported from the react-native package. It is a JavaScript component that renders the host View as its only child.
  • +
  • Host View, which you do not render directly. React Native takes the props you pass to the composite View, does some processing on them and passes them to the host View.
-

The part of the tree looks as follows:

+

In a full React tree, this would look like:

* <View> (composite)
   * <View> (host)
     * children prop passed in JSX
-

A similar relation exists between other composite and host pairs: e.g. Text , TextInput, and Image components:

-
* <Text> (composite)
-  * <Text> (host)
-    * string (or mixed) content
+

A similar relation exists between other composite and host pairs: e.g. Text, TextInput, and Image components.

Not all React Native components are organized this way, e.g., when you use Pressable (or TouchableOpacity), there is no host Pressable, but composite Pressable is rendering a host View with specific props being set:

* <Pressable> (composite)
   * <View accessible={true} {...}> (host)
     * children prop passed in JSX
-

Differentiating between host and composite elements

-

Any easy way to differentiate between host and composite elements is the type prop of HostElement:

-
    -
  • for host components, it's always a string value representing a component name, e.g., "View"
  • -
  • for composite components, it's a function or class corresponding to the component
  • -
-

You can use the following code to check if a given element is a host one:

-
function isHostElement(element: HostElement) {
-  return typeof element.type === 'string';
-}
+

Host-only element tree

+

In RNTL v14, Test Renderer only exposes host elements in the element tree. Composite components are not visible in the tree - you only see their host element output. This is an intentional design choice that aligns with Testing Library's philosophy: tests should focus on what users can see and interact with (host elements), not on implementation details (composite components).

+

For a HostElement, the type prop is always a string value representing the host component name, e.g., "View", "Text", "TextInput".

Tree nodes

-

We encourage you to only assert values on host views in your tests because they represent the user interface view and controls which the user can see and interact with. Users cannot see or interact with composite views as they exist purely in the JavaScript domain and do not generate any visible UI.

-

Asserting props

-

For example, suppose you assert a style prop of a composite element. In that case, there is no guarantee that the style will be visible to the user, as the component author can forget to pass this prop to some underlying View or other host component. Similarly onPress event handler on a composite prop can be unreachable by the user.

+

RNTL v14 queries and the element tree only expose host elements. This aligns with Testing Library's philosophy: tests should assert on what users can see and interact with. Host elements represent the actual UI controls that users interact with, while composite components exist purely in the JavaScript domain.

+

Understanding props

+

When asserting props on host elements, you're verifying what actually reaches the native view. This is important because composite components may process, transform, or even forget to pass props to their host children.

function ForgotToPassPropsButton({ title, onPress, style }) {
   return (
     <Pressable>
@@ -95,14 +85,12 @@
     </Pressable>
   );
 }
-

In the above example, user-defined components accept both onPress and style props but do not pass them (through Pressable) to host views, so they will not affect the user interface. Additionally, React Native and other libraries might pass some of the props under different names or transform their values between composite and host components.

+

In the above example, the component accepts onPress and style props but doesn't pass them to host views, so they won't affect the user interface. By testing host elements, RNTL helps you catch these issues: if a prop doesn't reach a host element, users won't see or interact with it.

Tree navigation

CAUTION

You should avoid navigating over the element tree, as this makes your testing code fragile and may result in false positives. This section is more relevant for people who want to contribute to our codebase.

-

You will encounter host and composite elements when navigating a tree of react elements using parent or children props of a HostElement element. You should be careful when navigating the element tree, as the tree structure for third-party components can change independently from your code and cause unexpected test failures.

-

Inside RNTL, we have various tree navigation helpers: getHostParent, getHostChildren, etc. These are intentionally not exported, as using them is not recommended.

+

You can navigate the tree of host elements using parent or children props of a HostElement. Be careful when doing this, as the tree structure for third-party components can change independently from your code and cause unexpected test failures.

Queries

-

All recommended Testing Library queries return host components to encourage the best practices described above.

-

Only UNSAFE_*ByType and UNSAFE_*ByProps queries can return both host and composite components depending on used predicates. They are marked as unsafe precisely because testing composite components makes your test more fragile.

+

All Testing Library queries return host components to encourage the best practices described above. Since v14, RNTL uses Test Renderer, which only renders host elements, making it impossible to query composite components directly.

diff --git a/14.x/docs/advanced/third-party-integration.html b/14.x/docs/advanced/third-party-integration.html index 9a59231e..79e00308 100644 --- a/14.x/docs/advanced/third-party-integration.html +++ b/14.x/docs/advanced/third-party-integration.html @@ -6,10 +6,10 @@ Third-Party Library Integration - React Native Testing Library - + -

Third-Party Library Integration

+

Third-Party Library Integration

The React Native Testing Library is designed to simulate the core behaviors of React Native. However, it does not replicate the internal logic of third-party libraries. This guide explains how to integrate your library with RNTL.

Handling Events in Third-Party Libraries

RNTL provides two subsystems to simulate events:

diff --git a/14.x/docs/advanced/understanding-act.html b/14.x/docs/advanced/understanding-act.html index 5fdfb78c..9b238297 100644 --- a/14.x/docs/advanced/understanding-act.html +++ b/14.x/docs/advanced/understanding-act.html @@ -6,14 +6,14 @@ Understanding `act` function - React Native Testing Library - + -

Understanding act function

-

When writing RNTL tests one of the things that confuses developers the most are cryptic act() function errors logged into console. In this article I will try to build an understanding of the purpose and behaviour of act() so you can build your tests with more confidence.

-

act warnings

-

Let’s start with typical act() warnings logged to console. There are two kinds of these issues, let’s call the first one the "sync act()" warning:

-
Warning: An update to Component inside a test was not wrapped in act(...). +

Understanding act function

+

When writing RNTL tests one of the things that confuses developers the most are cryptic act() function errors logged into console. In this article I will try to build an understanding of the purpose and behaviour of act() so you can build your tests with more confidence.

+

act warning

+

Let's start with a typical act() warning logged to console:

+
An update to Root inside a test was not wrapped in act(...). When testing, code that causes React state updates should be wrapped into act(...): @@ -21,13 +21,11 @@ act(() => { /* fire events that update state */ }); /* assert on the output */ + +This ensures that you're testing the behavior the user would see in the browser. +Learn more at https://react.dev/link/wrap-tests-with-act
-

The second one relates to async usage of act so let’s call it the "async act" error:

-
Warning: You called act(async () => ...) without await. This could lead to unexpected -testing behaviour, interleaving multiple act calls and mixing their scopes. You should -- await act(async () => ...); -
-

Synchronous act

+

Understanding act

Responsibility

This function is intended only for using in automated tests and works only in development mode. Attempting to use it in production build will throw an error.

The responsibility for act function is to make React renders and updates work in tests in a similar way they work in real application by grouping and executing related units of interaction (e.g. renders, effects, etc) together.

@@ -40,45 +38,53 @@ testing behaviour, interleaving multiple act calls and mixing their scopes. You return <Text>Count {count}</Text>; }
-

In the following tests we will directly use ReactTestRenderer instead of RNTL render function to render our component for tests. In order to expose familiar queries like getByText we will use within function from RNTL.

-
test('render without act', () => {
-  const renderer = TestRenderer.create(<TestComponent />);
+

In the following tests we will directly use Test Renderer instead of RNTL render function to render our component for tests. In order to expose familiar queries like getByText we will use within function from RNTL.

+
import { createRoot } from 'test-renderer';
+import { within } from '@testing-library/react-native';
+
+test('render without act', () => {
+  const renderer = createRoot();
+  renderer.render(<TestComponent />);
 
   // Bind RNTL queries for root element.
-  const view = within(renderer.root);
-  expect(view.getByText('Count 0')).toBeOnTheScreen();
+  const view = within(renderer.container);
+  expect(view.getByText('Count 0')).toBeTruthy();
 });
-

When testing without act call wrapping rendering call, we see that the assertion runs just after the rendering but before useEffecthooks effects are applied. Which is not what we expected in our tests.

-
test('render with act', async () => {
-  let renderer: ReactTestRenderer;
-  await act(async () => {
-    renderer = TestRenderer.create(<TestComponent />);
+

When testing without act call wrapping rendering call, we see that the assertion runs just after the rendering but before useEffect hooks effects are applied. Which is not what we expected in our tests.

+
import { createRoot } from 'test-renderer';
+import { act, within } from '@testing-library/react-native';
+
+test('render with act', async () => {
+  const renderer = createRoot();
+  await act(() => {
+    renderer.render(<TestComponent />);
   });
 
   // Bind RNTL queries for root element.
-  const view = within(renderer!.root);
-  expect(view.getByText('Count 1')).toBeOnTheScreen();
+  const view = within(renderer.container);
+  expect(view.getByText('Count 1')).toBeTruthy();
 });
-

Note: In v14, act is now async by default and always returns a Promise. Even if your callback is synchronous, you should use await act(async () => ...).

+

Note: In v14, act is now async by default and always returns a Promise. You should always use await act(...).

When wrapping rendering call with act we see that the changes caused by useEffect hook have been applied as we would expect.

When to use act

-

The name act comes from Arrange-Act-Assert unit testing pattern. Which means it’s related to part of the test when we execute some actions on the component tree.

+

The name act comes from Arrange-Act-Assert unit testing pattern. Which means it's related to part of the test when we execute some actions on the component tree.

So far we learned that act function allows tests to wait for all pending React interactions to be applied before we make our assertions. When using act we get guarantee that any state updates will be executed as well as any enqueued effects will be executed.

Therefore, we should use act whenever there is some action that causes element tree to render, particularly:

    -
  • initial render call - ReactTestRenderer.create call
  • -
  • re-rendering of component -renderer.rerender call
  • +
  • initial render call - renderer.render call
  • +
  • re-rendering of component - renderer.render call with updated element
  • triggering any event handlers that cause component tree render
-

Thankfully, for these basic cases RNTL has got you covered as our render, rerender and fireEvent methods already wrap their calls in act so that you do not have to do it explicitly.

-

Note that act calls can be safely nested and internally form a stack of calls. However, overlapping act calls, which can be achieved using async version of act, are not supported.

+

Thankfully, for these basic cases RNTL has got you covered as our render, rerender and fireEvent methods already wrap their calls in act so that you do not have to do it explicitly. In v14, these functions are all async and should be awaited.

+

Note that act calls can be safely nested and internally form a stack of calls.

Implementation

-

As of React version of 18.1.0, the act implementation is defined in the ReactAct.js source file inside React repository. This implementation has been fairly stable since React 17.0.

-

RNTL exports act for convenience of the users as defined in the act.ts source file. In v14, act is now async by default and always returns a Promise, making it compatible with React 19, React Suspense, and React.use(). The underlying implementation still uses React's act function, but wraps it to ensure consistent async behavior.

-

Asynchronous act

-

So far we have seen synchronous version of act which runs its callback immediately. This can deal with things like synchronous effects or mocks using already resolved promises. However, not all component code is synchronous. Frequently our components or mocks contain some asynchronous behaviours like setTimeout calls or network calls. Starting from React 16.9, act can also be called in asynchronous mode. In such case act implementation checks that the passed callback returns object resembling promise.

-

Asynchronous code

-

Asynchronous version of act also is executed immediately, but the callback is not yet completed because of some asynchronous operations inside.

+

The act implementation is defined in the ReactAct.js source file inside React repository. RNTL v14 requires React 19+, which provides the act function directly via React.act.

+

RNTL exports act for convenience of the users as defined in the act.ts source file. In v14, act is now async by default and always returns a Promise, making it compatible with async React features like Suspense boundary or use() hook. The underlying implementation wraps React's act function to ensure consistent async behavior.

+

Important: You should always use act exported from @testing-library/react-native rather than the one from react. The RNTL version automatically ensures async behavior, whereas using React.act directly could still trigger synchronous act behavior if used improperly, leading to subtle test issues.

+

Asynchronous code

+

In v14, act is always async and returns a Promise. While the callback you pass to act can be synchronous (dealing with things like synchronous effects or mocks using already resolved promises), the act function itself should always be awaited. However, not all component code is synchronous. Frequently our components or mocks contain some asynchronous behaviours like setTimeout calls or network calls.

+

Handling asynchronous operations

+

When the callback passed to act contains asynchronous operations, the Promise returned by act will resolve only after those operations complete.

Lets look at a simple example with component using setTimeout call to simulate asynchronous behaviour:

function TestAsyncComponent() {
   const [count, setCount] = React.useState(0);
@@ -92,48 +98,38 @@ testing behaviour, interleaving multiple act calls and mixing their scopes. You
 }
import { render, screen } from '@testing-library/react-native';
 
-test('render async natively', () => {
-  render(<TestAsyncComponent />);
+test('render async natively', async () => {
+  await render(<TestAsyncComponent />);
   expect(screen.getByText('Count 0')).toBeOnTheScreen();
 });
-

If we test our component in a native way without handling its asynchronous behaviour we will end up with sync act warning:

-
Warning: An update to TestAsyncComponent inside a test was not wrapped in act(...). - -When testing, code that causes React state updates should be wrapped into act(...): - -act(() => { - /* fire events that update state */ -}); -/* assert on the output */ -
-

Note that this is not yet the infamous async act warning. It only asks us to wrap our event code with act calls. However, this time our immediate state change does not originate from externally triggered events but rather forms an internal part of the component. So how can we apply act in such scenario?

+

If we test our component in a native way without handling its asynchronous behaviour we will end up with an act warning. This is because the setTimeout callback will trigger a state update after the test has finished.

Solution with fake timers

First solution is to use Jest's fake timers inside out tests:

test('render with fake timers', async () => {
   jest.useFakeTimers();
-  render(<TestAsyncComponent />);
+  await render(<TestAsyncComponent />);
 
-  await act(async () => {
+  await act(() => {
     jest.runAllTimers();
   });
   expect(screen.getByText('Count 1')).toBeOnTheScreen();
 });
-

Note: In v14, act is now async by default, so you should await it even when using fake timers.

-

That way we can wrap jest.runAllTimers() call which triggers the setTimeout updates inside an act call, hence resolving the act warning. Note that this whole code is synchronous thanks to usage of Jest fake timers.

+

Note: In v14, both render and act are async by default, so you should await them.

+

That way we can wrap jest.runAllTimers() call which triggers the setTimeout updates inside an act call, hence resolving the act warning.

Solution with real timers

-

If we wanted to stick with real timers then things get a bit more complex. Let’s start by applying a crude solution of opening async act() call for the expected duration of components updates:

+

If we wanted to stick with real timers then things get a bit more complex. Let's start by applying a crude solution of opening async act() call for the expected duration of components updates:

test('render with real timers - sleep', async () => {
-  render(<TestAsyncComponent />);
-  await act(async () => {
+  await render(<TestAsyncComponent />);
+  await act(() => {
     await sleep(100); // Wait a bit longer than setTimeout in `TestAsyncComponent`
   });
 
   expect(screen.getByText('Count 1')).toBeOnTheScreen();
 });

This works correctly as we use an explicit async act() call that resolves the console error. However, it relies on our knowledge of exact implementation details which is a bad practice.

-

Let’s try more elegant solution using waitFor that will wait for our desired state:

+

Let's try more elegant solution using waitFor that will wait for our desired state:

test('render with real timers - waitFor', async () => {
-  render(<TestAsyncComponent />);
+  await render(<TestAsyncComponent />);
 
   await waitFor(() => screen.getByText('Count 1'));
   expect(screen.getByText('Count 1')).toBeOnTheScreen();
@@ -141,24 +137,17 @@ act(() => {
 

This also works correctly, because waitFor call executes async act() call internally.

The above code can be simplified using findBy query:

test('render with real timers - findBy', async () => {
-  render(<TestAsyncComponent />);
+  await render(<TestAsyncComponent />);
 
   expect(await screen.findByText('Count 1')).toBeOnTheScreen();
 });

This also works since findByText internally calls waitFor which uses async act().

Note that all of the above examples are async tests using & awaiting async act() function call.

-

Async act warning

-

If we modify any of the above async tests and remove await keyword, then we will trigger the notorious async act()warning:

-
Warning: You called act(async () => ...) without await. This could lead to unexpected
-testing behaviour, interleaving multiple act calls and mixing their scopes. You should
-- await act(async () => ...);
-

React decides to show this error whenever it detects that async act()call has not been awaited.

-

The exact reasons why you might see async act() warnings vary, but finally it means that act() has been called with callback that returns Promise-like object, but it has not been waited on.

References

+
  • React testing documentation
  • +
    diff --git a/14.x/docs/api.html b/14.x/docs/api.html index 92a181d4..56e6a51b 100644 --- a/14.x/docs/api.html +++ b/14.x/docs/api.html @@ -6,10 +6,10 @@ API Overview - React Native Testing Library - + -
    diff --git a/14.x/docs/api/events/fire-event.html b/14.x/docs/api/events/fire-event.html index d0303547..0fd83b84 100644 --- a/14.x/docs/api/events/fire-event.html +++ b/14.x/docs/api/events/fire-event.html @@ -6,10 +6,10 @@ Fire Event API - React Native Testing Library - + -

    Fire Event API

    +

    Fire Event API

    fireEvent

    NOTE

    For common events like press or type it's recommended to use User Event API as it offers more realistic event simulation by emitting a sequence of events with proper event objects that mimic React Native runtime behavior.

    @@ -23,7 +23,7 @@ more realistic event simulation by emitting a sequence of events with proper eve test('fire changeText event', async () => { const onEventMock = jest.fn(); - render( + await render( // MyComponent renders TextInput which has a placeholder 'Enter details' // and with `onChangeText` bound to handleChangeText <MyComponent handleChangeText={onEventMock} /> @@ -36,11 +36,11 @@ more realistic event simulation by emitting a sequence of events with proper eve

    An example using fireEvent with native events that aren't already aliased by the fireEvent api.

    import { TextInput, View } from 'react-native';
    -import { fireEvent, render } from '@testing-library/react-native';
    +import { fireEvent, render, screen } from '@testing-library/react-native';
     
     const onBlurMock = jest.fn();
     
    -render(
    +await render(
       <View>
         <TextInput placeholder="my placeholder" onBlur={onBlurMock} />
       </View>
    @@ -68,7 +68,7 @@ more realistic event simulation by emitting a sequence of events with proper eve
       },
     };
     
    -render(
    +await render(
       <View>
         <TouchableOpacity onPress={onPressMock}>
           <Text>Press me</Text>
    @@ -92,7 +92,7 @@ more realistic event simulation by emitting a sequence of events with proper eve
     const onChangeTextMock = jest.fn();
     const CHANGE_TEXT = 'content';
     
    -render(
    +await render(
       <View>
         <TextInput placeholder="Enter data" onChangeText={onChangeTextMock} />
       </View>
    @@ -120,13 +120,13 @@ more realistic event simulation by emitting a sequence of events with proper eve
       },
     };
     
    -render(
    -  <ScrollView onScroll={onScrollMock}>
    -    <Text>XD</Text>
    +await render(
    +  <ScrollView testID="scroll-view" onScroll={onScrollMock}>
    +    <Text>Content</Text>
       </ScrollView>
     );
     
    -await fireEvent.scroll(screen.getByText('scroll-view'), eventData);
    +await fireEvent.scroll(screen.getByTestId('scroll-view'), eventData);
    diff --git a/14.x/docs/api/events/user-event.html b/14.x/docs/api/events/user-event.html index c6831a70..f1b7d3fa 100644 --- a/14.x/docs/api/events/user-event.html +++ b/14.x/docs/api/events/user-event.html @@ -6,18 +6,18 @@ User Event interactions - React Native Testing Library - + -

    User Event interactions

    +

    User Event interactions

    Comparison with Fire Event API

    Fire Event is our original event simulation API. It can invoke any event handler declared on either host or composite elements. Suppose the element does not have onEventName event handler for the passed eventName event, or the element is disabled. In that case, Fire Event will traverse up the component tree, looking for an event handler on both host and composite elements along the way. By default, it will not pass any event data, but the user might provide it in the last argument.

    In contrast, User Event provides realistic event simulation for user interactions like press or type. Each interaction will trigger a sequence of events corresponding to React Native runtime behavior. These events will be invoked only on host elements, and will automatically receive event data corresponding to each event.

    If User Event supports a given interaction, you should always prefer it over the Fire Event counterpart, as it will make your tests much more realistic and, hence, reliable. In other cases, e.g., when User Event does not support the given event or when invoking event handlers on composite elements, you have to use Fire Event as the only available option.

    setup()

    userEvent.setup(options?: {
    -  delay: number;
    -  advanceTimers: (delay: number) => Promise<void> | void;
    +  delay?: number;
    +  advanceTimers?: (delay: number) => Promise<void> | void;
     })

    Example

    const user = userEvent.setup();
    @@ -39,7 +39,7 @@

    longPress()

    longPress(
       element: HostElement,
    -  options: { duration: number } = { duration: 500 }
    +  options?: { duration?: number }
     ): Promise<void>

    Example

    const user = userEvent.setup();
    @@ -58,7 +58,8 @@
         skipPress?: boolean;
         skipBlur?: boolean;
         submitEditing?: boolean;
    -  }
    + } +): Promise<void>

    Example

    const user = userEvent.setup();
     await user.type(textInput, 'Hello world!');
    @@ -101,7 +102,7 @@ The endEditing and blur events can be skipped by passi

    clear()

    clear(
       element: HostElement,
    -)
    +): Promise<void>

    Example

    const user = userEvent.setup();
     await user.clear(textInput);
    @@ -133,7 +134,7 @@ The endEditing and blur events can be skipped by passi
    paste(
       element: HostElement,
       text: string,
    -)
    +): Promise<void>

    Example

    const user = userEvent.setup();
     await user.paste(textInput, 'Text to paste');
    @@ -154,6 +155,7 @@ The endEditing and blur events can be skipped by passi
  • change
  • changeText
  • selectionChange
  • +
  • contentSizeChange (only multiline)
  • Leaving the element:

      @@ -164,16 +166,17 @@ The endEditing and blur events can be skipped by passi
      scrollTo(
         element: HostElement,
         options: {
      -    y: number,
      -    momentumY?: number,
      -    contentSize?: { width: number, height: number },
      -    layoutMeasurement?: { width: number, height: number },
      +    y: number;
      +    momentumY?: number;
      +    contentSize?: { width: number; height: number };
      +    layoutMeasurement?: { width: number; height: number };
         } | {
      -    x: number,
      -    momentumX?: number,
      -    contentSize?: { width: number, height: number },
      -    layoutMeasurement?: { width: number, height: number },
      -  }
      + x: number; + momentumX?: number; + contentSize?: { width: number; height: number }; + layoutMeasurement?: { width: number; height: number }; + } +): Promise<void>

    Example

    const user = userEvent.setup();
     await user.scrollTo(scrollView, { y: 100, momentumY: 200 });
    diff --git a/14.x/docs/api/jest-matchers.html b/14.x/docs/api/jest-matchers.html index 0fbfdf41..8e96df40 100644 --- a/14.x/docs/api/jest-matchers.html +++ b/14.x/docs/api/jest-matchers.html @@ -6,10 +6,10 @@ Jest matchers - React Native Testing Library - + -

    Jest matchers

    +

    Jest matchers

    This guide describes built-in Jest matchers, we recommend using these matchers as they provide readable tests, accessibility support, and a better developer experience.

    Setup

    There is no need to set up the built-in matchers; they are automatically available in your tests when you import anything from @testing-library/react-native, e.g., render.

    @@ -80,12 +80,12 @@

    toBeExpanded() / toBeCollapsed()

    expect(element).toBeExpanded();
     expect(element).toBeCollapsed();
    -

    These allows you to assert whether the given element is expanded or collapsed from the user's perspective. It relies on the accessibility disabled state as set by aria-expanded or accessibilityState.expanded props.

    +

    These allow you to assert whether the given element is expanded or collapsed from the user's perspective. It relies on the accessibility expanded state as set by aria-expanded or accessibilityState.expanded props.

    NOTE

    These matchers are the negation of each other for expandable elements (elements with explicit aria-expanded or accessibilityState.expanded props). However, both won't pass for non-expandable elements (ones without explicit aria-expanded or accessibilityState.expanded props).

    toBeBusy()

    expect(element).toBeBusy();
    -

    This allows you to assert whether the given element is busy from the user's perspective. It relies on the accessibility selected state as set by aria-busy or accessibilityState.busy props.

    +

    This allows you to assert whether the given element is busy from the user's perspective. It relies on the accessibility busy state as set by aria-busy or accessibilityState.busy props.

    Checking element style

    toBeVisible()

    expect(element).toBeVisible();
    @@ -106,7 +106,7 @@ }, )

    This allows you to assert whether the given element has a specified accessible name. It accepts either string or RegExp matchers, as well as text match options of exact and normalizer.

    -

    The accessible name will be computed based on aria-labelledby, accessibilityLabelledBy, aria-label, and accessibilityLabel props, in the absence of these props, the element text content will be used.

    +

    The accessible name will be computed based on aria-labelledby, accessibilityLabelledBy, aria-label, and accessibilityLabel props. For Image elements, the alt prop will also be considered. In the absence of these props, the element text content will be used.

    When the name parameter is undefined it will only check if the element has any accessible name.

    toHaveProp()

    expect(element).toHaveProp(
    diff --git a/14.x/docs/api/misc/accessibility.html b/14.x/docs/api/misc/accessibility.html
    index e59c698d..4ae9663c 100644
    --- a/14.x/docs/api/misc/accessibility.html
    +++ b/14.x/docs/api/misc/accessibility.html
    @@ -6,16 +6,16 @@
         
         
         Accessibility - React Native Testing Library
    -  
    +  
     
       
    -    

    Accessibility

    +

    Accessibility

    isHiddenFromAccessibility

    function isHiddenFromAccessibility(element: HostElement | null): boolean {}

    Also available as isInaccessible() alias for React Testing Library compatibility.

    Checks if given element is hidden from assistive technology, e.g. screen readers.

    NOTE

    Like isInaccessible function from DOM Testing Library this function considers both accessibility elements and presentational elements (regular Views) to be accessible, unless they are hidden in terms of host platform.

    -

    This covers only part of ARIA notion of Accessiblity Tree, as ARIA excludes both hidden and presentational elements from the Accessibility Tree. +

    This covers only part of ARIA notion of Accessibility Tree, as ARIA excludes both hidden and presentational elements from the Accessibility Tree.

    For the scope of this function, element is inaccessible when it, or any of its ancestors, meets any of the following conditions:

    -

    Specifying accessible={false}, accessiblityRole="none", or importantForAccessibility="no" props does not cause the element to become inaccessible.

    +

    Specifying accessible={false}, role="none", accessibilityRole="none", or importantForAccessibility="no" props does not cause the element to become inaccessible.

    diff --git a/14.x/docs/api/misc/async.html b/14.x/docs/api/misc/async.html index 85b73147..375797e4 100644 --- a/14.x/docs/api/misc/async.html +++ b/14.x/docs/api/misc/async.html @@ -6,16 +6,20 @@ Async utilities - React Native Testing Library - + -

    Async utilities

    +

    Async utilities

    findBy* queries

    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.

    waitFor

    function waitFor<T>(
       expectation: () => T,
    -  options?: { timeout: number; interval: number }
    +  options?: {
    +    timeout?: number;
    +    interval?: number;
    +    onTimeout?: (error: Error) => Error;
    +  }
     ): Promise<T>;

    Waits for a period of time for the expectation callback to pass. waitFor may run the callback a number of 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, will be treated as meeting the expectation, and the callback result will be returned to the caller of waitFor function.

    await waitFor(() => expect(mockFunction).toHaveBeenCalledWith());
    @@ -28,9 +32,9 @@
    NOTE

    You can enforce awaiting waitFor by using the await-async-utils rule from eslint-plugin-testing-library.

    Since waitFor is likely to run expectation callback multiple times, it is highly recommended for it not to perform any side effects in waitFor.

    -
    await waitFor(() => {
    +
    await waitFor(async () => {
       // ❌ button will be pressed on each waitFor iteration
    -  fireEvent.press(screen.getByText('press me'));
    +  await fireEvent.press(screen.getByText('press me'));
       expect(mockOnPress).toHaveBeenCalled();
     });
    NOTE

    Avoiding side effects in expectation callback can be partially enforced with the no-wait-for-side-effects rule. @@ -62,28 +66,41 @@ // in test jest.useFakeTimers(); -await waitFor(() => { - expect(someFunction).toHaveBeenCalledWith(); -}, 10000);

    +await waitFor( + () => { + expect(someFunction).toHaveBeenCalledWith(); + }, + { timeout: 10000 } +);
    NOTE

    If you receive warnings related to act() function consult our Understanding Act function document.

    +

    Options

    +
      +
    • timeout: How long to wait for, in ms. Defaults to 1000 ms (configured by asyncUtilTimeout option).
    • +
    • interval: How often to check, in ms. Defaults to 50 ms.
    • +
    • onTimeout: Callback to transform the error before it's thrown. Useful for debugging, e.g., onTimeout: () => { screen.debug(); }.
    • +

    waitForElementToBeRemoved

    function waitForElementToBeRemoved<T>(
       expectation: () => T,
    -  options?: { timeout: number; interval: number }
    +  options?: {
    +    timeout?: number;
    +    interval?: number;
    +    onTimeout?: (error: Error) => Error;
    +  }
     ): Promise<T>;

    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.

    import { render, screen, waitForElementToBeRemoved } from '@testing-library/react-native';
     
     test('waiting for an Banana to be removed', async () => {
    -  render(<Banana />);
    +  await render(<Banana />);
     
       await waitForElementToBeRemoved(() => screen.getByText('Banana ready'));
     });

    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.

    You can use any of getBy, getAllBy, queryBy and queryAllBy queries for expectation parameter.

    NOTE

    If you receive warnings related to act() function consult our Understanding Act function document. -

    +

    diff --git a/14.x/docs/api/misc/config.html b/14.x/docs/api/misc/config.html index 26b41804..d4bf9aea 100644 --- a/14.x/docs/api/misc/config.html +++ b/14.x/docs/api/misc/config.html @@ -6,19 +6,28 @@ Configuration - React Native Testing Library - + -

    Configuration

    +

    Configuration

    configure

    type Config = {
    +  /** Default timeout, in ms, for `waitFor` and `findBy*` queries. */
       asyncUtilTimeout: number;
    -  defaultHidden: boolean;
    -  defaultDebugOptions: Partial<DebugOptions>;
    -  concurrentRoot: boolean;
    +
    +  /** Default value for `includeHiddenElements` query option. */
    +  defaultIncludeHiddenElements: boolean;
    +
    +  /** Default options for `debug` helper. */
    +  defaultDebugOptions?: Partial<DebugOptions>;
     };
     
    -function configure(options: Partial<Config>) {}
    +type ConfigAliasOptions = { + /** RTL-compatibility alias for `defaultIncludeHiddenElements`. */ + defaultHidden: boolean; +}; + +function configure(options: Partial<Config & ConfigAliasOptions>) {}

    asyncUtilTimeout option

    Default timeout, in ms, for async helper functions (waitFor, waitForElementToBeRemoved) and findBy* queries. Defaults to 1000 ms.

    defaultIncludeHiddenElements option

    @@ -26,9 +35,6 @@

    This option is also available as defaultHidden alias for compatibility with React Testing Library.

    defaultDebugOptions option

    Default debug options to be used when calling debug(). These default options will be overridden by the ones you specify directly when calling debug().

    -

    concurrentRoot option

    -

    Set to false to disable concurrent rendering. -Otherwise, render will default to using concurrent rendering used in the React Native New Architecture.

    resetToDefaults()

    function resetToDefaults() {}

    Environment variables

    @@ -37,7 +43,7 @@ Otherwise, render will default to using concurrent rendering used i
    $ RNTL_SKIP_AUTO_CLEANUP=true jest

    RNTL_SKIP_AUTO_DETECT_FAKE_TIMERS

    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 for more details.

    -
    $ RNTL_SKIP_AUTO_DETECT_FAKE_TIMERS=true jest
    +
    $ RNTL_SKIP_AUTO_DETECT_FAKE_TIMERS=true jest
    diff --git a/14.x/docs/api/misc/other.html b/14.x/docs/api/misc/other.html index 00e09072..718c2d26 100644 --- a/14.x/docs/api/misc/other.html +++ b/14.x/docs/api/misc/other.html @@ -6,20 +6,20 @@ Other helpers - React Native Testing Library - + -

    Other helpers

    +

    Other helpers

    within

    function within(element: HostElement): Queries {}

    within performs queries scoped to given element.

    NOTE

    Please note that additional render specific operations like rerender, unmount, debug, toJSON are not included.

    -
    const detailsScreen = within(screen.getByA11yHint('Details Screen'));
    +
    const detailsScreen = within(screen.getByHintText('Details Screen'));
     expect(detailsScreen.getByText('Some Text')).toBeOnTheScreen();
     expect(detailsScreen.getByDisplayValue('Some Value')).toBeOnTheScreen();
     expect(detailsScreen.queryByLabelText('Some Label')).toBeOnTheScreen();
    -await expect(detailsScreen.findByA11yHint('Some Label')).resolves.toBeOnTheScreen();
    +
    await expect(detailsScreen.findByHintText('Some Label')).resolves.toBeOnTheScreen();

    Use cases for scoped queries include:

    • queries scoped to a single item inside a FlatList containing many items
    • @@ -27,20 +27,20 @@

    act

    function act<T>(callback: () => T | Promise<T>): Promise<T>;
    -

    Useful function to help testing components that use hooks API. By default any render, rerender, fireEvent, and waitFor calls are wrapped by this function, so there is no need to wrap it manually.

    -

    In v14, act is now async by default and always returns a Promise, making it compatible with React 19, React Suspense, and React.use(). This ensures all pending React updates are executed before the Promise resolves.

    +

    Wraps code that causes React state updates to ensure all updates are processed before assertions. By default any render, rerender, fireEvent, and waitFor calls are wrapped by this function, so there is no need to wrap it manually.

    +

    In v14, act is now async by default and always returns a Promise, making it compatible with async React features like Suspense boundary or use() hook. This ensures all pending React updates are executed before the Promise resolves.

    import { act } from '@testing-library/react-native';
     
     it('should update state', async () => {
    -  await act(async () => {
    +  await act(() => {
         setState('new value');
       });
       expect(state).toBe('new value');
     });
    -

    Note: Even if your callback is synchronous, you should still use await act(async () => ...) as act now always returns a Promise.

    +

    Note: Even if your callback is synchronous, you should still use await act(...) as act now always returns a Promise.

    Consult our Understanding Act function document for more understanding of its intricacies.

    cleanup

    -
    const cleanup: () => void;
    +
    function cleanup(): Promise<void>;

    Unmounts React trees that were mounted with render and clears screen variable that holds latest render output.

    INFO

    Please note that this is done automatically if the testing framework you're using supports the afterEach global (like mocha, Jest, and Jasmine). If not, you will need to do manual cleanups after each test.

    @@ -48,18 +48,22 @@
    import { cleanup, render } from '@testing-library/react-native/pure';
     import { View } from 'react-native';
     
    -afterEach(cleanup);
    +afterEach(async () => {
    +  await cleanup();
    +});
     
    -it('renders a view', () => {
    -  render(<View />);
    +it('renders a view', async () => {
    +  await render(<View />);
       // ...
     });

    The afterEach(cleanup) call also works in describe blocks:

    describe('when logged in', () => {
    -  afterEach(cleanup);
    +  afterEach(async () => {
    +    await cleanup();
    +  });
     
    -  it('renders the user', () => {
    -    render(<SiteHeader />);
    +  it('renders the user', async () => {
    +    await render(<SiteHeader />);
         // ...
       });
     });
    diff --git a/14.x/docs/api/misc/render-hook.html b/14.x/docs/api/misc/render-hook.html index c9d4e67d..6c3fafe0 100644 --- a/14.x/docs/api/misc/render-hook.html +++ b/14.x/docs/api/misc/render-hook.html @@ -6,21 +6,21 @@ `renderHook` function - React Native Testing Library - + -

    renderHook function

    +

    renderHook function

    renderHook

    async function renderHook<Result, Props>(
    -  hookFn: (props?: Props) => Result,
    +  hookFn: (props: Props) => Result,
       options?: RenderHookOptions<Props>
     ): Promise<RenderHookResult<Result, Props>>;

    Renders a test component that will call the provided callback, including any hooks it calls, every time it renders. Returns a Promise that resolves to a RenderHookResult object, which you can interact with.

    -

    This is the recommended default API for testing hooks. It uses async act internally to ensure all pending React updates are executed during rendering, making it compatible with React 19, React Suspense, and React.use().

    +

    This is the recommended default API for testing hooks. It uses async act internally to ensure all pending React updates are executed during rendering, making it compatible with async React features like Suspense boundary or use() hook.

    • Returns a Promise: Should be awaited
    • Async methods: Both rerender and unmount return Promises and should be awaited
    • -
    • Suspense support: Compatible with React Suspense boundaries and React.use()
    • +
    • Suspense support: Compatible with Suspense boundaries and use() hook
    import { renderHook, act } from '@testing-library/react-native';
     import { useCount } from '../useCount';
    @@ -29,14 +29,16 @@
       const { result } = await renderHook(() => useCount());
     
       expect(result.current.count).toBe(0);
    -  await act(async () => {
    +  await act(() => {
         // Note that you should wrap the calls to functions your hook returns with `act` if they trigger an update of your hook's state to ensure pending useEffects are run before your next assertion.
         result.current.increment();
       });
       expect(result.current.count).toBe(1);
     });
    // useCount.js
    -export const useCount = () => {
    +import { useState } from 'react';
    +
    +export const useCount = () => {
       const [count, setCount] = useState(0);
       const increment = () => setCount((previousCount) => previousCount + 1);
     
    @@ -60,6 +62,7 @@
     

    The renderHook function returns a Promise that resolves to an object with the following properties:

    result

    The current value of the result will reflect the latest of whatever is returned from the callback passed to renderHook. The Result type is determined by the type passed to or inferred by the renderHook call.

    +

    Note: When using React Suspense, result.current will be null while the hook is suspended.

    rerender

    An async function to rerender the test component, causing any hooks to be recalculated. If newProps are passed, they will replace the callback function's initialProps for subsequent rerenders. The Props type is determined by the type passed to or inferred by the renderHook call.

    Note: This method returns a Promise and should be awaited.

    @@ -69,7 +72,10 @@

    Examples

    Here we present some extra examples of using renderHook API.

    With initialProps

    -
    const useCount = (initialCount: number) => {
    +
    import { useState, useEffect } from 'react';
    +import { renderHook, act } from '@testing-library/react-native';
    +
    +const useCount = (initialCount: number) => {
       const [count, setCount] = useState(initialCount);
       const increment = () => setCount((previousCount) => previousCount + 1);
     
    @@ -87,7 +93,7 @@
     
       expect(result.current.count).toBe(1);
     
    -  await act(async () => {
    +  await act(() => {
         result.current.increment();
       });
     
    @@ -128,7 +134,7 @@
       // Initially suspended, result should not be available
       expect(result.current).toBeNull();
     
    -  await act(async () => resolvePromise('resolved'));
    +  await act(() => resolvePromise('resolved'));
       expect(result.current).toBe('resolved');
     });
    diff --git a/14.x/docs/api/queries.html b/14.x/docs/api/queries.html index 6b29485e..dddd2915 100644 --- a/14.x/docs/api/queries.html +++ b/14.x/docs/api/queries.html @@ -6,18 +6,18 @@ Queries - React Native Testing Library - + -

    Queries

    +

    Queries

    Queries are one of the main building blocks for the React Native Testing Library. They enable you to find relevant elements in the element tree, which represents your application's user interface when running under tests.

    Accessing queries

    All queries described below are accessible in two main ways: through the screen object or by capturing the render function call result.

    Using screen object

    import { render, screen } from '@testing-library/react-native';
     
    -test('accessing queries using "screen" object', () => {
    -  render(...);
    +test('accessing queries using "screen" object', async () => {
    +  await render(...);
     
       screen.getByRole("button", { name: "Start" });
     })
    @@ -25,8 +25,8 @@

    Using render result

    import { render } from '@testing-library/react-native';
     
    -test('accessing queries using "render" result', () => {
    -  const { getByRole } = render(...);
    +test('accessing queries using "render" result', async () => {
    +  const { getByRole } = await render(...);
       getByRole("button", { name: "Start" });
     })

    The classic way is to capture query functions, as they are returned from the render function call. This provides access to the same functions as in the case of the screen object.

    @@ -122,9 +122,9 @@
    INFO

    In cases when your findBy* and findAllBy* queries throw when unable to find matching elements, it is helpful to pass onTimeout: () => { screen.debug(); } callback using the waitForOptions parameter.

    Query predicates

    -

    Note: most methods like this one return a HostElement with following properties that you may be interested in:

    +

    Note: most methods like this one return a HostElement with following properties that you may be interested in:

    type HostElement = {
    -  type: string | Function;
    +  type: string;
       props: { [propName: string]: any };
       parent: HostElement | null;
       children: Array<HostElement | string>;
    @@ -161,7 +161,7 @@
     
    import { render, screen } from '@testing-library/react-native';
     
    -render(
    +await render(
       <Pressable accessibilityRole="button" disabled>
         <Text>Hello</Text>
       </Pressable>
    @@ -235,10 +235,11 @@
     
     
    import { render, screen } from '@testing-library/react-native';
     
    -render(<MyComponent />);
    +await render(<MyComponent />);
     const element = screen.getByLabelText('my-label');

    *ByPlaceholderText

    @@ -255,7 +256,7 @@

    Returns a HostElement for a TextInput with a matching placeholder – may be a string or regular expression.

    import { render, screen } from '@testing-library/react-native';
     
    -render(<MyComponent />);
    +await render(<MyComponent />);
     const element = screen.getByPlaceholderText('username');

    *ByDisplayValue

    @@ -272,7 +273,7 @@

    Returns a HostElement for a TextInput with a matching display value – may be a string or regular expression.

    import { render, screen } from '@testing-library/react-native';
     
    -render(<MyComponent />);
    +await render(<MyComponent />);
     const element = screen.getByDisplayValue('username');

    *ByText

    @@ -290,7 +291,7 @@

    This method will join <Text> siblings to find matches, similarly to how React Native handles these components. This will allow for querying for strings that will be visually rendered together, but may be semantically separate React components.

    import { render, screen } from '@testing-library/react-native';
     
    -render(<MyComponent />);
    +await render(<MyComponent />);
     const element = screen.getByText('banana');

    *ByHintText

    @@ -309,7 +310,7 @@ getByHintText, getAllByHintText, queryByHintText, queryAllByHintText, findByHint

    Returns a HostElement with matching accessibilityHint prop.

    import { render, screen } from '@testing-library/react-native';
     
    -render(<MyComponent />);
    +await render(<MyComponent />);
     const element = screen.getByHintText('Plays a song');
    @@ -328,7 +329,7 @@ getByHintText, getAllByHintText, queryByHintText, queryAllByHintText, findByHint

    Returns a HostElement with matching testID prop. testID – may be a string or a regular expression.

    import { render, screen } from '@testing-library/react-native';
     
    -render(<MyComponent />);
    +await render(<MyComponent />);
     const element = screen.getByTestId('unique-id');
    INFO

    In the spirit of the guiding principles, it is recommended to use this only after the other queries don't work for your use case. Using testID attributes do not resemble how your software is used and should be avoided if possible. However, they are particularly useful for end-to-end testing on real devices, e.g. using Detox and it's an encouraged technique to use there. Learn more from the blog post "Making your UI tests resilient to change".

    @@ -339,7 +340,7 @@ getByHintText, getAllByHintText, queryByHintText, queryAllByHintText, findByHint

    You can configure the default value with the configure function.

    This option is also available as hidden alias for compatibility with React Testing Library.

    Examples

    -
    render(<Text style={{ display: 'none' }}>Hidden from accessibility</Text>);
    +
    await render(<Text style={{ display: 'none' }}>Hidden from accessibility</Text>);
     
     // Exclude hidden elements
     expect(
    @@ -358,7 +359,7 @@ getByHintText, getAllByHintText, queryByHintText, queryAllByHintText, findByHint
     

    Most of the query APIs take a TextMatch as an argument, which means the argument can be either a string or regex.

    Examples

    Given the following render:

    -
    render(<Text>Hello World</Text>);
    +
    await render(<Text>Hello World</Text>);

    Will find a match:

    // Matching a string:
     screen.getByText('Hello World'); // full string match
    @@ -407,28 +408,13 @@ getByHintText, getAllByHintText, queryByHintText, queryAllByHintText, findByHint
     
     
    Normalization Examples

    To perform a match against text without trimming:

    -
    screen.getByText(node, 'text', {
    +
    screen.getByText('text', {
       normalizer: getDefaultNormalizer({ trim: false }),
     });

    To override normalization to remove some Unicode characters whilst keeping some (but not all) of the built-in normalization behavior:

    -
    screen.getByText(node, 'text', {
    +
    screen.getByText('text', {
       normalizer: (str) => getDefaultNormalizer({ trim: false })(str).replace(/[\u200E-\u200F]*/g, ''),
    -});
    -

    Legacy unit testing helpers

    -

    render from @testing-library/react-native exposes additional queries that should not be used in integration or component testing, but some users (like component library creators) interested in unit testing some components may find helpful.

    -

    The interface is the same as for other queries, but we won't provide full names so that they're harder to find by search engines.

    -

    UNSAFE_ByType

    -
    -

    UNSAFE_getByType, UNSAFE_getAllByType, UNSAFE_queryByType, UNSAFE_queryAllByType

    -
    -

    Returns a HostElement with matching a React component type.

    -
    CAUTION

    This query has been marked unsafe, since it requires knowledge about implementation details of the component. Use responsibly.

    -

    UNSAFE_ByProps

    -
    -

    UNSAFE_getByProps, UNSAFE_getAllByProps, UNSAFE_queryByProps, UNSAFE_queryAllByProps

    -
    -

    Returns a HostElement with matching props object.

    -
    CAUTION

    This query has been marked unsafe, since it requires knowledge about implementation details of the component. Use responsibly.

    +});
    diff --git a/14.x/docs/api/render.html b/14.x/docs/api/render.html index 97a2bc54..797692b1 100644 --- a/14.x/docs/api/render.html +++ b/14.x/docs/api/render.html @@ -6,16 +6,16 @@ `render` API - React Native Testing Library - + -

    render API

    +

    render API

    render function

    -
    async function render(
    -  component: React.Element<any>,
    +
    async function render<T>(
    +  element: React.ReactElement<T>,
       options?: RenderOptions
    -): Promise<RenderResult>
    -

    The render function is the entry point for writing React Native Testing Library tests. It deeply renders the given React element and returns helpers to query the output components' structure. This function is async by default and uses async act internally to ensure all pending React updates are executed during rendering, making it compatible with React 19, React Suspense, and React.use().

    +
    ): Promise<RenderResult>;
    +

    The render function is the entry point for writing React Native Testing Library tests. It deeply renders the given React element and returns helpers to query the output components' structure. This function is async by default and uses async act internally to ensure all pending React updates are executed during rendering, making it compatible with async React features like Suspense boundary or use() hook.

    import { render, screen } from '@testing-library/react-native';
     
     test('basic test', async () => {
    @@ -30,11 +30,8 @@
     

    wrapper

    wrapper?: React.ComponentType<any>,

    This option allows you to wrap the tested component, passed as the first option to theΒ render()Β function, in an additional wrapper component. This is useful for creating reusable custom render functions for common React Context providers.

    -

    concurrentRoot

    -

    Set to false to disable concurrent rendering. -Otherwise, render will default to using concurrent rendering used in the React Native New Architecture.

    createNodeMock

    -
    createNodeMock?: (element: React.Element) => unknown,
    +
    createNodeMock?: (element: React.ReactElement) => object,

    This option allows you to pass createNodeMock option to the renderer's create() method in order to allow for custom mock refs. This option is passed through to Test Renderer.

    Text string validation

    Test Renderer automatically enforces React Native's requirement that text strings must be rendered within a <Text> component. If you try to render a string value under components other than <Text> (e.g., under <View>), it will throw an Invariant Violation: Text strings must be rendered within a <Text> component error, matching React Native's runtime behavior.

    @@ -43,9 +40,9 @@ Otherwise, render will default to using concurrent rendering used i

    Result

    The render function returns a promise that resolves to the same queries and utilities as the screen object. We recommend using the screen object for queries and the lifecycle methods from the render result when needed.

    See this article from Kent C. Dodds for more details.

    -
    Async lifecycle methods
    -

    When using render, the lifecycle methods rerender and unmount are async and must be awaited.

    -
    +
    Type information
    +

    Query results and element references use the HostElement type from Test Renderer. If you need to type element variables, you can import this type directly from test-renderer.

    +
    diff --git a/14.x/docs/api/screen.html b/14.x/docs/api/screen.html index 0bfbbf10..32ba1c0e 100644 --- a/14.x/docs/api/screen.html +++ b/14.x/docs/api/screen.html @@ -6,10 +6,10 @@ `screen` object - React Native Testing Library - + -

    screen object

    +

    screen object

    let screen: {
       ...queries;
       rerender(element: React.Element<unknown>): Promise<void>;
    @@ -17,7 +17,7 @@
       debug(options?: DebugOptions): void
       toJSON(): JsonElement | null;
       container: HostElement;
    -  root: HostElement;
    +  root: HostElement | null;
     };

    The screen object offers a recommended way to access queries and utilities for the currently rendered UI.

    This object is assigned after the render call and cleared after each test by calling cleanup. If no render call has been made in a given test, then it holds a special object and throws a helpful error on each property and method access.

    @@ -34,7 +34,7 @@

    rerender

    function rerender(element: React.Element<unknown>): Promise<void>;

    Re-render the in-memory tree with a new root element. This simulates a React update render at the root. If the new element has the same type (and key) as the previous element, the tree will be updated; otherwise, it will re-mount a new tree, in both cases triggering the appropriate lifecycle events.

    -

    This method is async and uses async act function internally to ensure all pending React updates are executed during updating, making it compatible with React 19, React Suspense, and React.use().

    +

    This method is async and uses async act function internally to ensure all pending React updates are executed during updating, making it compatible with async React features like Suspense boundary or use() hook.

    import { render, screen } from '@testing-library/react-native';
     
     test('async rerender test', async () => {
    @@ -46,7 +46,7 @@
     

    unmount

    function unmount(): Promise<void>;

    Unmount the in-memory tree, triggering the appropriate lifecycle events.

    -

    This method is async and uses async act function internally to ensure all pending React updates are executed during unmounting, making it compatible with React 19, React Suspense, and React.use().

    +

    This method is async and uses async act function internally to ensure all pending React updates are executed during unmounting, making it compatible with async React features like Suspense boundary or use() hook.

    NOTE

    Usually you should not need to call unmount as it is done automatically if your test runner supports afterEach hook (like Jest, mocha, Jasmine).

    @@ -95,9 +95,12 @@
    expect(container).toBeTruthy(); });

    root

    -
    const root: HostElement;
    -

    Returns the rendered root host element. This is the first child of the container, which represents the actual root element you rendered.

    +
    const root: HostElement | null;
    +

    Returns the rendered root host element, or null if nothing was rendered. This is the first child of the container, which represents the actual root element you rendered.

    This API is primarily useful for component tests, as it allows you to access root host view without using *ByTestId queries or similar methods.

    +
    NOTE
    +

    In rare cases where your root element is a React.Fragment with multiple children, the container will have more than one child, and root will return only the first one. In such cases, use container.children to access all rendered elements.

    +
    import { render, screen } from '@testing-library/react-native';
     
     test('example', async () => {
    diff --git a/14.x/docs/guides/community-resources.html b/14.x/docs/guides/community-resources.html
    index 39cce883..620d04b5 100644
    --- a/14.x/docs/guides/community-resources.html
    +++ b/14.x/docs/guides/community-resources.html
    @@ -6,10 +6,10 @@
         
         
         Community resources - React Native Testing Library
    -  
    +  
     
       
    -    

    Community resources

    +

    Community resources

    4. Test ID query

    As a final predicate, you can use the testID prop to find relevant views. Using the *ByTestId predicate offers the most flexibility, but at the same time, it does not represent the user experience, as users are not aware of test IDs.

    -

    Note that using test IDs is a widespread technique in end-to-end testing due to various issues with querying views through other means in its specific context. Nevertheless, we still encourage you to use recommended RNTL queries as it will make your integration and component test more reliable and resilient.

    +

    Note that using test IDs is a widespread technique in end-to-end testing due to various issues with querying views through other means in its specific context. Nevertheless, we still encourage you to use recommended RNTL queries as it will make your integration and component test more reliable and resilient.

    diff --git a/14.x/docs/guides/react-19.html b/14.x/docs/guides/react-19.html deleted file mode 100644 index ab215266..00000000 --- a/14.x/docs/guides/react-19.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - React 19 & Suspense Support - React Native Testing Library - - - -

    React 19 & Suspense Support

    -

    React 19 introduced full support for React Suspense, React.use(), and other async rendering features to React Native 0.78.0.

    -

    When testing components that use these features, React requires the async act helper to handle async state updates. This means React Native Testing Library needs new async versions of its core APIs. These async APIs work with both React 18 and React 19.

    -

    New async APIs

    -

    RNTL 14 introduces async versions of the core testing APIs to handle React 19's async rendering:

    -

    Rendering APIs:

    - -

    Event APIs:

    -
      -
    • fireEvent - updated to be async by default.
    • -
    -

    APIs that remain unchanged

    -

    Many existing APIs continue to work without modification:

    -
      -
    • Query methods: screen.getBy*, screen.queryBy*, screen.findBy* - all work the same
    • -
    • User Event API - already async, so no API changes needed
    • -
    • Jest matchers - work with already-rendered output, so no changes required
    • -
    -

    What changes in your tests

    -

    Making tests async

    -

    The main change is using render which is now async by default, which requires:

    -
      -
    1. Making your test function async
    2. -
    3. Adding await before render
    4. -
    -
    // Async approach (React 19 ready, default in v14)
    -test('my component', async () => {
    -  await render(<MyComponent />);
    -  expect(screen.getByText('Hello')).toBeOnTheScreen();
    -});
    -

    When to use async APIs

    -

    Use the async APIs when your components:

    -
      -
    • Use React Suspense for data fetching or code splitting
    • -
    • Call React.use() for reading promises or context
    • -
    • Have async state updates that need proper act() handling
    • -
    -

    Migration strategy

    -

    New projects

    -

    Use the async-ready APIs (render, User Event, Jest Matchers, etc.) from the start. They work with both React 18 and React 19.

    -

    Existing projects

    -

    You can migrate gradually:

    -
      -
    • Existing tests should be migrated to use async render (see migration guide)
    • -
    • New tests should use async render (default in v14)
    • -
    • Tests with Suspense/React.use() must use async render
    • -
    -

    Migration

    -

    See the v14 migration guide for detailed migration steps.

    -
    - - diff --git a/14.x/docs/guides/troubleshooting.html b/14.x/docs/guides/troubleshooting.html index 5203975e..cffdcb90 100644 --- a/14.x/docs/guides/troubleshooting.html +++ b/14.x/docs/guides/troubleshooting.html @@ -6,26 +6,11 @@ Troubleshooting - React Native Testing Library - + -

    Troubleshooting

    +

    Troubleshooting

    This guide describes common issues found by users when integrating React Native Test Library to their projects:

    -

    Matching React Native, React & Test Renderer versions

    -

    Check that you have matching versions of core dependencies:

    -
      -
    • React Native
    • -
    • React
    • -
    • Test Renderer (automatically installed with RNTL)
    • -
    -

    React Native uses different versioning scheme from React, you can use React Native Upgrade Helper to find the correct matching between React Native & React versions. In case you use Expo, run npx expo install --fix in your project to validate and install compatible versions of these dependencies.

    -

    Test Renderer is automatically managed as a dependency of React Native Testing Library and is compatible with React 18 and React 19.

    -

    Related issues: #1061, #938, #920

    -

    Errors that might indicate that you are facing this issue:

    -
      -
    • TypeError: Cannot read property 'current' of undefined when calling render()
    • -
    • TypeError: Cannot read property 'isBatchingLegacy' of undefined when calling render()
    • -

    Example repository

    We maintain an example repository that showcases a modern React Native Testing Library setup with TypeScript, etc.

    In case something does not work in your setup you can refer to this repository for recommended configuration.

    @@ -60,7 +45,7 @@

    You can read more about act() function in our understanding act function guide.

    Normally, you should not encounter sync act() warnings, but if that happens this probably indicate an issue with your test and should be investigated.

    -

    In case of async act() function this might happen more or less randomly, especially if your components contain async logic. So far this warning does not seem to affect test correctness.

    +

    In case of async act() function this might happen more or less randomly, especially if your components contain async logic. So far this warning does not seem to affect test correctness.

    diff --git a/14.x/docs/migration/jest-matchers.html b/14.x/docs/migration/jest-matchers.html index cf94e9f9..75edf3b3 100644 --- a/14.x/docs/migration/jest-matchers.html +++ b/14.x/docs/migration/jest-matchers.html @@ -6,10 +6,10 @@ Migration to built-in Jest matchers - React Native Testing Library - + -

    Migration to built-in Jest matchers

    +

    Migration to built-in Jest matchers

    This guide describes the steps necessary to migrate from legacy Jest Native matchers v5 to built-in Jest matchers.

    General notes

    All of the built-in Jest matchers provided by the React Native Testing Library support only host elements. This should not be an issue, as all RNTL v12 queries already return only host elements. When this guide states that a given matcher should work the same it assumes behavior only host elements. If you need to assert the status of composite elements use Jest Native matchers in legacy mode.

    @@ -55,9 +55,9 @@

    You should be aware of the following details:

    • toBeEnabled() / toBeDisabled() matchers also check the disabled state for the element's ancestors and not only the element itself. This is the same as in legacy Jest Native matchers of the same name but differs from the removed toHaveAccessibilityState() matcher.
    • -
    • toBeChecked() matcher supports only elements with a checkbox, radio and 'switch' role
    • +
    • toBeChecked() matcher works only on Switch host elements or accessibility elements with checkbox, radio or switch role
    • toBePartiallyChecked() matcher supports only elements with checkbox role
    • -
    +
    diff --git a/14.x/docs/migration/previous/v11.html b/14.x/docs/migration/previous/v11.html deleted file mode 100644 index 3098e27e..00000000 --- a/14.x/docs/migration/previous/v11.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - Migration to 11.x - React Native Testing Library - - - -

    Migration to 11.x

    -

    Migration to React Native Testing Library version 11 from version 9.x or 10.x should be a relatively easy task due small amount of breaking changes.

    -

    Breaking changes

    -

    Update to Jest 28 if you use fake timers

    -

    If you use fake timers in any of your tests you should update your Jest dependencies to version 28. This is due to the fact that jest.useFakeTimers() config structure has changed.

    -

    Refactor legacy waitForOptions position

    -

    In version 9 we introducted query options parameters for each query type. This affected all findBy and findAllBy queries because their signatures changed e.g. from:

    -
    function findByText(text: TextMatch, waitForOptions?: WaitForOptions);
    -function findAllByText(text: TextMatch, waitForOptions?: WaitForOptions);
    -

    to

    -
    function findByText(text: TextMatch, options?: TextMatchOptions, waitForOptions?: WaitForOptions);
    -function findAllByText(
    -  text: TextMatch,
    -  options?: TextMatchOptions,
    -  waitForOptions?: WaitForOptions
    -);
    -

    In order to facilitate transition, in version 9 and 10, we provided a temporary possibility to pass WaitForOptions like timeout, interval, etc inside options argument. From this release we require passing these as the proper third parameter.

    -

    This change is easy to implement:

    -
    findByText(/Text/, { timeout: 1000 });
    -

    should become

    -
    findByText(/Text/, {}, { timeout: 1000 });
    -

    Triggering non-touch events on targets with pointerEvents="box-none" prop

    -

    Up to version 10, RNTL disables all events for a target with pointerEvents="box-none". This behavior is counter to how React Native itself functions.

    -

    From version 11, RNTL continues to disable press event for these targets but allows triggering other events, e.g. layout.

    -

    Full Changelog

    -

    https://github.com/callstack/react-native-testing-library/compare/v10.1.1...v11.0.0

    -
    - - diff --git a/14.x/docs/migration/previous/v12.html b/14.x/docs/migration/previous/v12.html deleted file mode 100644 index ab7ab45e..00000000 --- a/14.x/docs/migration/previous/v12.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - Migration to 12.x - React Native Testing Library - - - -

    Migration to 12.x

    -
    INFO
    -

    If you are already using legacy @testing-library/jest-native Jest Matchers, we have a migration guide for moving to the built-in matchers.

    -
    -

    React Native Testing Library 12 introduces a handful of breaking changes compared to 11.x versions. We believe they were necessary to improve the experience using the library and help the users fall into the pit of success when writing meaningful tests. You will find migration instructions for each and every change described below.

    -

    Breaking changes

    -

    1. All queries exclude elements hidden from accessibility by default

    -

    Elements that are hidden from accessiblity, e.g. elements on non-active screen when using React Navigation, now will not be matched by default by all queries. This is the effect of switching the default value for global config option defaultIncludeHiddenElements(api#defaultincludehiddenelements-option) to false.

    -

    Previous behaviour of matching hidden elements can be enabled on query level using includeHiddenElements query options or globally using defaultIncludeHiddenElements(api#defaultincludehiddenelements-option) configuration option.

    -

    2. *ByRole queries now return only accessibility elements

    -

    *ByRole queries now return only accessibility elements, either explicitly marked with accessible prop or implicit ones where this status is derived from component type itself (e.g Text, TextInput, Switch, but not View).

    -

    You may need to adjust relevant components under test to make sure they pass isAccessibilityElement check.

    -

    Examples

    -

    Let's assume we are using getByRole("button") query.

    -

    Following elements will match:

    -
    // Explicit "accessible" prop for View
    -<View accessible accessibilityRole="button" />
    -
    -// No need to "accessible" prop for Text, as it is implicitly accessible element.
    -<Text accessibilityRole="button">Button</Text>
    -

    While following elements will not match:

    -
    // Missing "accessible" prop for View
    -<View accessibilityRole="button" />
    -
    -// Explicit "accessible={false}" prop for View
    -<View accessible={false} accessibilityRole="button" />
    -
    -// Explicit "accessible={false}" for Text, which is implicitly accessible element
    -<Text accessible={false} accessibilityRole="button">Button</Text>
    -

    3. *ByText, *ByDisplayValue, *ByPlaceholderText queries now return host elements

    -

    *ByText, *ByDisplayValue, *ByPlaceholderText queries now return host elements, which is consistent with other queries.

    -

    While potentially breaking, this should not cause issues in tests if you are using recommended queries and Jest Matchers from Jest Native package.

    -

    Problematic cases may include: directly checking some prop values (without using Jest Native matchers), referencing other nodes using parent or children props, examining type property of HostElement, etc.

    -

    4. container API has been renamed to UNSAFE_root.

    -

    Historically container was supposed to mimic the RTL's container. However it turned out not so relevant in RNTL's environment, where we actually used it to return React Test Renderer's root instance.

    -

    RNTL v12 introduces root API as an alternative that returns a root host element. The difference between root and UNSAFE_root properties is that that root will always represents a host element, while UNSAFE_root will typically represent a composite element.

    -

    If you use toBeOnTheScreen matcher from @testing-library/jest-native your tests will fail because it uses the container api. To fix this, update @testing-library/jest-native to version 5.4.2.

    -

    Full Changelog

    -

    https://github.com/callstack/react-native-testing-library/compare/v11.5.2...v12.0.0

    -
    - - diff --git a/14.x/docs/migration/previous/v7.html b/14.x/docs/migration/previous/v7.html deleted file mode 100644 index 2a9d695d..00000000 --- a/14.x/docs/migration/previous/v7.html +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - Migration to 7.x - React Native Testing Library - - - -

    Migration to 7.x

    -
    INFO
    -

    We renamed the react-native-testing-library npm package to @testing-library/react-native, officially joining the "Testing Library" family πŸŽ‰.

    -
    -

    As the version 7.0 involves merging two libraries together, there are two variants for migration guide, dependent on library you used previously:

    -

    Guide for react-native-testing-library users

    -

    This guide describes steps necessary to migrate from React Native Testing Library v2.x or v6.0 to v7.0.

    -

    Renaming the library

    -
      -
    1. Install @testing-library/react-native.
    2. -
    3. Uninstall react-native-testing-library.
    4. -
    5. Rename all references of react-native-testing-library to @testing-library/react-native.
    6. -
    -

    You may have noticed a strange v2 to v7 upgrade, skipping versions 3, 4, 5 and 6. This is because we renamed the react-native-testing-library npm package to @testing-library/react-native, officially joining the "Testing Library" family πŸŽ‰. We're merging existing two libraries into a single one. The native-testing-library repository, which had v6, will soon be archived and using @testing-library/react-native below v7, sourced from mentioned repository, is deprecated.

    -

    For branding purposes we keep the "React Native Testing Library" name, similar to "React Testing Library". Only the npm published package is changing. The code repository also stays the same under Callstack governance.

    -

    New aliases

    -

    To improve compatibility with React Testing Library, and ease the migration for @testing-library/react-native users using version below v7, we've introduced new aliases to our accessibility queries:

    -
      -
    • ByLabelText aliasing ByA11yLabel queries
    • -
    • ByHintText aliasing ByA11yHint queries
    • -
    • ByRole aliasing ByA11yRole queries
    • -
    -

    We like the new names and consider removing the aliases in future releases.

    -

    Renaming ByPlaceholder queries

    -

    To improve compatibility with React Testing Library, and to ease the migration for @testing-library/react-native users using version below v7, we've renamed following queries:

    -
      -
    • ByPlaceholder -> ByPlaceholderText
    • -
    -

    Please replace all occurrences of these queries in your codebase.

    -

    fireEvent support for disabled components

    -

    To improve compatibility with the real React Native environment fireEvent now performs checks whether the component is "disabled" before firing an event on it. It uses the Responder system to establish should the event fire, which resembles the actual React Native runtime closer than we used to.

    -

    If your code contained any workarounds for preventing events firing on disabled events, you should now be able to remove them.

    -

    Guide for @testing-library/react-native users

    -

    This guide describes steps necessary to migrate from @testing-library/react-native from v6.0 to v7.0. Although the name stays the same, this is a different library, sourced at Callstack GitHub repository. We made sure the upgrade path is as easy for you as possible.

    -

    Renaming "wait" helpers

    -

    The wait and waitForElement helpers are replaced by waitFor. Please rename all occurrences of these in your codebase.

    -

    Changes to ByTestId queries

    -

    The ByTestId queries don't accept RegExps. Please use strings instead. We're happy to accept PRs adding this functionality :).

    -

    No ByTitle queries

    -

    Our library doesn't implement ByTitle queries, which are targetting components with title prop, specifically Button and RefreshControl. If your tests only use ByTitle to target Button components, you can replace them with ByText queries, since React Native renders Text under the hood.

    -

    If you need to query RefreshControl component and can't figure out other way around it, you can use e.g. UNSAFE_getByProps({title}) query.

    -

    No custom Jest configuration

    -

    Use the official React Native preset for Jest:

    -
    {
    -  "jest": {
    --    "preset": "@testing-library/react-native"
    -+    "preset": "react-native"
    -  }
    -}
    -

    We're told this also speeds up your tests startup on cold cache. Using official preset has another benefit – the library is compatible with any version of React Native without introducing breaking changes.

    -

    Cleanup is included by default

    -

    Cleaning up (unmounting) components after each test is included by default in the same manner as in React Testing Library. Please remove this setup file from Jest config:

    -
    {
    -  "jest": {
    --    "setupFilesAfterEnv": ["@testing-library/react-native/cleanup-after-each"]
    -  }
    -}
    -

    You can opt-out of this behavior by running tests with RNTL_SKIP_AUTO_CLEANUP=true flag or importing from @testing-library/react-native/pure. We encourage you to keep the default though.

    -

    No NativeTestInstance abstraction

    -

    We don't provide any abstraction over HostElement returned by queries, but allow to use it directly to access queried component's props or type for that example.

    -

    No container nor baseElement returned from render

    -

    There's no container returned from the render function. If you must, use react-test-renderer directly, although we advise against doing so. We also don't implement baseElement because of that, since there's no document.documentElement nor container.

    -

    Firing events changes

    -

    There are slight differences in how fireEvent works in both libraries:

    -
      -
    1. Our library doesn't perform validation checks for events fired upon tested components.
    2. -
    3. Signature is different: -
      -fireEvent[eventName](node: FiberRoot, eventProperties: NativeTestEvent)
      -+fireEvent(element: HostElement, eventName: string, ...data: Array<any>)
      -
    4. -
    5. There is no NativeTestEvent - second and rest arguments are used instead.
    6. -
    7. There are only 3 short-hand events: fireEvent.press, fireEvent.changeText and fireEvent.scroll. For all other or custom events you can use the base signature.
    8. -
    -
    - - diff --git a/14.x/docs/migration/previous/v9.html b/14.x/docs/migration/previous/v9.html deleted file mode 100644 index 00da6144..00000000 --- a/14.x/docs/migration/previous/v9.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - Migration to 9.x - React Native Testing Library - - - -

    Migration to 9.x

    -

    Version 7.0 brought React Native Testing Library into the @testing-library family. Since it has been implemented independently from its web counterpart – the React Testing Library – there are some differences in the API and behavior. Version 9.0 solves several of these problems.

    -

    Support for text match options a.k.a string precision API

    -

    This is a backward compatible change.

    -

    When querying text, it is now possible to pass a TextMatch to most text based queries, which lets you configure how @testing-library/react-native should match your text. For instance, passing exact: false will allow matching substrings and will ignore case:

    -
    const { getByText } = render(<Text>Hello World</Text>);
    -
    -getByText('Hello World'); // Matches
    -getByText('Hello'); // Doesn't match
    -getByText('hello', { exact: false }); // ignore case-sensitivity and does partial matching
    -

    Please note that the findBy* queries used to take a waitForOptions parameter as a second argument, which has now been moved to the third argument:

    -
    -findByText('Hello world', { timeout: 3000 }); // old findBy* API
    -+findByText('Hello world', {}, { timeout: 3000 }); // new findBy* API
    -

    For backward compatibility RNTL v9 can still read waitForOptions from the second argument but will print a deprecation warning.

    -

    Reverted matching text across several nodes

    -
    CAUTION

    This is a breaking change.

    -

    In v1.14 we've introduced a feature allowing to match text when it's spread across several nodes:

    -
    const { getByText } = render(
    -  <Text>
    -    Hello <Text>world</Text>
    -  </Text>
    -);
    -getByText('Hello world'); // matches
    -

    However this behavior was different than the web one, and wouldn't always be straightforward to reason about. For instance it could match text nodes far from each other on the screen. It also prevented us from implementing the string precision API. From v9, this type of match will not work.

    -

    A work around is to use within:

    -
    import { Text } from 'react-native'
    -import { render, within } from '@testing-library/react-native'
    -
    -const { getByText } = render(<Text>Hello <Text>world</Text</Text>)
    -
    -within(getByText('Hello', {exact: false})).getByText('world')
    -

    Future plans

    -

    This release changes a lot of internal logic in the library, paving the way for more improvements to bring us closer to our web counterpart, with a possibly better story for accessibility queries.

    -

    We're also migrating the codebase to TypeScript. Please let us know if you're interested in helping us with this effort.

    -

    Stay safe!

    -
    - - diff --git a/14.x/docs/migration/v11.html b/14.x/docs/migration/v11.html new file mode 100644 index 00000000..4c60572b --- /dev/null +++ b/14.x/docs/migration/v11.html @@ -0,0 +1,40 @@ + + + + + + + + Migration to 11.x - React Native Testing Library + + + +

    Migration to 11.x

    +

    Migration to React Native Testing Library version 11 from version 9.x or 10.x should be a relatively easy task due small amount of breaking changes.

    +

    Breaking changes

    +

    Update to Jest 28 if you use fake timers

    +

    If you use fake timers in any of your tests you should update your Jest dependencies to version 28. This is due to the fact that jest.useFakeTimers() config structure has changed.

    +

    Refactor legacy waitForOptions position

    +

    In version 9 we introducted query options parameters for each query type. This affected all findBy and findAllBy queries because their signatures changed e.g. from:

    +
    function findByText(text: TextMatch, waitForOptions?: WaitForOptions);
    +function findAllByText(text: TextMatch, waitForOptions?: WaitForOptions);
    +

    to

    +
    function findByText(text: TextMatch, options?: TextMatchOptions, waitForOptions?: WaitForOptions);
    +function findAllByText(
    +  text: TextMatch,
    +  options?: TextMatchOptions,
    +  waitForOptions?: WaitForOptions
    +);
    +

    In order to facilitate transition, in version 9 and 10, we provided a temporary possibility to pass WaitForOptions like timeout, interval, etc inside options argument. From this release we require passing these as the proper third parameter.

    +

    This change is easy to implement:

    +
    findByText(/Text/, { timeout: 1000 });
    +

    should become

    +
    findByText(/Text/, {}, { timeout: 1000 });
    +

    Triggering non-touch events on targets with pointerEvents="box-none" prop

    +

    Up to version 10, RNTL disables all events for a target with pointerEvents="box-none". This behavior is counter to how React Native itself functions.

    +

    From version 11, RNTL continues to disable press event for these targets but allows triggering other events, e.g. layout.

    +

    Full Changelog

    +

    https://github.com/callstack/react-native-testing-library/compare/v10.1.1...v11.0.0

    +
    + + diff --git a/14.x/docs/migration/v12.html b/14.x/docs/migration/v12.html new file mode 100644 index 00000000..13b4374b --- /dev/null +++ b/14.x/docs/migration/v12.html @@ -0,0 +1,53 @@ + + + + + + + + Migration to 12.x - React Native Testing Library + + + +

    Migration to 12.x

    +
    INFO
    +

    If you are already using legacy @testing-library/jest-native Jest Matchers, we have a migration guide for moving to the built-in matchers.

    +
    +

    React Native Testing Library 12 introduces a handful of breaking changes compared to 11.x versions. We believe they were necessary to improve the experience using the library and help the users fall into the pit of success when writing meaningful tests. You will find migration instructions for each and every change described below.

    +

    Breaking changes

    +

    1. All queries exclude elements hidden from accessibility by default

    +

    Elements that are hidden from accessiblity, e.g. elements on non-active screen when using React Navigation, now will not be matched by default by all queries. This is the effect of switching the default value for global config option defaultIncludeHiddenElements(api#defaultincludehiddenelements-option) to false.

    +

    Previous behaviour of matching hidden elements can be enabled on query level using includeHiddenElements query options or globally using defaultIncludeHiddenElements(api#defaultincludehiddenelements-option) configuration option.

    +

    2. *ByRole queries now return only accessibility elements

    +

    *ByRole queries now return only accessibility elements, either explicitly marked with accessible prop or implicit ones where this status is derived from component type itself (e.g Text, TextInput, Switch, but not View).

    +

    You may need to adjust relevant components under test to make sure they pass isAccessibilityElement check.

    +

    Examples

    +

    Let's assume we are using getByRole("button") query.

    +

    Following elements will match:

    +
    // Explicit "accessible" prop for View
    +<View accessible accessibilityRole="button" />
    +
    +// No need to "accessible" prop for Text, as it is implicitly accessible element.
    +<Text accessibilityRole="button">Button</Text>
    +

    While following elements will not match:

    +
    // Missing "accessible" prop for View
    +<View accessibilityRole="button" />
    +
    +// Explicit "accessible={false}" prop for View
    +<View accessible={false} accessibilityRole="button" />
    +
    +// Explicit "accessible={false}" for Text, which is implicitly accessible element
    +<Text accessible={false} accessibilityRole="button">Button</Text>
    +

    3. *ByText, *ByDisplayValue, *ByPlaceholderText queries now return host elements

    +

    *ByText, *ByDisplayValue, *ByPlaceholderText queries now return host elements, which is consistent with other queries.

    +

    While potentially breaking, this should not cause issues in tests if you are using recommended queries and Jest Matchers from Jest Native package.

    +

    Problematic cases may include: directly checking some prop values (without using Jest Native matchers), referencing other nodes using parent or children props, examining type property of HostElement, etc.

    +

    4. container API has been renamed to UNSAFE_root.

    +

    Historically container was supposed to mimic the RTL's container. However it turned out not so relevant in RNTL's environment, where we actually used it to return React Test Renderer's root instance.

    +

    RNTL v12 introduces root API as an alternative that returns a root host element. The difference between root and UNSAFE_root properties is that that root will always represents a host element, while UNSAFE_root will typically represent a composite element.

    +

    If you use toBeOnTheScreen matcher from @testing-library/jest-native your tests will fail because it uses the container api. To fix this, update @testing-library/jest-native to version 5.4.2.

    +

    Full Changelog

    +

    https://github.com/callstack/react-native-testing-library/compare/v11.5.2...v12.0.0

    +
    + + diff --git a/14.x/docs/migration/v13.html b/14.x/docs/migration/v13.html index a210aa0a..d6943449 100644 --- a/14.x/docs/migration/v13.html +++ b/14.x/docs/migration/v13.html @@ -6,10 +6,10 @@ Migration to 13.x - React Native Testing Library - + -

    Migration to 13.x

    +
    +

    https://github.com/callstack/react-native-testing-library/compare/v12.8.1...v13.0.0

    diff --git a/14.x/docs/migration/v14.html b/14.x/docs/migration/v14.html index 9be7e4c4..5e41dd0f 100644 --- a/14.x/docs/migration/v14.html +++ b/14.x/docs/migration/v14.html @@ -6,36 +6,74 @@ Migration to 14.x - React Native Testing Library - + -

    Migration to 14.x

    +

    Migration to 14.x

    This guide describes the migration to React Native Testing Library version 14 from version 13.x.

    -

    Breaking changes

    +

    Overview

    +

    RNTL v14 is a major release that drops support for React 18 and fully embraces React 19's async-first paradigm. Key changes include:

    +
      +
    • React 19+ required: Minimum supported versions are React 19.0.0 and React Native 0.78+
    • +
    • Async APIs by default: render, renderHook, fireEvent, and act are now async
    • +
    • New renderer: Switched from deprecated React Test Renderer to Test Renderer
    • +
    • API cleanup: Removed deprecated APIs (update, getQueriesForElement, UNSAFE_root, concurrentRoot option)
    • +
    • Safe container API: Reintroduced container which is now safe to use
    • +
    +
    React 18 Users
    +

    If you need to support React 18, please continue using RNTL v13.x.

    +
    +

    Quick Migration

    +

    We provide codemods to automate most of the migration:

    +

    Step 1: Update dependencies

    +
    npm
    yarn
    pnpm
    bun
    npx codemod@latest rntl-v14-update-deps --target .
    +npm install
    +

    Step 2: Update test code to async

    +
    npm
    yarn
    pnpm
    bun
    npx codemod@latest rntl-v14-async-functions --target ./src
    +

    After running the codemods, review the changes and run your tests.

    +

    Breaking Changes

    +

    Supported React and React Native versions

    +

    This version requires React 19+ and React Native 0.78+. If you need to support React 18, please use the latest v13.x version.

    + + + + + + + + + + + + + + + + + + + + +
    RNTL VersionReact VersionReact Native Version
    v14.x>= 19.0.0>= 0.78
    v13.x>= 18.0.0>= 0.71

    Test Renderer replaces React Test Renderer

    -

    In v14, React Native Testing Library now uses Test Renderer instead of the deprecated react-test-renderer package. Test Renderer is a modern, actively maintained alternative that provides better compatibility with React 19 and improved type safety.

    +

    In v14, React Native Testing Library now uses Test Renderer instead of the deprecated React Test Renderer. Test Renderer is a modern, actively maintained alternative that provides better compatibility with React 19 and improved type safety.

    What changed:

      -
    • The underlying rendering engine has been switched from react-test-renderer to test-renderer
    • +
    • The underlying renderer has been switched from React Test Renderer to Test Renderer
    • This change is mostly internal and should not require code changes in most cases
    • -
    • Type definitions have been updated to use HostElement from Test Renderer instead of ReactTestInstance
    • +
    • Type definitions have been updated to use HostElement from Test Renderer instead of ReactTestInstance

    Migration:

    1. Update dependencies

    -

    Remove react-test-renderer and its type definitions from your dev dependencies, and add test-renderer:

    -
    # Using npm
    -npm uninstall react-test-renderer @types/react-test-renderer
    -npm install -D test-renderer@^0.10.0
    -
    -# Using yarn
    -yarn remove react-test-renderer @types/react-test-renderer
    -yarn add -D test-renderer@^0.10.0
    -
    -# Using pnpm
    -pnpm remove react-test-renderer @types/react-test-renderer
    -pnpm add -D test-renderer@^0.10.0
    +

    Run codemod for updating dependencies:

    +
    npm
    yarn
    pnpm
    bun
    npx codemod@latest rntl-v14-update-deps
    +npm install
    +
    Manual changes
    +

    Remove React Test Renderer and its type definitions from your dev dependencies, and add Test Renderer:

    +
    npm
    yarn
    pnpm
    bun
    npm uninstall react-test-renderer @types/react-test-renderer
    +npm install -D test-renderer@^0.14.0

    2. Update type imports (if needed)

    -

    If you were directly importing types from react-test-renderer, you may need to update your imports:

    +

    If you were directly importing types from React Test Renderer, you may need to update your imports:

    // Before (v13)
     import type { ReactTestInstance } from 'react-test-renderer';
     
    @@ -43,6 +81,164 @@
     import type { HostElement } from 'test-renderer';

    Note: Most users won't need to update type imports, as React Native Testing Library now exports the necessary types directly.

    For more details, see the Test Renderer documentation.

    +

    Async APIs by Default

    +

    With React 18 support dropped, RNTL v14 fully embraces React 19's async rendering model. The following functions are now async by default:

    +
      +
    • render() β†’ returns Promise<RenderResult>
    • +
    • rerender() and unmount() β†’ return Promise<void>
    • +
    • renderHook() β†’ returns Promise<RenderHookResult>
    • +
    • fireEvent() and helpers (press, changeText, scroll) β†’ return Promise<void>
    • +
    • act() β†’ always returns Promise<T>
    • +
    +
    Already using async APIs?
    +

    If you adopted the async APIs introduced in RNTL v13.3 (renderAsync, fireEventAsync, renderHookAsync), simply rename them to their non-async counterparts (render, fireEvent, renderHook). The async versions have been removed as the standard APIs are now async by default.

    +
    +

    render is now async

    +

    In v14, render is now async by default and returns a Promise. This change enables proper support for async React features like Suspense boundary or use() hook.

    +

    Before (v13):

    +
    import { render, screen } from '@testing-library/react-native';
    +
    +it('should render component', () => {
    +  render(<MyComponent />);
    +  expect(screen.getByText('Hello')).toBeOnTheScreen();
    +});
    +

    After (v14):

    +
    import { render, screen } from '@testing-library/react-native';
    +
    +it('should render component', async () => {
    +  await render(<MyComponent />);
    +  expect(screen.getByText('Hello')).toBeOnTheScreen();
    +});
    +

    For more details, see the render API documentation.

    +

    renderHook is now async

    +

    In v14, renderHook is now async by default and returns a Promise.

    +

    Before (v13):

    +
    import { renderHook } from '@testing-library/react-native';
    +
    +it('should test hook', () => {
    +  const { result, rerender } = renderHook(() => useMyHook());
    +
    +  rerender(newProps);
    +  unmount();
    +});
    +

    After (v14):

    +
    import { renderHook } from '@testing-library/react-native';
    +
    +it('should test hook', async () => {
    +  const { result, rerender } = await renderHook(() => useMyHook());
    +
    +  await rerender(newProps);
    +  await unmount();
    +});
    +

    For more details, see the renderHook API documentation.

    +

    fireEvent is now async

    +

    In v14, fireEvent and its helpers (press, changeText, scroll) are now async by default and return a Promise.

    +

    Before (v13):

    +
    import { fireEvent, screen } from '@testing-library/react-native';
    +
    +it('should press button', () => {
    +  render(<MyComponent />);
    +  fireEvent.press(screen.getByText('Press me'));
    +  expect(onPress).toHaveBeenCalled();
    +});
    +

    After (v14):

    +
    import { fireEvent, screen } from '@testing-library/react-native';
    +
    +it('should press button', async () => {
    +  await render(<MyComponent />);
    +  await fireEvent.press(screen.getByText('Press me'));
    +  expect(onPress).toHaveBeenCalled();
    +});
    +

    act is now async

    +

    In v14, act is now async by default and always returns a Promise. You should always await the result of act().

    +

    What changed:

    +
      +
    • act now always returns a Promise<T> instead of T | Thenable<T>
    • +
    • act should always be awaited
    • +
    • The API is more consistent and predictable
    • +
    +
    NOTE
    +

    The transition to async act may prevent testing very short transient states, as awaiting act will flush all pending updates before returning.

    +
    +

    Before (v13):

    +
    import { act } from '@testing-library/react-native';
    +
    +it('should update state', () => {
    +  act(() => {
    +    setState('new value');
    +  });
    +  expect(state).toBe('new value');
    +});
    +

    After (v14):

    +
    import { act } from '@testing-library/react-native';
    +
    +it('should update state', async () => {
    +  await act(() => {
    +    setState('new value');
    +  });
    +  expect(state).toBe('new value');
    +});
    +

    Note: Even if your callback is synchronous, you should still use await act(...) as act now always returns a Promise.

    +

    For more details, see the act API documentation.

    +

    Benefits of Async APIs

    +
      +
    • Suspense support: Properly handles Suspense boundaries and use() hook
    • +
    • Better timing: Ensures all pending React updates are executed before assertions
    • +
    • Simpler mental model: All rendering operations are consistently async
    • +
    • Future-proof: Aligns with React's direction toward async rendering
    • +
    +

    Removed APIs

    +

    update alias removed

    +

    The update alias for rerender has been removed. Use rerender instead:

    +
    // Before (v13)
    +screen.update(<MyComponent />);
    +const { update } = render(<MyComponent />);
    +update(<MyComponent newProp />);
    +
    +// After (v14)
    +await screen.rerender(<MyComponent />);
    +const { rerender } = await render(<MyComponent />);
    +await rerender(<MyComponent newProp />);
    +

    getQueriesForElement export removed

    +

    The getQueriesForElement export alias for within has been removed. Use within instead:

    +
    // Before (v13)
    +import { getQueriesForElement } from '@testing-library/react-native';
    +
    +const queries = getQueriesForElement(element);
    +
    +// After (v14)
    +import { within } from '@testing-library/react-native';
    +
    +const queries = within(element);
    +

    Note: getQueriesForElement was just an alias for within, so the functionality is identical - only the import needs to change.

    +

    UNSAFE_root removed

    +

    UNSAFE_root has been removed. Use container to access the pseudo-element container, or root to access the first rendered host element:

    +
    // Before (v13)
    +const unsafeRoot = screen.UNSAFE_root;
    +
    +// After (v14)
    +const container = screen.container; // pseudo-element container
    +const root = screen.root; // first rendered host element
    +

    Legacy UNSAFE_* queries removed

    +

    The legacy UNSAFE_getAllByType, UNSAFE_getByType, UNSAFE_getAllByProps, and UNSAFE_getByProps queries have been removed. These queries could return composite (user-defined) components, which is no longer supported with Test Renderer as it only renders host elements.

    +

    If you were using these legacy queries, you should refactor your tests to use the standard queries (getByRole, getByText, getByTestId, etc.) which target host elements.

    +
    // Before (v13)
    +const buttons = screen.UNSAFE_getAllByType(Button);
    +const input = screen.UNSAFE_getByProps({ placeholder: 'Enter text' });
    +
    +// After (v14)
    +const buttons = screen.getAllByRole('button');
    +const input = screen.getByPlaceholderText('Enter text');
    +

    concurrentRoot option removed

    +

    The concurrentRoot option has been removed from both render options and configure function. In v14, concurrent rendering is always enabled by default, as it is the standard rendering mode for React 19 and React Native's New Architecture.

    +
    // Before (v13)
    +render(<MyComponent />, { concurrentRoot: true });  // Enable concurrent mode
    +render(<MyComponent />, { concurrentRoot: false }); // Disable concurrent mode
    +configure({ concurrentRoot: false });               // Disable globally
    +
    +// After (v14)
    +await render(<MyComponent />); // Always uses concurrent rendering
    +

    Migration: Simply remove any concurrentRoot options from your render calls and configure function. If you were explicitly setting concurrentRoot: true, no changes are needed beyond removing the option. If you were setting concurrentRoot: false to disable concurrent rendering, this is no longer supported in v14.

    container API reintroduced

    In v14, the container API has been reintroduced and is now safe to use. Previously, container was renamed to UNSAFE_root in v12 due to behavioral differences from React Testing Library's container. In v14, container now returns a pseudo-element container whose children are the elements you asked to render, making it safe and consistent with React Testing Library's behavior.

    What changed:

    @@ -70,266 +266,8 @@ // root is the first child of container const root = screen.root; });
    -

    Migration:

    -

    If you were using UNSAFE_root, replace it with container:

    -
    // Before
    -const root = screen.UNSAFE_root;
    -
    -// After
    -const container = screen.container;
    -// Or use screen.root if you need the actual root element
    -const root = screen.root;

    For more details, see the screen API documentation.

    -

    render is now async by default

    -

    In v14, render is now async by default and returns a Promise. This change makes it compatible with React 19, React Suspense, and React.use().

    -

    Before (v13):

    -
    import { render, screen } from '@testing-library/react-native';
    -
    -it('should render component', () => {
    -  render(<MyComponent />);
    -  expect(screen.getByText('Hello')).toBeOnTheScreen();
    -});
    -

    After (v14):

    -
    import { render, screen } from '@testing-library/react-native';
    -
    -it('should render component', async () => {
    -  await render(<MyComponent />);
    -  expect(screen.getByText('Hello')).toBeOnTheScreen();
    -});
    -

    Step-by-step migration guide

    -

    To migrate from v13 render to v14 render:

    -
    1. Add async to your test function
    -
    // Before (v13)
    -it('should render component', () => {
    -
    -// After (v14)
    -it('should render component', async () => {
    -
    2. Await render
    -
    // Before
    -render(<MyComponent />);
    -
    -// After
    -await render(<MyComponent />);
    -
    3. Update rerender calls to await
    -
    // Before
    -screen.rerender(<MyComponent />);
    -
    -// After
    -await screen.rerender(<MyComponent />);
    -
    4. Replace update alias with rerender
    -

    The update alias for rerender has been removed in v14. If you were using screen.update() or renderer.update(), replace it with rerender():

    -
    // Before (v13)
    -screen.update(<MyComponent />);
    -// or
    -const { update } = render(<MyComponent />);
    -update(<MyComponent />);
    -
    -// After (v14)
    -await screen.rerender(<MyComponent />);
    -// or
    -const { rerender } = await render(<MyComponent />);
    -await rerender(<MyComponent />);
    -
    5. Update unmount calls to await
    -
    // Before
    -screen.unmount();
    -
    -// After
    -await screen.unmount();
    -

    Complete example

    -

    Before (v13):

    -
    import { render, screen } from '@testing-library/react-native';
    -
    -it('should update component', () => {
    -  render(<Counter initialCount={0} />);
    -  expect(screen.getByText('Count: 0')).toBeOnTheScreen();
    -
    -  screen.rerender(<Counter initialCount={5} />);
    -  expect(screen.getByText('Count: 5')).toBeOnTheScreen();
    -
    -  screen.unmount();
    -});
    -

    After (v14):

    -
    import { render, screen } from '@testing-library/react-native';
    -
    -it('should update component', async () => {
    -  await render(<Counter initialCount={0} />);
    -  expect(screen.getByText('Count: 0')).toBeOnTheScreen();
    -
    -  await screen.rerender(<Counter initialCount={5} />);
    -  expect(screen.getByText('Count: 5')).toBeOnTheScreen();
    -
    -  await screen.unmount();
    -});
    -

    Benefits of async render

    -
      -
    • React 19 compatibility: Works seamlessly with React 19's async features
    • -
    • Suspense support: Properly handles React Suspense boundaries and React.use()
    • -
    • Better timing: Ensures all pending React updates are executed before assertions
    • -
    • Future-proof: Aligns with React's direction toward async rendering
    • -
    -

    For more details, see the render API documentation.

    -

    update alias removed

    -

    In v14, the update alias for rerender has been removed. You must use rerender instead.

    -

    What changed:

    -
      -
    • screen.update() has been removed
    • -
    • renderer.update() has been removed
    • -
    • Only rerender is now available
    • -
    -

    Migration:

    -

    Replace all update calls with rerender:

    -
    // Before (v13)
    -screen.update(<MyComponent />);
    -// or
    -const { update } = render(<MyComponent />);
    -update(<MyComponent />);
    -
    -// After (v14)
    -await screen.rerender(<MyComponent />);
    -// or
    -const { rerender } = await render(<MyComponent />);
    -await rerender(<MyComponent />);
    -

    Note: This change is included in the step-by-step migration guide for async render above.

    -

    getQueriesForElement export removed

    -

    In v14, the getQueriesForElement export alias for within has been removed. You must use within instead.

    -

    What changed:

    -
      -
    • getQueriesForElement is no longer exported from the main package
    • -
    • within is the only exported function for scoped queries
    • -
    • getQueriesForElement remains available internally but is not part of the public API
    • -
    -

    Migration:

    -

    Replace all getQueriesForElement imports and usage with within:

    -
    // Before (v13)
    -import { getQueriesForElement } from '@testing-library/react-native';
    -
    -const queries = getQueriesForElement(element);
    -
    -// After (v14)
    -import { within } from '@testing-library/react-native';
    -
    -const queries = within(element);
    -

    Note: getQueriesForElement was just an alias for within, so the functionality is identical - only the import needs to change.

    -

    renderHook is now async by default

    -

    In v14, renderHook is now async by default and returns a Promise. This change makes it compatible with React 19, React Suspense, and React.use().

    -

    Before (v13):

    -
    import { renderHook } from '@testing-library/react-native';
    -
    -it('should test hook', () => {
    -  const { result, rerender } = renderHook(() => useMyHook());
    -
    -  rerender(newProps);
    -  unmount();
    -});
    -

    After (v14):

    -
    import { renderHook } from '@testing-library/react-native';
    -
    -it('should test hook', async () => {
    -  const { result, rerender } = await renderHook(() => useMyHook());
    -
    -  await rerender(newProps);
    -  await unmount();
    -});
    -

    Step-by-step migration guide

    -

    To migrate from v13 renderHook to v14 renderHook:

    -
    1. Add async to your test function
    -
    // Before
    -it('should test hook', () => {
    -
    -// After
    -it('should test hook', async () => {
    -
    2. Await renderHook
    -
    // Before (v13)
    -const { result } = renderHook(() => useMyHook());
    -
    -// After (v14)
    -const { result } = await renderHook(() => useMyHook());
    -
    3. Update rerender calls to await
    -
    // Before
    -rerender(newProps);
    -
    -// After
    -await rerender(newProps);
    -
    4. Update unmount calls to await
    -
    // Before
    -unmount();
    -
    -// After
    -await unmount();
    -
    6. Update act calls to use async act
    -
    // Before
    -act(() => {
    -  result.current.doSomething();
    -});
    -
    -// After
    -await act(async () => {
    -  result.current.doSomething();
    -});
    -

    Complete example

    -

    Before (v13):

    -
    import { renderHook, act } from '@testing-library/react-native';
    -
    -it('should increment count', () => {
    -  const { result, rerender } = renderHook((initialCount: number) => useCount(initialCount), {
    -    initialProps: 1,
    -  });
    -
    -  expect(result.current.count).toBe(1);
    -
    -  act(() => {
    -    result.current.increment();
    -  });
    -
    -  expect(result.current.count).toBe(2);
    -  rerender(5);
    -  expect(result.current.count).toBe(5);
    -});
    -

    After (v14):

    -
    import { renderHook, act } from '@testing-library/react-native';
    -
    -it('should increment count', async () => {
    -  const { result, rerender } = await renderHook((initialCount: number) => useCount(initialCount), {
    -    initialProps: 1,
    -  });
    -
    -  expect(result.current.count).toBe(1);
    -
    -  await act(async () => {
    -    result.current.increment();
    -  });
    -
    -  expect(result.current.count).toBe(2);
    -  await rerender(5);
    -  expect(result.current.count).toBe(5);
    -});
    -

    Benefits of async renderHook

    -
      -
    • React 19 compatibility: Works seamlessly with React 19's async features
    • -
    • Suspense support: Properly handles React Suspense boundaries and React.use()
    • -
    • Better timing: Ensures all pending React updates are executed before assertions
    • -
    • Future-proof: Aligns with React's direction toward async rendering
    • -
    -

    For more details, see the renderHook API documentation.

    -

    fireEvent is now async by default

    -

    In v14, fireEvent and its helpers (press, changeText, scroll) are now async by default and return a Promise. This change makes it compatible with React 19, React Suspense, and React.use().

    -

    Before (v13):

    -
    import { fireEvent, screen } from '@testing-library/react-native';
    -
    -it('should press button', () => {
    -  render(<MyComponent />);
    -  fireEvent.press(screen.getByText('Press me'));
    -  expect(onPress).toHaveBeenCalled();
    -});
    -

    After (v14):

    -
    import { fireEvent, screen } from '@testing-library/react-native';
    -
    -it('should press button', async () => {
    -  render(<MyComponent />);
    -  await fireEvent.press(screen.getByText('Press me'));
    -  expect(onPress).toHaveBeenCalled();
    -});
    -

    Text string validation now enforced by default

    +

    Text string validation enforced by default

    In v14, Test Renderer automatically enforces React Native's requirement that text strings must be rendered within a <Text> component. This means the unstable_validateStringsRenderedWithinText option has been removed from RenderOptions, as this validation is now always enabled.

    What changed:

      @@ -340,7 +278,7 @@

      Migration:

      If you were using unstable_validateStringsRenderedWithinText: true in your render options, you can simply remove this option as the validation is now always enabled:

      // Before (v13)
      -await render(<MyComponent />, {
      +render(<MyComponent />, {
         unstable_validateStringsRenderedWithinText: true,
       });
       
      @@ -348,104 +286,38 @@
       await render(<MyComponent />);
       // Validation is now always enabled

      If you were relying on the previous behavior where strings could be rendered outside of <Text> components, you'll need to fix your components to wrap strings in <Text> components, as this matches React Native's actual runtime behavior.

      -

      act is now async by default

      -

      In v14, act is now async by default and always returns a Promise. This change makes it compatible with React 19, React Suspense, and React.use().

      -

      What changed:

      +

      Codemods

      +

      We provide two codemods to automate the migration. Both codemods are safe to run multiple times - they will only transform code that hasn't been migrated yet.

      +

      rntl-v14-update-deps

      +

      Updates your package.json:

        -
      • act now always returns a Promise<T> instead of T | Thenable<T>
      • -
      • act is now a named export (no default export)
      • +
      • Removes React Test Renderer (react-test-renderer and @types/react-test-renderer)
      • +
      • Adds Test Renderer (test-renderer)
      • +
      • Updates @testing-library/react-native to ^14.0.0
      -

      Before (v13):

      -
      import act from '@testing-library/react-native';
      -
      -it('should update state', () => {
      -  act(() => {
      -    // Synchronous callback
      -    setState('new value');
      -  });
      -  // act could return synchronously or a thenable
      -  expect(state).toBe('new value');
      -});
      -

      After (v14):

      -
      import { act } from '@testing-library/react-native';
      -
      -it('should update state', async () => {
      -  await act(async () => {
      -    // Callback can be sync or async
      -    setState('new value');
      -  });
      -  // act always returns a Promise
      -  expect(state).toBe('new value');
      -});
      -

      Step-by-step migration guide

      -

      To migrate from v13 act to v14 act:

      -
      1. Update import statement
      -
      // Before
      -import act from '@testing-library/react-native';
      -
      -// After
      -import { act } from '@testing-library/react-native';
      -
      2. Add async to your test function
      -
      // Before
      -it('should update state', () => {
      -
      -// After
      -it('should update state', async () => {
      -
      3. Await act calls
      -
      // Before
      -act(() => {
      -  setState('new value');
      -});
      -
      -// After
      -await act(async () => {
      -  setState('new value');
      -});
      -

      Note: Even if your callback is synchronous, you should still use await act(async () => ...) as act now always returns a Promise.

      -

      Complete example

      -

      Before (v13):

      -
      import act from '@testing-library/react-native';
      -
      -it('should update state synchronously', () => {
      -  act(() => {
      -    setState('new value');
      -  });
      -  expect(state).toBe('new value');
      -});
      -
      -it('should update state asynchronously', () => {
      -  act(async () => {
      -    await Promise.resolve();
      -    setState('new value');
      -  }).then(() => {
      -    expect(state).toBe('new value');
      -  });
      -});
      -

      After (v14):

      -
      import { act } from '@testing-library/react-native';
      -
      -it('should update state synchronously', async () => {
      -  await act(async () => {
      -    setState('new value');
      -  });
      -  expect(state).toBe('new value');
      -});
      -
      -it('should update state asynchronously', async () => {
      -  await act(async () => {
      -    await Promise.resolve();
      -    setState('new value');
      -  });
      -  expect(state).toBe('new value');
      -});
      -

      Benefits of async act

      +
      npm
      yarn
      pnpm
      bun
      npx codemod@latest rntl-v14-update-deps --target .
      +npm install
      +

      rntl-v14-async-functions

      +

      Transforms test files:

        -
      • React 19 compatibility: Works seamlessly with React 19's async features
      • -
      • Suspense support: Properly handles React Suspense boundaries and React.use()
      • -
      • Consistent API: Always returns a Promise, making the API more predictable
      • -
      • Future-proof: Aligns with React's direction toward async rendering
      • +
      • Adds await to render(), act(), renderHook(), fireEvent() calls
      • +
      • Makes test functions async when needed
      • +
      • Handles screen.rerender(), screen.unmount(), and renderer methods
      -

      For more details, see the act API documentation.

    +
    npm
    yarn
    pnpm
    bun
    npx codemod@latest rntl-v14-async-functions --target ./src
    +

    Custom render functions

    +

    If you have custom render helpers (like renderWithProviders), you can specify them using the customRenderFunctions parameter. The codemod will then also transform calls to these functions:

    +
    npm
    yarn
    pnpm
    bun
    npx codemod@latest rntl-v14-async-functions \
    +  --target ./src \
    +  --param customRenderFunctions="renderWithProviders,renderWithTheme"
    +

    This will add await to your custom render calls and make the containing test functions async, just like it does for the standard render function.

    +

    Limitations

    +
      +
    • Helper functions defined in test files are not transformed by default
    • +
    • Namespace imports (import * as RNTL) are not handled
    • +
    +

    Full Changelog

    +

    https://github.com/callstack/react-native-testing-library/compare/v13.3.3...v14.0.0

    diff --git a/14.x/docs/migration/previous/v2.html b/14.x/docs/migration/v2.html similarity index 56% rename from 14.x/docs/migration/previous/v2.html rename to 14.x/docs/migration/v2.html index 3ae2b9a5..ab72b1ad 100644 --- a/14.x/docs/migration/previous/v2.html +++ b/14.x/docs/migration/v2.html @@ -6,10 +6,10 @@ Migration to 2.x - React Native Testing Library - + -

    Migration to 2.x

    +

    Migration to 2.x

    This guide describes steps necessary to migrate from React Native Testing Library v1.x to v2.x.

    Dropping Node 8

    Node 8 reached its EOL more than 5 months ago, so it's about time to target the library to Node 10. If you used lower version, you'll have to upgrade to v10, but we recommend using the latest LTS version.

    @@ -95,7 +95,7 @@

    If you can't or don't want to migrate your tests, don't worry. You can use the same implementation we have today:

    function flushMicrotasksQueue() {
       return new Promise((resolve) => setImmediate(resolve));
    -}
    +}
    diff --git a/14.x/docs/migration/v7.html b/14.x/docs/migration/v7.html new file mode 100644 index 00000000..8afdcf02 --- /dev/null +++ b/14.x/docs/migration/v7.html @@ -0,0 +1,87 @@ + + + + + + + + Migration to 7.x - React Native Testing Library + + + +

    Migration to 7.x

    +
    INFO
    +

    We renamed the react-native-testing-library npm package to @testing-library/react-native, officially joining the "Testing Library" family πŸŽ‰.

    +
    +

    As the version 7.0 involves merging two libraries together, there are two variants for migration guide, dependent on library you used previously:

    +

    Guide for react-native-testing-library users

    +

    This guide describes steps necessary to migrate from React Native Testing Library v2.x or v6.0 to v7.0.

    +

    Renaming the library

    +
      +
    1. Install @testing-library/react-native.
    2. +
    3. Uninstall react-native-testing-library.
    4. +
    5. Rename all references of react-native-testing-library to @testing-library/react-native.
    6. +
    +

    You may have noticed a strange v2 to v7 upgrade, skipping versions 3, 4, 5 and 6. This is because we renamed the react-native-testing-library npm package to @testing-library/react-native, officially joining the "Testing Library" family πŸŽ‰. We're merging existing two libraries into a single one. The native-testing-library repository, which had v6, will soon be archived and using @testing-library/react-native below v7, sourced from mentioned repository, is deprecated.

    +

    For branding purposes we keep the "React Native Testing Library" name, similar to "React Testing Library". Only the npm published package is changing. The code repository also stays the same under Callstack governance.

    +

    New aliases

    +

    To improve compatibility with React Testing Library, and ease the migration for @testing-library/react-native users using version below v7, we've introduced new aliases to our accessibility queries:

    +
      +
    • ByLabelText aliasing ByA11yLabel queries
    • +
    • ByHintText aliasing ByA11yHint queries
    • +
    • ByRole aliasing ByA11yRole queries
    • +
    +

    We like the new names and consider removing the aliases in future releases.

    +

    Renaming ByPlaceholder queries

    +

    To improve compatibility with React Testing Library, and to ease the migration for @testing-library/react-native users using version below v7, we've renamed following queries:

    +
      +
    • ByPlaceholder -> ByPlaceholderText
    • +
    +

    Please replace all occurrences of these queries in your codebase.

    +

    fireEvent support for disabled components

    +

    To improve compatibility with the real React Native environment fireEvent now performs checks whether the component is "disabled" before firing an event on it. It uses the Responder system to establish should the event fire, which resembles the actual React Native runtime closer than we used to.

    +

    If your code contained any workarounds for preventing events firing on disabled events, you should now be able to remove them.

    +

    Guide for @testing-library/react-native users

    +

    This guide describes steps necessary to migrate from @testing-library/react-native from v6.0 to v7.0. Although the name stays the same, this is a different library, sourced at Callstack GitHub repository. We made sure the upgrade path is as easy for you as possible.

    +

    Renaming "wait" helpers

    +

    The wait and waitForElement helpers are replaced by waitFor. Please rename all occurrences of these in your codebase.

    +

    Changes to ByTestId queries

    +

    The ByTestId queries don't accept RegExps. Please use strings instead. We're happy to accept PRs adding this functionality :).

    +

    No ByTitle queries

    +

    Our library doesn't implement ByTitle queries, which are targetting components with title prop, specifically Button and RefreshControl. If your tests only use ByTitle to target Button components, you can replace them with ByText queries, since React Native renders Text under the hood.

    +

    If you need to query RefreshControl component and can't figure out other way around it, you can use e.g. UNSAFE_getByProps({title}) query.

    +

    No custom Jest configuration

    +

    Use the official React Native preset for Jest:

    +
    {
    +  "jest": {
    +-    "preset": "@testing-library/react-native"
    ++    "preset": "react-native"
    +  }
    +}
    +

    We're told this also speeds up your tests startup on cold cache. Using official preset has another benefit – the library is compatible with any version of React Native without introducing breaking changes.

    +

    Cleanup is included by default

    +

    Cleaning up (unmounting) components after each test is included by default in the same manner as in React Testing Library. Please remove this setup file from Jest config:

    +
    {
    +  "jest": {
    +-    "setupFilesAfterEnv": ["@testing-library/react-native/cleanup-after-each"]
    +  }
    +}
    +

    You can opt-out of this behavior by running tests with RNTL_SKIP_AUTO_CLEANUP=true flag or importing from @testing-library/react-native/pure. We encourage you to keep the default though.

    +

    No NativeTestInstance abstraction

    +

    We don't provide any abstraction over HostElement returned by queries, but allow to use it directly to access queried component's props or type for that example.

    +

    No container nor baseElement returned from render

    +

    There's no container returned from the render function. If you must, use react-test-renderer directly, although we advise against doing so. We also don't implement baseElement because of that, since there's no document.documentElement nor container.

    +

    Firing events changes

    +

    There are slight differences in how fireEvent works in both libraries:

    +
      +
    1. Our library doesn't perform validation checks for events fired upon tested components.
    2. +
    3. Signature is different: +
      -fireEvent[eventName](node: FiberRoot, eventProperties: NativeTestEvent)
      ++fireEvent(element: HostElement, eventName: string, ...data: Array<any>)
      +
    4. +
    5. There is no NativeTestEvent - second and rest arguments are used instead.
    6. +
    7. There are only 3 short-hand events: fireEvent.press, fireEvent.changeText and fireEvent.scroll. For all other or custom events you can use the base signature.
    8. +
    +
    + + diff --git a/14.x/docs/migration/v9.html b/14.x/docs/migration/v9.html new file mode 100644 index 00000000..3bdc004d --- /dev/null +++ b/14.x/docs/migration/v9.html @@ -0,0 +1,49 @@ + + + + + + + + Migration to 9.x - React Native Testing Library + + + +

    Migration to 9.x

    +

    Version 7.0 brought React Native Testing Library into the @testing-library family. Since it has been implemented independently from its web counterpart – the React Testing Library – there are some differences in the API and behavior. Version 9.0 solves several of these problems.

    +

    Support for text match options a.k.a string precision API

    +

    This is a backward compatible change.

    +

    When querying text, it is now possible to pass a TextMatch to most text based queries, which lets you configure how @testing-library/react-native should match your text. For instance, passing exact: false will allow matching substrings and will ignore case:

    +
    const { getByText } = render(<Text>Hello World</Text>);
    +
    +getByText('Hello World'); // Matches
    +getByText('Hello'); // Doesn't match
    +getByText('hello', { exact: false }); // ignore case-sensitivity and does partial matching
    +

    Please note that the findBy* queries used to take a waitForOptions parameter as a second argument, which has now been moved to the third argument:

    +
    -findByText('Hello world', { timeout: 3000 }); // old findBy* API
    ++findByText('Hello world', {}, { timeout: 3000 }); // new findBy* API
    +

    For backward compatibility RNTL v9 can still read waitForOptions from the second argument but will print a deprecation warning.

    +

    Reverted matching text across several nodes

    +
    CAUTION

    This is a breaking change.

    +

    In v1.14 we've introduced a feature allowing to match text when it's spread across several nodes:

    +
    const { getByText } = render(
    +  <Text>
    +    Hello <Text>world</Text>
    +  </Text>
    +);
    +getByText('Hello world'); // matches
    +

    However this behavior was different than the web one, and wouldn't always be straightforward to reason about. For instance it could match text nodes far from each other on the screen. It also prevented us from implementing the string precision API. From v9, this type of match will not work.

    +

    A work around is to use within:

    +
    import { Text } from 'react-native'
    +import { render, within } from '@testing-library/react-native'
    +
    +const { getByText } = render(<Text>Hello <Text>world</Text</Text>)
    +
    +within(getByText('Hello', {exact: false})).getByText('world')
    +

    Future plans

    +

    This release changes a lot of internal logic in the library, paving the way for more improvements to bring us closer to our web counterpart, with a possibly better story for accessibility queries.

    +

    We're also migrating the codebase to TypeScript. Please let us know if you're interested in helping us with this effort.

    +

    Stay safe!

    +
    + + diff --git a/14.x/docs/start/intro.html b/14.x/docs/start/intro.html index 7161e983..e459408e 100644 --- a/14.x/docs/start/intro.html +++ b/14.x/docs/start/intro.html @@ -6,14 +6,14 @@ Introduction - React Native Testing Library - + -

    Introduction

    +

    Introduction

    The problem

    You want to write maintainable tests for your React Native components. As a part of this goal, you want your tests to avoid including implementation details of your components and focus on making your tests give you the confidence they are intended. As part of this, you want your tests to be maintainable in the long run so refactors of your components (changes to implementation but not functionality) don't break your tests and slow you and your team down.

    This solution

    -

    The React Native Testing Library (RNTL) is a lightweight solution for testing React Native components. It provides light utility functions on top of Test Renderer, in a way that encourages better testing practices. Its primary guiding principle is:

    +

    The React Native Testing Library (RNTL) is a comprehensive solution for testing React Native components. It provides React Native runtime simulation on top of Test Renderer, in a way that encourages better testing practices. Its primary guiding principle is:

    The more your tests resemble how your software is used, the more confidence they can give you.

    @@ -27,7 +27,7 @@ const onSubmit = jest.fn(); const user = userEvent.setup(); - render(<QuestionsBoard questions={questions} onSubmit={onSubmit} />); + await render(<QuestionsBoard questions={questions} onSubmit={onSubmit} />); const answerInputs = screen.getAllByLabelText('answer input'); await user.type(answerInputs[0], 'a1'); diff --git a/14.x/docs/start/quick-start.html b/14.x/docs/start/quick-start.html index 50aa6455..3eddf10e 100644 --- a/14.x/docs/start/quick-start.html +++ b/14.x/docs/start/quick-start.html @@ -6,20 +6,22 @@ Quick Start - React Native Testing Library - + -

    Quick Start

    +

    Quick Start

    Installation

    Open a Terminal in your project's folder and run:

    -
    yarn
    npm
    yarn add -D @testing-library/react-native
    -

    This library uses Test Renderer as its underlying rendering engine. Test Renderer is automatically installed as a dependency and provides better compatibility with React 19 and improved type safety compared to the deprecated react-test-renderer package.

    +
    npm
    yarn
    pnpm
    bun
    npm install -D @testing-library/react-native
    +

    This library has a peer dependency on Test Renderer. Make sure to install it:

    +
    npm
    yarn
    pnpm
    bun
    npm install -D test-renderer
    +

    Test Renderer provides better compatibility with React 19 and improved type safety compared to the deprecated React Test Renderer.

    Jest matchers

    -

    RNTL v13 automatically extends Jest with React Native-specific matchers. The only thing you need to do is to import anything from @testing-library/react-native which you already need to do to access the render function.

    +

    RNTL automatically extends Jest with React Native-specific matchers. The only thing you need to do is to import anything from @testing-library/react-native which you already need to do to access the render function.

    ESLint plugin

    We recommend setting up eslint-plugin-testing-library package to help you avoid common Testing Library mistakes and bad practices.

    Install the plugin (assuming you already have eslint installed & configured):

    -
    yarn
    npm
    yarn add -D eslint-plugin-testing-library
    +
    npm
    yarn
    pnpm
    bun
    npm install -D eslint-plugin-testing-library

    Then, add relevant entry to your ESLint config (e.g., .eslintrc.js). We recommend extending the react plugin:

    .eslintrc.js
    module.exports = {
       overrides: [
    @@ -29,7 +31,7 @@
           extends: ['plugin:testing-library/react'],
         },
       ],
    -};
    +};
    diff --git a/14.x/index.html b/14.x/index.html index 10386c9b..d422b740 100644 --- a/14.x/index.html +++ b/14.x/index.html @@ -6,7 +6,7 @@ React Native Testing Library - +

    React Native

    Testing Library

    Helps you to write better tests with less effort.

    ✨

    Maintainable

    Write maintainable tests for your React Native apps.

    βœ…

    Reliable

    Promotes testing public APIs and avoiding implementation details.

    ❀️

    Community Driven

    Supported by React Native community and its core contributors.

    Copyright Β© 2026 Callstack Open Source
    diff --git a/404.html b/404.html index 05fd49e9..fdac072c 100644 --- a/404.html +++ b/404.html @@ -6,7 +6,7 @@ React Native Testing Library - + diff --git a/cookbook/advanced/network-requests.html b/cookbook/advanced/network-requests.html index 6496104f..881ecdd7 100644 --- a/cookbook/advanced/network-requests.html +++ b/cookbook/advanced/network-requests.html @@ -6,7 +6,7 @@ Network Requests - React Native Testing Library - +

    Network Requests

    diff --git a/cookbook/basics/async-tests.html b/cookbook/basics/async-tests.html index d31df8c2..68a5e002 100644 --- a/cookbook/basics/async-tests.html +++ b/cookbook/basics/async-tests.html @@ -6,7 +6,7 @@ Async tests - React Native Testing Library - +

    Async tests

    diff --git a/cookbook/basics/custom-render.html b/cookbook/basics/custom-render.html index ca8408b9..a6465646 100644 --- a/cookbook/basics/custom-render.html +++ b/cookbook/basics/custom-render.html @@ -6,7 +6,7 @@ Custom `render` function - React Native Testing Library - +

    Custom render function

    diff --git a/cookbook/index.html b/cookbook/index.html index 9faa2b2a..d5ee3a09 100644 --- a/cookbook/index.html +++ b/cookbook/index.html @@ -6,7 +6,7 @@ Introduction - React Native Testing Library - +

    Introduction

    diff --git a/cookbook/state-management/jotai.html b/cookbook/state-management/jotai.html index 4cb69672..c09f1d02 100644 --- a/cookbook/state-management/jotai.html +++ b/cookbook/state-management/jotai.html @@ -6,7 +6,7 @@ Jotai - React Native Testing Library - +

    Jotai

    diff --git a/docs/advanced/testing-env.html b/docs/advanced/testing-env.html index 76bdd962..914867ba 100644 --- a/docs/advanced/testing-env.html +++ b/docs/advanced/testing-env.html @@ -6,7 +6,7 @@ Testing environment - React Native Testing Library - +

    Testing environment

    diff --git a/docs/advanced/third-party-integration.html b/docs/advanced/third-party-integration.html index b4ce262c..c00dc576 100644 --- a/docs/advanced/third-party-integration.html +++ b/docs/advanced/third-party-integration.html @@ -6,7 +6,7 @@ Third-Party Library Integration - React Native Testing Library - +

    Third-Party Library Integration

    diff --git a/docs/advanced/understanding-act.html b/docs/advanced/understanding-act.html index cbe729b6..a9043c12 100644 --- a/docs/advanced/understanding-act.html +++ b/docs/advanced/understanding-act.html @@ -6,7 +6,7 @@ Understanding `act` function - React Native Testing Library - +

    Understanding act function

    diff --git a/docs/api.html b/docs/api.html index 33b7a796..9e4eb47b 100644 --- a/docs/api.html +++ b/docs/api.html @@ -6,7 +6,7 @@ API Overview - React Native Testing Library - +

    API Overview

    diff --git a/docs/api/events/fire-event.html b/docs/api/events/fire-event.html index 964166b3..8f8da29d 100644 --- a/docs/api/events/fire-event.html +++ b/docs/api/events/fire-event.html @@ -6,7 +6,7 @@ Fire Event API - React Native Testing Library - +

    Fire Event API

    diff --git a/docs/api/events/user-event.html b/docs/api/events/user-event.html index 0b84b0ca..712803e6 100644 --- a/docs/api/events/user-event.html +++ b/docs/api/events/user-event.html @@ -6,7 +6,7 @@ User Event interactions - React Native Testing Library - +

    User Event interactions

    diff --git a/docs/api/jest-matchers.html b/docs/api/jest-matchers.html index d46d16ee..e539e7ee 100644 --- a/docs/api/jest-matchers.html +++ b/docs/api/jest-matchers.html @@ -6,7 +6,7 @@ Jest matchers - React Native Testing Library - +

    Jest matchers

    diff --git a/docs/api/misc/accessibility.html b/docs/api/misc/accessibility.html index 0b7db437..b13a3df5 100644 --- a/docs/api/misc/accessibility.html +++ b/docs/api/misc/accessibility.html @@ -6,7 +6,7 @@ Accessibility - React Native Testing Library - +

    Accessibility

    diff --git a/docs/api/misc/async.html b/docs/api/misc/async.html index 4996cea0..74fc9667 100644 --- a/docs/api/misc/async.html +++ b/docs/api/misc/async.html @@ -6,7 +6,7 @@ Async utilities - React Native Testing Library - +

    Async utilities

    diff --git a/docs/api/misc/config.html b/docs/api/misc/config.html index edfaac38..12568d57 100644 --- a/docs/api/misc/config.html +++ b/docs/api/misc/config.html @@ -6,7 +6,7 @@ Configuration - React Native Testing Library - +

    Configuration

    diff --git a/docs/api/misc/other.html b/docs/api/misc/other.html index cca69617..e04eb43e 100644 --- a/docs/api/misc/other.html +++ b/docs/api/misc/other.html @@ -6,7 +6,7 @@ Other helpers - React Native Testing Library - +

    Other helpers

    diff --git a/docs/api/misc/render-hook.html b/docs/api/misc/render-hook.html index 8a26be49..52c62569 100644 --- a/docs/api/misc/render-hook.html +++ b/docs/api/misc/render-hook.html @@ -6,7 +6,7 @@ `renderHook` function - React Native Testing Library - +

    renderHook function

    diff --git a/docs/api/queries.html b/docs/api/queries.html index c1b8321d..bb60593d 100644 --- a/docs/api/queries.html +++ b/docs/api/queries.html @@ -6,7 +6,7 @@ Queries - React Native Testing Library - +

    Queries

    diff --git a/docs/api/render.html b/docs/api/render.html index 6d4812f9..71af2ab0 100644 --- a/docs/api/render.html +++ b/docs/api/render.html @@ -6,7 +6,7 @@ `render` API - React Native Testing Library - +

    render API

    diff --git a/docs/api/screen.html b/docs/api/screen.html index bd01fdb2..642706f0 100644 --- a/docs/api/screen.html +++ b/docs/api/screen.html @@ -6,7 +6,7 @@ `screen` object - React Native Testing Library - +

    screen object

    diff --git a/docs/guides/community-resources.html b/docs/guides/community-resources.html index 6ccc7478..732659c6 100644 --- a/docs/guides/community-resources.html +++ b/docs/guides/community-resources.html @@ -6,7 +6,7 @@ Community resources - React Native Testing Library - +

    Community resources

    diff --git a/docs/guides/faq.html b/docs/guides/faq.html index ae9de830..f50ff124 100644 --- a/docs/guides/faq.html +++ b/docs/guides/faq.html @@ -6,7 +6,7 @@ FAQ - React Native Testing Library - +

    FAQ

    diff --git a/docs/guides/how-to-query.html b/docs/guides/how-to-query.html index 40bf6000..48814369 100644 --- a/docs/guides/how-to-query.html +++ b/docs/guides/how-to-query.html @@ -6,7 +6,7 @@ How should I query? - React Native Testing Library - +

    How should I query?

    diff --git a/docs/guides/react-19.html b/docs/guides/react-19.html index 73bc6d3b..9c006cfb 100644 --- a/docs/guides/react-19.html +++ b/docs/guides/react-19.html @@ -6,7 +6,7 @@ React 19 & Suspense Support - React Native Testing Library - +

    React 19 & Suspense Support

    diff --git a/docs/guides/troubleshooting.html b/docs/guides/troubleshooting.html index 862615cd..c76298c9 100644 --- a/docs/guides/troubleshooting.html +++ b/docs/guides/troubleshooting.html @@ -6,7 +6,7 @@ Troubleshooting - React Native Testing Library - +

    Troubleshooting

    diff --git a/docs/migration/jest-matchers.html b/docs/migration/jest-matchers.html index d4dbd9af..af54a423 100644 --- a/docs/migration/jest-matchers.html +++ b/docs/migration/jest-matchers.html @@ -6,7 +6,7 @@ Migration to built-in Jest matchers - React Native Testing Library - +

    Migration to built-in Jest matchers

    diff --git a/docs/migration/previous/v11.html b/docs/migration/previous/v11.html index fd6918d6..19fa4f3e 100644 --- a/docs/migration/previous/v11.html +++ b/docs/migration/previous/v11.html @@ -6,7 +6,7 @@ Migration to 11.x - React Native Testing Library - +

    Migration to 11.x

    diff --git a/docs/migration/previous/v12.html b/docs/migration/previous/v12.html index d230c773..c0e2a4f1 100644 --- a/docs/migration/previous/v12.html +++ b/docs/migration/previous/v12.html @@ -6,7 +6,7 @@ Migration to 12.x - React Native Testing Library - +

    Migration to 12.x

    diff --git a/docs/migration/previous/v2.html b/docs/migration/previous/v2.html index f3f2f68d..ff40e85c 100644 --- a/docs/migration/previous/v2.html +++ b/docs/migration/previous/v2.html @@ -6,7 +6,7 @@ Migration to 2.x - React Native Testing Library - +

    Migration to 2.x

    diff --git a/docs/migration/previous/v7.html b/docs/migration/previous/v7.html index 396bc5c4..94e562f8 100644 --- a/docs/migration/previous/v7.html +++ b/docs/migration/previous/v7.html @@ -6,7 +6,7 @@ Migration to 7.x - React Native Testing Library - +

    Migration to 7.x

    diff --git a/docs/migration/previous/v9.html b/docs/migration/previous/v9.html index 0fadb24e..0ed7a64b 100644 --- a/docs/migration/previous/v9.html +++ b/docs/migration/previous/v9.html @@ -6,7 +6,7 @@ Migration to 9.x - React Native Testing Library - +

    Migration to 9.x

    diff --git a/docs/migration/v13.html b/docs/migration/v13.html index 99d674d4..d4346d9a 100644 --- a/docs/migration/v13.html +++ b/docs/migration/v13.html @@ -6,7 +6,7 @@ Migration to 13.x - React Native Testing Library - +

    Migration to 13.x

    diff --git a/docs/start/intro.html b/docs/start/intro.html index a790296c..0f8cc989 100644 --- a/docs/start/intro.html +++ b/docs/start/intro.html @@ -6,7 +6,7 @@ Introduction - React Native Testing Library - +

    Introduction

    diff --git a/docs/start/quick-start.html b/docs/start/quick-start.html index 5bf1d169..f1b9dbd7 100644 --- a/docs/start/quick-start.html +++ b/docs/start/quick-start.html @@ -6,7 +6,7 @@ Quick Start - React Native Testing Library - +

    Quick Start

    diff --git a/index.html b/index.html index e48d96d4..9052082b 100644 --- a/index.html +++ b/index.html @@ -6,7 +6,7 @@ React Native Testing Library - +

    React Native

    Testing Library

    Helps you to write better tests with less effort.

    ✨

    Maintainable

    Write maintainable tests for your React Native apps.

    βœ…

    Reliable

    Promotes testing public APIs and avoiding implementation details.

    ❀️

    Community Driven

    Supported by React Native community and its core contributors.

    Copyright Β© 2026 Callstack Open Source
    diff --git a/static/js/2179.4246b248.js b/static/js/2179.4246b248.js new file mode 100644 index 00000000..feae92ac --- /dev/null +++ b/static/js/2179.4246b248.js @@ -0,0 +1,6 @@ +/*! For license information please see 2179.4246b248.js.LICENSE.txt */ +(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["2179"],{436:function(e,t,n){"use strict";n.d(t,{ri:()=>tu,LX:()=>tm,E9:()=>tb,R0:()=>td,Vi:()=>tD,i6:()=>tg,TH:()=>tk,AP:()=>tf,s0:()=>tI,pV:()=>tp,yv:()=>tx,pJ:()=>tA,VK:()=>tl,aw:()=>tE,Ni:()=>th,Jr:()=>tw,Tm:()=>tv,iP:()=>tF,VY:()=>tc,Ww:()=>ty});var r=n(7294),i=n(3935);let a=(0,r.createContext)({}),o=(0,r.createContext)({});var s=n(5893),l=n(9250),c=n(5378),d=n(3040);let u=(0,d.lazyWithPreload)(()=>n.e("5123").then(n.bind(n,6080))),h=(0,d.lazyWithPreload)(()=>n.e("7654").then(n.bind(n,403))),p=(0,d.lazyWithPreload)(()=>n.e("7824").then(n.bind(n,3986))),x=(0,d.lazyWithPreload)(()=>n.e("6703").then(n.bind(n,6528))),m=(0,d.lazyWithPreload)(()=>n.e("7221").then(n.bind(n,377))),f=(0,d.lazyWithPreload)(()=>n.e("6112").then(n.bind(n,2875))),g=(0,d.lazyWithPreload)(()=>n.e("9538").then(n.bind(n,5845))),v=(0,d.lazyWithPreload)(()=>n.e("2276").then(n.bind(n,1544))),y=(0,d.lazyWithPreload)(()=>n.e("8274").then(n.bind(n,1644))),b=(0,d.lazyWithPreload)(()=>n.e("5190").then(n.bind(n,2029))),w=(0,d.lazyWithPreload)(()=>n.e("7956").then(n.bind(n,6227))),k=(0,d.lazyWithPreload)(()=>n.e("1995").then(n.bind(n,8216))),I=(0,d.lazyWithPreload)(()=>n.e("3875").then(n.bind(n,5098))),D=(0,d.lazyWithPreload)(()=>n.e("1912").then(n.bind(n,4721))),E=(0,d.lazyWithPreload)(()=>n.e("9422").then(n.bind(n,817))),F=(0,d.lazyWithPreload)(()=>n.e("2540").then(n.bind(n,7683))),A=(0,d.lazyWithPreload)(()=>n.e("1732").then(n.bind(n,9802))),C=(0,d.lazyWithPreload)(()=>n.e("7458").then(n.bind(n,1698))),j=(0,d.lazyWithPreload)(()=>n.e("6307").then(n.bind(n,7623))),P=(0,d.lazyWithPreload)(()=>n.e("3551").then(n.bind(n,6842))),S=(0,d.lazyWithPreload)(()=>n.e("8318").then(n.bind(n,7798))),T=(0,d.lazyWithPreload)(()=>n.e("1399").then(n.bind(n,9424))),N=(0,d.lazyWithPreload)(()=>n.e("238").then(n.bind(n,6601))),_=(0,d.lazyWithPreload)(()=>n.e("2829").then(n.bind(n,3834))),B=(0,d.lazyWithPreload)(()=>n.e("820").then(n.bind(n,301))),O=(0,d.lazyWithPreload)(()=>n.e("8841").then(n.bind(n,4310))),R=(0,d.lazyWithPreload)(()=>n.e("9806").then(n.bind(n,7787))),q=(0,d.lazyWithPreload)(()=>n.e("9862").then(n.bind(n,8108))),L=(0,d.lazyWithPreload)(()=>n.e("9322").then(n.bind(n,3513))),M=(0,d.lazyWithPreload)(()=>n.e("2299").then(n.bind(n,1801))),z=(0,d.lazyWithPreload)(()=>n.e("2640").then(n.bind(n,3873))),H=(0,d.lazyWithPreload)(()=>n.e("9716").then(n.bind(n,2154))),$=(0,d.lazyWithPreload)(()=>n.e("9437").then(n.bind(n,751))),W=(0,d.lazyWithPreload)(()=>n.e("4877").then(n.bind(n,4718))),K=(0,d.lazyWithPreload)(()=>n.e("5363").then(n.bind(n,8924))),U=(0,d.lazyWithPreload)(()=>n.e("4607").then(n.bind(n,3871))),V=(0,d.lazyWithPreload)(()=>n.e("1034").then(n.bind(n,8365))),G=(0,d.lazyWithPreload)(()=>n.e("4979").then(n.bind(n,8335))),Z=(0,d.lazyWithPreload)(()=>n.e("6791").then(n.bind(n,1997))),J=(0,d.lazyWithPreload)(()=>n.e("2721").then(n.bind(n,1564))),Q=(0,d.lazyWithPreload)(()=>n.e("7401").then(n.bind(n,4785))),Y=(0,d.lazyWithPreload)(()=>n.e("521").then(n.bind(n,6083))),X=(0,d.lazyWithPreload)(()=>n.e("5010").then(n.bind(n,7300))),ee=(0,d.lazyWithPreload)(()=>n.e("8186").then(n.bind(n,277))),et=(0,d.lazyWithPreload)(()=>n.e("1584").then(n.bind(n,1718))),en=(0,d.lazyWithPreload)(()=>n.e("7201").then(n.bind(n,2771))),er=(0,d.lazyWithPreload)(()=>n.e("1974").then(n.bind(n,651))),ei=(0,d.lazyWithPreload)(()=>n.e("1396").then(n.bind(n,7828))),ea=(0,d.lazyWithPreload)(()=>n.e("9453").then(n.bind(n,7284))),eo=(0,d.lazyWithPreload)(()=>n.e("3895").then(n.bind(n,2077))),es=(0,d.lazyWithPreload)(()=>n.e("1644").then(n.bind(n,3447))),el=(0,d.lazyWithPreload)(()=>n.e("3942").then(n.bind(n,7265))),ec=(0,d.lazyWithPreload)(()=>n.e("4645").then(n.bind(n,8013))),ed=(0,d.lazyWithPreload)(()=>n.e("8566").then(n.bind(n,4089))),eu=(0,d.lazyWithPreload)(()=>n.e("3218").then(n.bind(n,9729))),eh=(0,d.lazyWithPreload)(()=>n.e("2068").then(n.bind(n,7772))),ep=(0,d.lazyWithPreload)(()=>n.e("5481").then(n.bind(n,5240))),ex=(0,d.lazyWithPreload)(()=>n.e("4108").then(n.bind(n,6132))),em=(0,d.lazyWithPreload)(()=>n.e("2951").then(n.bind(n,6755))),ef=(0,d.lazyWithPreload)(()=>n.e("4025").then(n.bind(n,4575))),eg=(0,d.lazyWithPreload)(()=>n.e("2033").then(n.bind(n,9353))),ev=(0,d.lazyWithPreload)(()=>n.e("635").then(n.bind(n,937))),ey=(0,d.lazyWithPreload)(()=>n.e("6324").then(n.bind(n,8586))),eb=(0,d.lazyWithPreload)(()=>n.e("7365").then(n.bind(n,86))),ew=(0,d.lazyWithPreload)(()=>n.e("2184").then(n.bind(n,6427))),ek=(0,d.lazyWithPreload)(()=>n.e("2787").then(n.bind(n,686))),eI=(0,d.lazyWithPreload)(()=>n.e("3552").then(n.bind(n,8035))),eD=(0,d.lazyWithPreload)(()=>n.e("1290").then(n.bind(n,6147))),eE=(0,d.lazyWithPreload)(()=>n.e("4804").then(n.bind(n,5353))),eF=(0,d.lazyWithPreload)(()=>n.e("5263").then(n.bind(n,8502))),eA=(0,d.lazyWithPreload)(()=>n.e("2595").then(n.bind(n,6977))),eC=(0,d.lazyWithPreload)(()=>n.e("5658").then(n.bind(n,6413))),ej=(0,d.lazyWithPreload)(()=>n.e("7308").then(n.bind(n,8333))),eP=(0,d.lazyWithPreload)(()=>n.e("7368").then(n.bind(n,2828))),eS=(0,d.lazyWithPreload)(()=>n.e("435").then(n.bind(n,6942))),eT=(0,d.lazyWithPreload)(()=>n.e("1441").then(n.bind(n,2991))),eN=(0,d.lazyWithPreload)(()=>n.e("3012").then(n.bind(n,2931))),e_=(0,d.lazyWithPreload)(()=>n.e("1020").then(n.bind(n,5637))),eB=(0,d.lazyWithPreload)(()=>n.e("6096").then(n.bind(n,6665))),eO=(0,d.lazyWithPreload)(()=>n.e("2473").then(n.bind(n,7321))),eR=(0,d.lazyWithPreload)(()=>n.e("3858").then(n.bind(n,68))),eq=(0,d.lazyWithPreload)(()=>n.e("7804").then(n.bind(n,7870))),eL=(0,d.lazyWithPreload)(()=>n.e("5469").then(n.bind(n,6495))),eM=(0,d.lazyWithPreload)(()=>n.e("8425").then(n.bind(n,6620))),ez=(0,d.lazyWithPreload)(()=>n.e("7839").then(n.bind(n,4955))),eH=(0,d.lazyWithPreload)(()=>n.e("3014").then(n.bind(n,6415))),e$=(0,d.lazyWithPreload)(()=>n.e("4880").then(n.bind(n,1310))),eW=(0,d.lazyWithPreload)(()=>n.e("9148").then(n.bind(n,3753))),eK=(0,d.lazyWithPreload)(()=>n.e("1121").then(n.bind(n,4723))),eU=(0,d.lazyWithPreload)(()=>n.e("8369").then(n.bind(n,4916))),eV=(0,d.lazyWithPreload)(()=>n.e("7635").then(n.bind(n,6636))),eG=(0,d.lazyWithPreload)(()=>n.e("7487").then(n.bind(n,49))),eZ=(0,d.lazyWithPreload)(()=>n.e("4672").then(n.bind(n,6276))),eJ=(0,d.lazyWithPreload)(()=>n.e("3815").then(n.bind(n,4380))),eQ=(0,d.lazyWithPreload)(()=>n.e("8708").then(n.bind(n,8591))),eY=(0,d.lazyWithPreload)(()=>n.e("3241").then(n.bind(n,9546))),eX=(0,d.lazyWithPreload)(()=>n.e("3655").then(n.bind(n,9910))),e1=(0,d.lazyWithPreload)(()=>n.e("4682").then(n.bind(n,7136))),e0=(0,d.lazyWithPreload)(()=>n.e("8217").then(n.bind(n,7318))),e2=(0,d.lazyWithPreload)(()=>n.e("6600").then(n.bind(n,6906))),e3=(0,d.lazyWithPreload)(()=>n.e("5820").then(n.bind(n,9136))),e4=(0,d.lazyWithPreload)(()=>n.e("4913").then(n.bind(n,983))),e5=(0,d.lazyWithPreload)(()=>n.e("2321").then(n.bind(n,7869))),e6=[{path:"/react-native-testing-library/12.x/cookbook/advanced/network-requests",element:r.createElement(u),filePath:"12.x/cookbook/advanced/network-requests.md",preload:async()=>(await u.preload(),n.e("5123").then(n.bind(n,6080))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/cookbook/basics/async-tests",element:r.createElement(h),filePath:"12.x/cookbook/basics/async-tests.md",preload:async()=>(await h.preload(),n.e("7654").then(n.bind(n,403))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/cookbook/basics/custom-render",element:r.createElement(p),filePath:"12.x/cookbook/basics/custom-render.md",preload:async()=>(await p.preload(),n.e("7824").then(n.bind(n,3986))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/cookbook/",element:r.createElement(x),filePath:"12.x/cookbook/index.md",preload:async()=>(await x.preload(),n.e("6703").then(n.bind(n,6528))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/cookbook/state-management/jotai",element:r.createElement(m),filePath:"12.x/cookbook/state-management/jotai.md",preload:async()=>(await m.preload(),n.e("7221").then(n.bind(n,377))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/advanced/testing-env",element:r.createElement(f),filePath:"12.x/docs/advanced/testing-env.mdx",preload:async()=>(await f.preload(),n.e("6112").then(n.bind(n,2875))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/advanced/understanding-act",element:r.createElement(g),filePath:"12.x/docs/advanced/understanding-act.mdx",preload:async()=>(await g.preload(),n.e("9538").then(n.bind(n,5845))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api",element:r.createElement(v),filePath:"12.x/docs/api.md",preload:async()=>(await v.preload(),n.e("2276").then(n.bind(n,1544))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/events/fire-event",element:r.createElement(y),filePath:"12.x/docs/api/events/fire-event.mdx",preload:async()=>(await y.preload(),n.e("8274").then(n.bind(n,1644))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/events/user-event",element:r.createElement(b),filePath:"12.x/docs/api/events/user-event.mdx",preload:async()=>(await b.preload(),n.e("5190").then(n.bind(n,2029))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/jest-matchers",element:r.createElement(w),filePath:"12.x/docs/api/jest-matchers.mdx",preload:async()=>(await w.preload(),n.e("7956").then(n.bind(n,6227))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/misc/accessibility",element:r.createElement(k),filePath:"12.x/docs/api/misc/accessibility.mdx",preload:async()=>(await k.preload(),n.e("1995").then(n.bind(n,8216))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/misc/async",element:r.createElement(I),filePath:"12.x/docs/api/misc/async.mdx",preload:async()=>(await I.preload(),n.e("3875").then(n.bind(n,5098))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/misc/config",element:r.createElement(D),filePath:"12.x/docs/api/misc/config.mdx",preload:async()=>(await D.preload(),n.e("1912").then(n.bind(n,4721))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/misc/other",element:r.createElement(E),filePath:"12.x/docs/api/misc/other.mdx",preload:async()=>(await E.preload(),n.e("9422").then(n.bind(n,817))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/misc/render-hook",element:r.createElement(F),filePath:"12.x/docs/api/misc/render-hook.mdx",preload:async()=>(await F.preload(),n.e("2540").then(n.bind(n,7683))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/queries",element:r.createElement(A),filePath:"12.x/docs/api/queries.mdx",preload:async()=>(await A.preload(),n.e("1732").then(n.bind(n,9802))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/render",element:r.createElement(C),filePath:"12.x/docs/api/render.mdx",preload:async()=>(await C.preload(),n.e("7458").then(n.bind(n,1698))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/screen",element:r.createElement(j),filePath:"12.x/docs/api/screen.mdx",preload:async()=>(await j.preload(),n.e("6307").then(n.bind(n,7623))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/guides/community-resources",element:r.createElement(P),filePath:"12.x/docs/guides/community-resources.mdx",preload:async()=>(await P.preload(),n.e("3551").then(n.bind(n,6842))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/guides/faq",element:r.createElement(S),filePath:"12.x/docs/guides/faq.mdx",preload:async()=>(await S.preload(),n.e("8318").then(n.bind(n,7798))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/guides/how-to-query",element:r.createElement(T),filePath:"12.x/docs/guides/how-to-query.mdx",preload:async()=>(await T.preload(),n.e("1399").then(n.bind(n,9424))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/guides/troubleshooting",element:r.createElement(N),filePath:"12.x/docs/guides/troubleshooting.mdx",preload:async()=>(await N.preload(),n.e("238").then(n.bind(n,6601))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/migration/jest-matchers",element:r.createElement(_),filePath:"12.x/docs/migration/jest-matchers.mdx",preload:async()=>(await _.preload(),n.e("2829").then(n.bind(n,3834))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/migration/previous/v11",element:r.createElement(B),filePath:"12.x/docs/migration/previous/v11.mdx",preload:async()=>(await B.preload(),n.e("820").then(n.bind(n,301))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/migration/previous/v2",element:r.createElement(O),filePath:"12.x/docs/migration/previous/v2.mdx",preload:async()=>(await O.preload(),n.e("8841").then(n.bind(n,4310))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/migration/previous/v7",element:r.createElement(R),filePath:"12.x/docs/migration/previous/v7.mdx",preload:async()=>(await R.preload(),n.e("9806").then(n.bind(n,7787))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/migration/previous/v9",element:r.createElement(q),filePath:"12.x/docs/migration/previous/v9.mdx",preload:async()=>(await q.preload(),n.e("9862").then(n.bind(n,8108))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/migration/v12",element:r.createElement(L),filePath:"12.x/docs/migration/v12.mdx",preload:async()=>(await L.preload(),n.e("9322").then(n.bind(n,3513))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/start/intro",element:r.createElement(M),filePath:"12.x/docs/start/intro.md",preload:async()=>(await M.preload(),n.e("2299").then(n.bind(n,1801))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/start/quick-start",element:r.createElement(z),filePath:"12.x/docs/start/quick-start.mdx",preload:async()=>(await z.preload(),n.e("2640").then(n.bind(n,3873))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/",element:r.createElement(H),filePath:"12.x/index.md",preload:async()=>(await H.preload(),n.e("9716").then(n.bind(n,2154))),lang:"",version:"12.x"},{path:"/react-native-testing-library/cookbook/advanced/network-requests",element:r.createElement($),filePath:"13.x/cookbook/advanced/network-requests.md",preload:async()=>(await $.preload(),n.e("9437").then(n.bind(n,751))),lang:"",version:"13.x"},{path:"/react-native-testing-library/cookbook/basics/async-tests",element:r.createElement(W),filePath:"13.x/cookbook/basics/async-tests.md",preload:async()=>(await W.preload(),n.e("4877").then(n.bind(n,4718))),lang:"",version:"13.x"},{path:"/react-native-testing-library/cookbook/basics/custom-render",element:r.createElement(K),filePath:"13.x/cookbook/basics/custom-render.md",preload:async()=>(await K.preload(),n.e("5363").then(n.bind(n,8924))),lang:"",version:"13.x"},{path:"/react-native-testing-library/cookbook/",element:r.createElement(U),filePath:"13.x/cookbook/index.md",preload:async()=>(await U.preload(),n.e("4607").then(n.bind(n,3871))),lang:"",version:"13.x"},{path:"/react-native-testing-library/cookbook/state-management/jotai",element:r.createElement(V),filePath:"13.x/cookbook/state-management/jotai.md",preload:async()=>(await V.preload(),n.e("1034").then(n.bind(n,8365))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/advanced/testing-env",element:r.createElement(G),filePath:"13.x/docs/advanced/testing-env.mdx",preload:async()=>(await G.preload(),n.e("4979").then(n.bind(n,8335))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/advanced/third-party-integration",element:r.createElement(Z),filePath:"13.x/docs/advanced/third-party-integration.mdx",preload:async()=>(await Z.preload(),n.e("6791").then(n.bind(n,1997))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/advanced/understanding-act",element:r.createElement(J),filePath:"13.x/docs/advanced/understanding-act.mdx",preload:async()=>(await J.preload(),n.e("2721").then(n.bind(n,1564))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api",element:r.createElement(Q),filePath:"13.x/docs/api.md",preload:async()=>(await Q.preload(),n.e("7401").then(n.bind(n,4785))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/events/fire-event",element:r.createElement(Y),filePath:"13.x/docs/api/events/fire-event.mdx",preload:async()=>(await Y.preload(),n.e("521").then(n.bind(n,6083))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/events/user-event",element:r.createElement(X),filePath:"13.x/docs/api/events/user-event.mdx",preload:async()=>(await X.preload(),n.e("5010").then(n.bind(n,7300))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/jest-matchers",element:r.createElement(ee),filePath:"13.x/docs/api/jest-matchers.mdx",preload:async()=>(await ee.preload(),n.e("8186").then(n.bind(n,277))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/misc/accessibility",element:r.createElement(et),filePath:"13.x/docs/api/misc/accessibility.mdx",preload:async()=>(await et.preload(),n.e("1584").then(n.bind(n,1718))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/misc/async",element:r.createElement(en),filePath:"13.x/docs/api/misc/async.mdx",preload:async()=>(await en.preload(),n.e("7201").then(n.bind(n,2771))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/misc/config",element:r.createElement(er),filePath:"13.x/docs/api/misc/config.mdx",preload:async()=>(await er.preload(),n.e("1974").then(n.bind(n,651))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/misc/other",element:r.createElement(ei),filePath:"13.x/docs/api/misc/other.mdx",preload:async()=>(await ei.preload(),n.e("1396").then(n.bind(n,7828))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/misc/render-hook",element:r.createElement(ea),filePath:"13.x/docs/api/misc/render-hook.mdx",preload:async()=>(await ea.preload(),n.e("9453").then(n.bind(n,7284))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/queries",element:r.createElement(eo),filePath:"13.x/docs/api/queries.mdx",preload:async()=>(await eo.preload(),n.e("3895").then(n.bind(n,2077))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/render",element:r.createElement(es),filePath:"13.x/docs/api/render.mdx",preload:async()=>(await es.preload(),n.e("1644").then(n.bind(n,3447))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/screen",element:r.createElement(el),filePath:"13.x/docs/api/screen.mdx",preload:async()=>(await el.preload(),n.e("3942").then(n.bind(n,7265))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/guides/community-resources",element:r.createElement(ec),filePath:"13.x/docs/guides/community-resources.mdx",preload:async()=>(await ec.preload(),n.e("4645").then(n.bind(n,8013))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/guides/faq",element:r.createElement(ed),filePath:"13.x/docs/guides/faq.mdx",preload:async()=>(await ed.preload(),n.e("8566").then(n.bind(n,4089))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/guides/how-to-query",element:r.createElement(eu),filePath:"13.x/docs/guides/how-to-query.mdx",preload:async()=>(await eu.preload(),n.e("3218").then(n.bind(n,9729))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/guides/react-19",element:r.createElement(eh),filePath:"13.x/docs/guides/react-19.mdx",preload:async()=>(await eh.preload(),n.e("2068").then(n.bind(n,7772))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/guides/troubleshooting",element:r.createElement(ep),filePath:"13.x/docs/guides/troubleshooting.mdx",preload:async()=>(await ep.preload(),n.e("5481").then(n.bind(n,5240))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/migration/jest-matchers",element:r.createElement(ex),filePath:"13.x/docs/migration/jest-matchers.mdx",preload:async()=>(await ex.preload(),n.e("4108").then(n.bind(n,6132))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/migration/previous/v11",element:r.createElement(em),filePath:"13.x/docs/migration/previous/v11.mdx",preload:async()=>(await em.preload(),n.e("2951").then(n.bind(n,6755))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/migration/previous/v12",element:r.createElement(ef),filePath:"13.x/docs/migration/previous/v12.mdx",preload:async()=>(await ef.preload(),n.e("4025").then(n.bind(n,4575))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/migration/previous/v2",element:r.createElement(eg),filePath:"13.x/docs/migration/previous/v2.mdx",preload:async()=>(await eg.preload(),n.e("2033").then(n.bind(n,9353))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/migration/previous/v7",element:r.createElement(ev),filePath:"13.x/docs/migration/previous/v7.mdx",preload:async()=>(await ev.preload(),n.e("635").then(n.bind(n,937))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/migration/previous/v9",element:r.createElement(ey),filePath:"13.x/docs/migration/previous/v9.mdx",preload:async()=>(await ey.preload(),n.e("6324").then(n.bind(n,8586))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/migration/v13",element:r.createElement(eb),filePath:"13.x/docs/migration/v13.mdx",preload:async()=>(await eb.preload(),n.e("7365").then(n.bind(n,86))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/start/intro",element:r.createElement(ew),filePath:"13.x/docs/start/intro.md",preload:async()=>(await ew.preload(),n.e("2184").then(n.bind(n,6427))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/start/quick-start",element:r.createElement(ek),filePath:"13.x/docs/start/quick-start.mdx",preload:async()=>(await ek.preload(),n.e("2787").then(n.bind(n,686))),lang:"",version:"13.x"},{path:"/react-native-testing-library/",element:r.createElement(eI),filePath:"13.x/index.md",preload:async()=>(await eI.preload(),n.e("3552").then(n.bind(n,8035))),lang:"",version:"13.x"},{path:"/react-native-testing-library/14.x/cookbook/advanced/network-requests",element:r.createElement(eD),filePath:"14.x/cookbook/advanced/network-requests.md",preload:async()=>(await eD.preload(),n.e("1290").then(n.bind(n,6147))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/cookbook/basics/async-events",element:r.createElement(eE),filePath:"14.x/cookbook/basics/async-events.md",preload:async()=>(await eE.preload(),n.e("4804").then(n.bind(n,5353))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/cookbook/basics/custom-render",element:r.createElement(eF),filePath:"14.x/cookbook/basics/custom-render.md",preload:async()=>(await eF.preload(),n.e("5263").then(n.bind(n,8502))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/cookbook/",element:r.createElement(eA),filePath:"14.x/cookbook/index.md",preload:async()=>(await eA.preload(),n.e("2595").then(n.bind(n,6977))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/cookbook/state-management/jotai",element:r.createElement(eC),filePath:"14.x/cookbook/state-management/jotai.md",preload:async()=>(await eC.preload(),n.e("5658").then(n.bind(n,6413))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/advanced/testing-env",element:r.createElement(ej),filePath:"14.x/docs/advanced/testing-env.mdx",preload:async()=>(await ej.preload(),n.e("7308").then(n.bind(n,8333))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/advanced/third-party-integration",element:r.createElement(eP),filePath:"14.x/docs/advanced/third-party-integration.mdx",preload:async()=>(await eP.preload(),n.e("7368").then(n.bind(n,2828))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/advanced/understanding-act",element:r.createElement(eS),filePath:"14.x/docs/advanced/understanding-act.mdx",preload:async()=>(await eS.preload(),n.e("435").then(n.bind(n,6942))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api",element:r.createElement(eT),filePath:"14.x/docs/api.md",preload:async()=>(await eT.preload(),n.e("1441").then(n.bind(n,2991))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/events/fire-event",element:r.createElement(eN),filePath:"14.x/docs/api/events/fire-event.mdx",preload:async()=>(await eN.preload(),n.e("3012").then(n.bind(n,2931))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/events/user-event",element:r.createElement(e_),filePath:"14.x/docs/api/events/user-event.mdx",preload:async()=>(await e_.preload(),n.e("1020").then(n.bind(n,5637))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/jest-matchers",element:r.createElement(eB),filePath:"14.x/docs/api/jest-matchers.mdx",preload:async()=>(await eB.preload(),n.e("6096").then(n.bind(n,6665))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/misc/accessibility",element:r.createElement(eO),filePath:"14.x/docs/api/misc/accessibility.mdx",preload:async()=>(await eO.preload(),n.e("2473").then(n.bind(n,7321))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/misc/async",element:r.createElement(eR),filePath:"14.x/docs/api/misc/async.mdx",preload:async()=>(await eR.preload(),n.e("3858").then(n.bind(n,68))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/misc/config",element:r.createElement(eq),filePath:"14.x/docs/api/misc/config.mdx",preload:async()=>(await eq.preload(),n.e("7804").then(n.bind(n,7870))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/misc/other",element:r.createElement(eL),filePath:"14.x/docs/api/misc/other.mdx",preload:async()=>(await eL.preload(),n.e("5469").then(n.bind(n,6495))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/misc/render-hook",element:r.createElement(eM),filePath:"14.x/docs/api/misc/render-hook.mdx",preload:async()=>(await eM.preload(),n.e("8425").then(n.bind(n,6620))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/queries",element:r.createElement(ez),filePath:"14.x/docs/api/queries.mdx",preload:async()=>(await ez.preload(),n.e("7839").then(n.bind(n,4955))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/render",element:r.createElement(eH),filePath:"14.x/docs/api/render.mdx",preload:async()=>(await eH.preload(),n.e("3014").then(n.bind(n,6415))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/screen",element:r.createElement(e$),filePath:"14.x/docs/api/screen.mdx",preload:async()=>(await e$.preload(),n.e("4880").then(n.bind(n,1310))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/guides/community-resources",element:r.createElement(eW),filePath:"14.x/docs/guides/community-resources.mdx",preload:async()=>(await eW.preload(),n.e("9148").then(n.bind(n,3753))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/guides/faq",element:r.createElement(eK),filePath:"14.x/docs/guides/faq.mdx",preload:async()=>(await eK.preload(),n.e("1121").then(n.bind(n,4723))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/guides/how-to-query",element:r.createElement(eU),filePath:"14.x/docs/guides/how-to-query.mdx",preload:async()=>(await eU.preload(),n.e("8369").then(n.bind(n,4916))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/guides/troubleshooting",element:r.createElement(eV),filePath:"14.x/docs/guides/troubleshooting.mdx",preload:async()=>(await eV.preload(),n.e("7635").then(n.bind(n,6636))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/jest-matchers",element:r.createElement(eG),filePath:"14.x/docs/migration/jest-matchers.mdx",preload:async()=>(await eG.preload(),n.e("7487").then(n.bind(n,49))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/v11",element:r.createElement(eZ),filePath:"14.x/docs/migration/v11.mdx",preload:async()=>(await eZ.preload(),n.e("4672").then(n.bind(n,6276))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/v12",element:r.createElement(eJ),filePath:"14.x/docs/migration/v12.mdx",preload:async()=>(await eJ.preload(),n.e("3815").then(n.bind(n,4380))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/v13",element:r.createElement(eQ),filePath:"14.x/docs/migration/v13.mdx",preload:async()=>(await eQ.preload(),n.e("8708").then(n.bind(n,8591))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/v14",element:r.createElement(eY),filePath:"14.x/docs/migration/v14.mdx",preload:async()=>(await eY.preload(),n.e("3241").then(n.bind(n,9546))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/v2",element:r.createElement(eX),filePath:"14.x/docs/migration/v2.mdx",preload:async()=>(await eX.preload(),n.e("3655").then(n.bind(n,9910))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/v7",element:r.createElement(e1),filePath:"14.x/docs/migration/v7.mdx",preload:async()=>(await e1.preload(),n.e("4682").then(n.bind(n,7136))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/v9",element:r.createElement(e0),filePath:"14.x/docs/migration/v9.mdx",preload:async()=>(await e0.preload(),n.e("8217").then(n.bind(n,7318))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/start/intro",element:r.createElement(e2),filePath:"14.x/docs/start/intro.md",preload:async()=>(await e2.preload(),n.e("6600").then(n.bind(n,6906))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/start/quick-start",element:r.createElement(e3),filePath:"14.x/docs/start/quick-start.mdx",preload:async()=>(await e3.preload(),n.e("5820").then(n.bind(n,9136))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/",element:r.createElement(e4),filePath:"14.x/index.md",preload:async()=>(await e4.preload(),n.e("4913").then(n.bind(n,983))),lang:"",version:"14.x"},{path:"/react-native-testing-library/404",element:r.createElement(e5),filePath:"404.mdx",preload:async()=>(await e5.preload(),n.e("2321").then(n.bind(n,7869))),lang:"",version:"13.x"}];var e7=n(2599);function e8(e){return decodeURIComponent(e).replace(/\.html$/,"").replace(/\/index$/,"/")}let e9=new Map;function te(e){var t;let n=e9.get(e);if(n)return n;let r=(0,e7.fp)(e6,e8(e)),i=null==r||null==(t=r[0])?void 0:t.route;return i&&e9.set(e,i),i}let tt=(0,r.memo)(function(e){var t;let n=e.el;return(null===c.Z||void 0===c.Z||null==(t=c.Z.themeConfig)?void 0:t.enableContentAnimation)&&(n=function(e){let[t,n]=(0,r.useState)(e);return(0,r.useLayoutEffect)(()=>{document.startViewTransition&&t!==e?document.startViewTransition(()=>{(0,i.flushSync)(()=>{n(e)}),window.dispatchEvent(new Event("RspressReloadContent"))}):((0,i.flushSync)(()=>{n(e)}),window.dispatchEvent(new Event("RspressReloadContent")))},[e]),t}(e.el)),n},(e,t)=>e.el===t.el);var tn=n(8995);function tr(e="/"){return(0,tn.pJ)(e,c.Z.base)}function ti(e){var t;let n=!!(null===c.Z||void 0===c.Z||null==(t=c.Z.route)?void 0:t.cleanUrls);return(0,tn.yc)(e,n)}tn.nY;var ta=tn.yv;tn.Kw,tn.Qj;var to=n(9655),ts=n(405),tl=to.VK,tc=({fallback:e=(0,s.jsx)(s.Fragment,{})})=>{let{pathname:t}=(0,l.TH)(),n=te(t);if(!n)return(0,s.jsx)("div",{});let i=n.element;return(0,s.jsx)(r.Suspense,{fallback:e,children:(0,s.jsx)(tt,{el:i})})},td=a;ts.ql;var tu=function(e){let{children:t}=e,[n,i]=(0,r.useState)(!1);return((0,r.useEffect)(()=>{i(!0)},[]),n)?(0,s.jsx)(s.Fragment,{children:t}):null},th=o,tp=function(e,t){return tr(ti((0,tn.lm)(e)))===tr(ti((0,tn.lm)(t)))},tx=ta,tm=e7.LX;e7.fp;var tf=ti,tg=function(e){var t;return!(0,tn.yv)()||(t=e,(0,tn.xf)(t)||(0,tn.pZ)(t)||t.startsWith("//"))||!e.startsWith("/")?e:tr(e)},tv=e8,ty=te,tb=function(e){return(0,tn.E9)(e,c.Z.base)},tw=function(){return(0,r.useContext)(a).data.page.lang||""},tk=l.TH,tI=l.s0,tD=function(){return(0,r.useContext)(a).data};to.lr;var tE=function(){return(0,r.useContext)(a).data.page.version||""},tF=function(e,t){let[n,i]=(0,r.useState)({width:e??("undefined"==typeof window?Number.POSITIVE_INFINITY:window.innerWidth),height:t??("undefined"==typeof window?Number.POSITIVE_INFINITY:window.innerHeight)});return(0,r.useLayoutEffect)(()=>{let e=()=>{i({width:window.innerWidth,height:window.innerHeight})};return window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}},[]),n},tA=tr},640:function(e,t,n){"use strict";var r=n(1742),i={"text/plain":"Text","text/html":"Url",default:"Text"};e.exports=function(e,t){var n,a,o,s,l,c,d,u,h=!1;t||(t={}),o=t.debug||!1;try{if(l=r(),c=document.createRange(),d=document.getSelection(),(u=document.createElement("span")).textContent=e,u.ariaHidden="true",u.style.all="unset",u.style.position="fixed",u.style.top=0,u.style.clip="rect(0, 0, 0, 0)",u.style.whiteSpace="pre",u.style.webkitUserSelect="text",u.style.MozUserSelect="text",u.style.msUserSelect="text",u.style.userSelect="text",u.addEventListener("copy",function(n){if(n.stopPropagation(),t.format)if(n.preventDefault(),void 0===n.clipboardData){o&&console.warn("unable to use e.clipboardData"),o&&console.warn("trying IE specific stuff"),window.clipboardData.clearData();var r=i[t.format]||i.default;window.clipboardData.setData(r,e)}else n.clipboardData.clearData(),n.clipboardData.setData(t.format,e);t.onCopy&&(n.preventDefault(),t.onCopy(n.clipboardData))}),document.body.appendChild(u),c.selectNodeContents(u),d.addRange(c),!document.execCommand("copy"))throw Error("copy command was unsuccessful");h=!0}catch(r){o&&console.error("unable to copy using execCommand: ",r),o&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(t.format||"text",e),t.onCopy&&t.onCopy(window.clipboardData),h=!0}catch(r){o&&console.error("unable to copy using clipboardData: ",r),o&&console.error("falling back to prompt"),n="message"in t?t.message:"Copy to clipboard: #{key}, Enter",a=(/mac os x/i.test(navigator.userAgent)?"⌘":"Ctrl")+"+C",s=n.replace(/#{\s*key\s*}/g,a),window.prompt(s,e)}}finally{d&&("function"==typeof d.removeRange?d.removeRange(c):d.removeAllRanges()),u&&document.body.removeChild(u),l()}return h}},8892:function(e){"use strict";e.exports=function(e,n){for(var r,i,a,o=e||"",s=n||"div",l={},c=0;c4&&x.slice(0,4)===o&&s.test(t)&&("-"===t.charAt(4)?m=o+(n=t.slice(5).replace(l,u)).charAt(0).toUpperCase()+n.slice(1):(p=(h=t).slice(4),t=l.test(p)?h:("-"!==(p=p.replace(c,d)).charAt(0)&&(p="-"+p),o+p)),f=i),new f(m,t))};var s=/^data[-\w.:]+$/i,l=/-[a-z]/g,c=/[A-Z]/g;function d(e){return"-"+e.toLowerCase()}function u(e){return e.charAt(1).toUpperCase()}},8055:function(e,t,n){"use strict";var r=n(6230),i=n(3970);e.exports=r([n(629),i,n(647),n(1305),n(2537)])},1305:function(e,t,n){"use strict";var r=n(1422),i=n(7589),a=r.booleanish,o=r.number,s=r.spaceSeparated;e.exports=i({transform:function(e,t){return"role"===t?t:"aria-"+t.slice(4).toLowerCase()},properties:{ariaActiveDescendant:null,ariaAtomic:a,ariaAutoComplete:null,ariaBusy:a,ariaChecked:a,ariaColCount:o,ariaColIndex:o,ariaColSpan:o,ariaControls:s,ariaCurrent:null,ariaDescribedBy:s,ariaDetails:null,ariaDisabled:a,ariaDropEffect:s,ariaErrorMessage:null,ariaExpanded:a,ariaFlowTo:s,ariaGrabbed:a,ariaHasPopup:null,ariaHidden:a,ariaInvalid:null,ariaKeyShortcuts:null,ariaLabel:null,ariaLabelledBy:s,ariaLevel:o,ariaLive:null,ariaModal:a,ariaMultiLine:a,ariaMultiSelectable:a,ariaOrientation:null,ariaOwns:s,ariaPlaceholder:null,ariaPosInSet:o,ariaPressed:a,ariaReadOnly:a,ariaRelevant:null,ariaRequired:a,ariaRoleDescription:s,ariaRowCount:o,ariaRowIndex:o,ariaRowSpan:o,ariaSelected:a,ariaSetSize:o,ariaSort:null,ariaValueMax:o,ariaValueMin:o,ariaValueNow:o,ariaValueText:null,role:null}})},2537:function(e,t,n){"use strict";var r=n(1422),i=n(7589),a=n(9348),o=r.boolean,s=r.overloadedBoolean,l=r.booleanish,c=r.number,d=r.spaceSeparated,u=r.commaSeparated;e.exports=i({space:"html",attributes:{acceptcharset:"accept-charset",classname:"class",htmlfor:"for",httpequiv:"http-equiv"},transform:a,mustUseProperty:["checked","multiple","muted","selected"],properties:{abbr:null,accept:u,acceptCharset:d,accessKey:d,action:null,allow:null,allowFullScreen:o,allowPaymentRequest:o,allowUserMedia:o,alt:null,as:null,async:o,autoCapitalize:null,autoComplete:d,autoFocus:o,autoPlay:o,capture:o,charSet:null,checked:o,cite:null,className:d,cols:c,colSpan:null,content:null,contentEditable:l,controls:o,controlsList:d,coords:c|u,crossOrigin:null,data:null,dateTime:null,decoding:null,default:o,defer:o,dir:null,dirName:null,disabled:o,download:s,draggable:l,encType:null,enterKeyHint:null,form:null,formAction:null,formEncType:null,formMethod:null,formNoValidate:o,formTarget:null,headers:d,height:c,hidden:o,high:c,href:null,hrefLang:null,htmlFor:d,httpEquiv:d,id:null,imageSizes:null,imageSrcSet:u,inputMode:null,integrity:null,is:null,isMap:o,itemId:null,itemProp:d,itemRef:d,itemScope:o,itemType:d,kind:null,label:null,lang:null,language:null,list:null,loading:null,loop:o,low:c,manifest:null,max:null,maxLength:c,media:null,method:null,min:null,minLength:c,multiple:o,muted:o,name:null,nonce:null,noModule:o,noValidate:o,onAbort:null,onAfterPrint:null,onAuxClick:null,onBeforePrint:null,onBeforeUnload:null,onBlur:null,onCancel:null,onCanPlay:null,onCanPlayThrough:null,onChange:null,onClick:null,onClose:null,onContextMenu:null,onCopy:null,onCueChange:null,onCut:null,onDblClick:null,onDrag:null,onDragEnd:null,onDragEnter:null,onDragExit:null,onDragLeave:null,onDragOver:null,onDragStart:null,onDrop:null,onDurationChange:null,onEmptied:null,onEnded:null,onError:null,onFocus:null,onFormData:null,onHashChange:null,onInput:null,onInvalid:null,onKeyDown:null,onKeyPress:null,onKeyUp:null,onLanguageChange:null,onLoad:null,onLoadedData:null,onLoadedMetadata:null,onLoadEnd:null,onLoadStart:null,onMessage:null,onMessageError:null,onMouseDown:null,onMouseEnter:null,onMouseLeave:null,onMouseMove:null,onMouseOut:null,onMouseOver:null,onMouseUp:null,onOffline:null,onOnline:null,onPageHide:null,onPageShow:null,onPaste:null,onPause:null,onPlay:null,onPlaying:null,onPopState:null,onProgress:null,onRateChange:null,onRejectionHandled:null,onReset:null,onResize:null,onScroll:null,onSecurityPolicyViolation:null,onSeeked:null,onSeeking:null,onSelect:null,onSlotChange:null,onStalled:null,onStorage:null,onSubmit:null,onSuspend:null,onTimeUpdate:null,onToggle:null,onUnhandledRejection:null,onUnload:null,onVolumeChange:null,onWaiting:null,onWheel:null,open:o,optimum:c,pattern:null,ping:d,placeholder:null,playsInline:o,poster:null,preload:null,readOnly:o,referrerPolicy:null,rel:d,required:o,reversed:o,rows:c,rowSpan:c,sandbox:d,scope:null,scoped:o,seamless:o,selected:o,shape:null,size:c,sizes:null,slot:null,span:c,spellCheck:l,src:null,srcDoc:null,srcLang:null,srcSet:u,start:c,step:null,style:null,tabIndex:c,target:null,title:null,translate:null,type:null,typeMustMatch:o,useMap:null,value:l,width:c,wrap:null,align:null,aLink:null,archive:d,axis:null,background:null,bgColor:null,border:c,borderColor:null,bottomMargin:c,cellPadding:null,cellSpacing:null,char:null,charOff:null,classId:null,clear:null,code:null,codeBase:null,codeType:null,color:null,compact:o,declare:o,event:null,face:null,frame:null,frameBorder:null,hSpace:c,leftMargin:c,link:null,longDesc:null,lowSrc:null,marginHeight:c,marginWidth:c,noResize:o,noHref:o,noShade:o,noWrap:o,object:null,profile:null,prompt:null,rev:null,rightMargin:c,rules:null,scheme:null,scrolling:l,standby:null,summary:null,text:null,topMargin:c,valueType:null,version:null,vAlign:null,vLink:null,vSpace:c,allowTransparency:null,autoCorrect:null,autoSave:null,disablePictureInPicture:o,disableRemotePlayback:o,prefix:null,property:null,results:c,security:null,unselectable:null}})},9348:function(e,t,n){"use strict";var r=n(1098);e.exports=function(e,t){return r(e,t.toLowerCase())}},1098:function(e){"use strict";e.exports=function(e,t){return t in e?e[t]:t}},7589:function(e,t,n){"use strict";var r=n(4977),i=n(6038),a=n(8444);e.exports=function(e){var t,n,o=e.space,s=e.mustUseProperty||[],l=e.attributes||{},c=e.properties,d=e.transform,u={},h={};for(t in c)n=new a(t,d(l,t),c[t],o),-1!==s.indexOf(t)&&(n.mustUseProperty=!0),u[t]=n,h[r(t)]=t,h[r(n.attribute)]=t;return new i(u,h,o)}},8444:function(e,t,n){"use strict";var r=n(313),i=n(1422);e.exports=s,s.prototype=new r,s.prototype.defined=!0;var a=["boolean","booleanish","overloadedBoolean","number","commaSeparated","spaceSeparated","commaOrSpaceSeparated"],o=a.length;function s(e,t,n,s){var l,c,d,u,h,p,x=-1;for(l=this,(c=s)&&(l.space=c),r.call(this,e,t);++x-1}var o=["itemScope"];function s(t,n,r,i){void 0===i&&(i=null);var a=r[t],o=r._;return a?e.createElement(a,n,i):o?o(t,n,i):e.createElement(t,n,i)}return function(e,r){if(void 0===r&&(r={}),"string"!=typeof e)throw TypeError("Expected HTML string");var a=document.createElement("div");a.innerHTML=e.trim();var o=Array.from(a.childNodes).map(function(e,a){return function e(r,a,o){var l,c=o.transform||{},d=o.preserveAttributes||[],u=o.dangerouslySetChildren||["style"],h=c._;if(8===r.nodeType)return null;if(3===r.nodeType){var p=r.textContent;return h?h(p):p}for(var x={},m=r.attributes,f=0;f1){var i,a=(i=r[0].trim(),/^-ms-/.test(i)&&(i=i.substr(1)),i.startsWith("--")?i:t(i)),s=(n=r.slice(1).join(":").trim(),/^\d+$/.test(n)?Number(n):n.replace(/'/g,'"'));o[a]=s}}),o);else{var c=l[n],u=""===c||String(c).toLowerCase()===r.toLowerCase();e[s.name]=s.isBoolean?u:c}return e},{})),y=Array.from(r.childNodes).map(function(t,r){return n.indexOf(g)>-1&&3===t.nodeType&&(t.textContent=t.textContent.trim(),""===t.textContent)?null:e(t,a+"."+r,o)}).filter(Boolean);if(u.indexOf(g)>-1){var b=r.innerHTML;return b&&("style"!==g&&"script"!==g&&(b=b.replace(/"/g,""")),v.dangerouslySetInnerHTML={__html:b.trim()}),s(g,v,c)}return s(g,v,c,0===y.length?null:y)}(e,String(a),r)}).filter(Boolean);return 1===o.length?o[0]:o}}(n(7294))},1143:function(e){"use strict";e.exports=function(e,t,n,r,i,a,o,s){if(!e){var l;if(void 0===t)l=Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,i,a,o,s],d=0;(l=Error(t.replace(/%s/g,function(){return c[d++]}))).name="Invariant Violation"}throw l.framesToPop=1,l}}},4865:function(e){var t;t=function(){var e,t,n,r={};r.version="0.2.0";var i=r.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
    '};function a(e,t,n){return en?n:e}r.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(i[t]=n);return this},r.status=null,r.set=function(e){var t=r.isStarted();r.status=1===(e=a(e,i.minimum,1))?null:e;var n=r.render(!t),l=n.querySelector(i.barSelector),c=i.speed,d=i.easing;return n.offsetWidth,o(function(t){var a,o,u,h;""===i.positionUsing&&(i.positionUsing=r.getPositioningCSS()),s(l,(a=e,o=c,u=d,(h="translate3d"===i.positionUsing?{transform:"translate3d("+(-1+a)*100+"%,0,0)"}:"translate"===i.positionUsing?{transform:"translate("+(-1+a)*100+"%,0)"}:{"margin-left":(-1+a)*100+"%"}).transition="all "+o+"ms "+u,h)),1===e?(s(n,{transition:"none",opacity:1}),n.offsetWidth,setTimeout(function(){s(n,{transition:"all "+c+"ms linear",opacity:0}),setTimeout(function(){r.remove(),t()},c)},c)):setTimeout(t,c)}),this},r.isStarted=function(){return"number"==typeof r.status},r.start=function(){r.status||r.set(0);var e=function(){setTimeout(function(){r.status&&(r.trickle(),e())},i.trickleSpeed)};return i.trickle&&e(),this},r.done=function(e){return e||r.status?r.inc(.3+.5*Math.random()).set(1):this},r.inc=function(e){var t=r.status;return t?("number"!=typeof e&&(e=(1-t)*a(Math.random()*t,.1,.95)),t=a(t+e,0,.994),r.set(t)):r.start()},r.trickle=function(){return r.inc(Math.random()*i.trickleRate)},e=0,t=0,r.promise=function(n){return n&&"resolved"!==n.state()&&(0===t&&r.start(),e++,t++,n.always(function(){0==--t?(e=0,r.done()):r.set((e-t)/e)})),this},r.render=function(e){if(r.isRendered())return document.getElementById("nprogress");c(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=i.template;var n,a=t.querySelector(i.barSelector),o=e?"-100":(-1+(r.status||0))*100,l=document.querySelector(i.parent);return s(a,{transition:"all 0 linear",transform:"translate3d("+o+"%,0,0)"}),!i.showSpinner&&(n=t.querySelector(i.spinnerSelector))&&h(n),l!=document.body&&c(l,"nprogress-custom-parent"),l.appendChild(t),t},r.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(i.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&h(e)},r.isRendered=function(){return!!document.getElementById("nprogress")},r.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var o=(n=[],function(e){n.push(e),1==n.length&&function e(){var t=n.shift();t&&t(e)}()}),s=function(){var e=["Webkit","O","Moz","ms"],t={};function n(n,r,i){var a;r=t[a=(a=r).replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(e,t){return t.toUpperCase()})]||(t[a]=function(t){var n=document.body.style;if(t in n)return t;for(var r,i=e.length,a=t.charAt(0).toUpperCase()+t.slice(1);i--;)if((r=e[i]+a)in n)return r;return t}(a)),n.style[r]=i}return function(e,t){var r,i,a=arguments;if(2==a.length)for(r in t)void 0!==(i=t[r])&&t.hasOwnProperty(r)&&n(e,r,i);else n(e,a[1],a[2])}}();function l(e,t){return("string"==typeof e?e:u(e)).indexOf(" "+t+" ")>=0}function c(e,t){var n=u(e),r=n+t;l(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=u(e);l(e,t)&&(e.className=(n=r.replace(" "+t+" "," ")).substring(1,n.length-1))}function u(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function h(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return r},"function"==typeof define&&define.amd?define(t):e.exports=t()},2703:function(e,t,n){"use strict";var r=n(414);function i(){}function a(){}a.resetWarningCache=i,e.exports=function(){function e(e,t,n,i,a,o){if(o!==r){var s=Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:a,resetWarningCache:i};return n.PropTypes=n,n}},5697:function(e,t,n){e.exports=n(2703)()},414:function(e){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},9590:function(e){var t="undefined"!=typeof Element,n="function"==typeof Map,r="function"==typeof Set,i="function"==typeof ArrayBuffer&&!!ArrayBuffer.isView;e.exports=function(e,a){try{return function e(a,o){if(a===o)return!0;if(a&&o&&"object"==typeof a&&"object"==typeof o){var s,l,c,d;if(a.constructor!==o.constructor)return!1;if(Array.isArray(a)){if((s=a.length)!=o.length)return!1;for(l=s;0!=l--;)if(!e(a[l],o[l]))return!1;return!0}if(n&&a instanceof Map&&o instanceof Map){if(a.size!==o.size)return!1;for(d=a.entries();!(l=d.next()).done;)if(!o.has(l.value[0]))return!1;for(d=a.entries();!(l=d.next()).done;)if(!e(l.value[1],o.get(l.value[0])))return!1;return!0}if(r&&a instanceof Set&&o instanceof Set){if(a.size!==o.size)return!1;for(d=a.entries();!(l=d.next()).done;)if(!o.has(l.value[0]))return!1;return!0}if(i&&ArrayBuffer.isView(a)&&ArrayBuffer.isView(o)){if((s=a.length)!=o.length)return!1;for(l=s;0!=l--;)if(a[l]!==o[l])return!1;return!0}if(a.constructor===RegExp)return a.source===o.source&&a.flags===o.flags;if(a.valueOf!==Object.prototype.valueOf&&"function"==typeof a.valueOf&&"function"==typeof o.valueOf)return a.valueOf()===o.valueOf();if(a.toString!==Object.prototype.toString&&"function"==typeof a.toString&&"function"==typeof o.toString)return a.toString()===o.toString();if((s=(c=Object.keys(a)).length)!==Object.keys(o).length)return!1;for(l=s;0!=l--;)if(!Object.prototype.hasOwnProperty.call(o,c[l]))return!1;if(t&&a instanceof Element)return!1;for(l=s;0!=l--;)if(("_owner"!==c[l]&&"__v"!==c[l]&&"__o"!==c[l]||!a.$$typeof)&&!e(a[c[l]],o[c[l]]))return!1;return!0}return a!=a&&o!=o}(e,a)}catch(e){if((e.message||"").match(/stack|recursion/i))return console.warn("react-fast-compare cannot handle circular refs"),!1;throw e}}},405:function(e,t,n){"use strict";n.d(t,{B6:()=>$,ql:()=>Q});var r=n(7294),i=n(5697),a=n.n(i),o=n(9590),s=n.n(o),l=n(1143),c=n.n(l),d=n(6774),u=n.n(d);function h(){return(h=Object.assign||function(e){for(var t=1;t=0||(i[n]=e[n]);return i}var f={BASE:"base",BODY:"body",HEAD:"head",HTML:"html",LINK:"link",META:"meta",NOSCRIPT:"noscript",SCRIPT:"script",STYLE:"style",TITLE:"title",FRAGMENT:"Symbol(react.fragment)"},g={rel:["amphtml","canonical","alternate"]},v={type:["application/ld+json"]},y={charset:"",name:["robots","description"],property:["og:type","og:title","og:url","og:image","og:image:alt","og:description","twitter:url","twitter:title","twitter:description","twitter:image","twitter:image:alt","twitter:card","twitter:site"]},b=Object.keys(f).map(function(e){return f[e]}),w={accesskey:"accessKey",charset:"charSet",class:"className",contenteditable:"contentEditable",contextmenu:"contextMenu","http-equiv":"httpEquiv",itemprop:"itemProp",tabindex:"tabIndex"},k=Object.keys(w).reduce(function(e,t){return e[w[t]]=t,e},{}),I=function(e,t){for(var n=e.length-1;n>=0;n-=1){var r=e[n];if(Object.prototype.hasOwnProperty.call(r,t))return r[t]}return null},D=function(e){var t=I(e,f.TITLE),n=I(e,"titleTemplate");if(Array.isArray(t)&&(t=t.join("")),n&&t)return n.replace(/%s/g,function(){return t});var r=I(e,"defaultTitle");return t||r||void 0},E=function(e,t){return t.filter(function(t){return void 0!==t[e]}).map(function(t){return t[e]}).reduce(function(e,t){return h({},e,t)},{})},F=function(e,t,n){var r={};return n.filter(function(t){return!!Array.isArray(t[e])||(void 0!==t[e]&&console&&"function"==typeof console.warn&&console.warn("Helmet: "+e+' should be of type "Array". Instead found type "'+typeof t[e]+'"'),!1)}).map(function(t){return t[e]}).reverse().reduce(function(e,n){var i={};n.filter(function(e){for(var n,a=Object.keys(e),o=0;o/g,">").replace(/"/g,""").replace(/'/g,"'")},N=function(e){return Object.keys(e).reduce(function(t,n){var r=void 0!==e[n]?n+'="'+e[n]+'"':""+n;return t?t+" "+r:r},"")},_=function(e,t){return void 0===t&&(t={}),Object.keys(e).reduce(function(t,n){return t[w[n]||n]=e[n],t},t)},B=function(e,t){return t.map(function(t,n){var i,a=((i={key:n})["data-rh"]=!0,i);return Object.keys(t).forEach(function(e){var n=w[e]||e;"innerHTML"===n||"cssText"===n?a.dangerouslySetInnerHTML={__html:t.innerHTML||t.cssText}:a[n]=t[e]}),r.createElement(e,a)})},O=function(e,t,n){switch(e){case f.TITLE:return{toComponent:function(){var e,n,i,a;return n=t.titleAttributes,(i={key:e=t.title})["data-rh"]=!0,a=_(n,i),[r.createElement(f.TITLE,a,e)]},toString:function(){var r,i,a,o;return r=t.title,i=t.titleAttributes,a=N(i),o=C(r),a?"<"+e+' data-rh="true" '+a+">"+T(o,n)+"":"<"+e+' data-rh="true">'+T(o,n)+""}};case"bodyAttributes":case"htmlAttributes":return{toComponent:function(){return _(t)},toString:function(){return N(t)}};default:return{toComponent:function(){return B(e,t)},toString:function(){return t.reduce(function(t,r){var i=Object.keys(r).filter(function(e){return"innerHTML"!==e&&"cssText"!==e}).reduce(function(e,t){var i=void 0===r[t]?t:t+'="'+T(r[t],n)+'"';return e?e+" "+i:i},""),a=r.innerHTML||r.cssText||"",o=-1===S.indexOf(e);return t+"<"+e+' data-rh="true" '+i+(o?"/>":">"+a+"")},"")}}}},R=function(e){var t=e.baseTag,n=e.bodyAttributes,r=e.encode,i=e.htmlAttributes,a=e.noscriptTags,o=e.styleTags,s=e.title,l=e.titleAttributes,c=e.linkTags,d=e.metaTags,u=e.scriptTags,h={toComponent:function(){},toString:function(){return""}};if(e.prioritizeSeoTags){var p,x,m,b,w,k,I=(p=e.linkTags,x=e.scriptTags,m=e.encode,b=j(e.metaTags,y),w=j(p,g),k=j(x,v),{priorityMethods:{toComponent:function(){return[].concat(B(f.META,b.priority),B(f.LINK,w.priority),B(f.SCRIPT,k.priority))},toString:function(){return O(f.META,b.priority,m)+" "+O(f.LINK,w.priority,m)+" "+O(f.SCRIPT,k.priority,m)}},metaTags:b.default,linkTags:w.default,scriptTags:k.default});h=I.priorityMethods,c=I.linkTags,d=I.metaTags,u=I.scriptTags}return{priority:h,base:O(f.BASE,t,r),bodyAttributes:O("bodyAttributes",n,r),htmlAttributes:O("htmlAttributes",i,r),link:O(f.LINK,c,r),meta:O(f.META,d,r),noscript:O(f.NOSCRIPT,a,r),script:O(f.SCRIPT,u,r),style:O(f.STYLE,o,r),title:O(f.TITLE,{title:void 0===s?"":s,titleAttributes:l},r)}},q=[],L=function(e,t){var n=this;void 0===t&&(t="undefined"!=typeof document),this.instances=[],this.value={setHelmet:function(e){n.context.helmet=e},helmetInstances:{get:function(){return n.canUseDOM?q:n.instances},add:function(e){(n.canUseDOM?q:n.instances).push(e)},remove:function(e){var t=(n.canUseDOM?q:n.instances).indexOf(e);(n.canUseDOM?q:n.instances).splice(t,1)}}},this.context=e,this.canUseDOM=t,t||(e.helmet=R({baseTag:[],bodyAttributes:{},encodeSpecialCharacters:!0,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],scriptTags:[],styleTags:[],title:"",titleAttributes:{}}))},M=r.createContext({}),z=a().shape({setHelmet:a().func,helmetInstances:a().shape({get:a().func,add:a().func,remove:a().func})}),H="undefined"!=typeof document,$=function(e){function t(n){var r;return(r=e.call(this,n)||this).helmetData=new L(r.props.context,t.canUseDOM),r}return p(t,e),t.prototype.render=function(){return r.createElement(M.Provider,{value:this.helmetData.value},this.props.children)},t}(r.Component);$.canUseDOM=H,$.propTypes={context:a().shape({helmet:a().shape()}),children:a().node.isRequired},$.defaultProps={context:{}},$.displayName="HelmetProvider";var W=function(e,t){var n,r=document.head||document.querySelector(f.HEAD),i=r.querySelectorAll(e+"[data-rh]"),a=[].slice.call(i),o=[];return t&&t.length&&t.forEach(function(t){var r=document.createElement(e);for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&("innerHTML"===i?r.innerHTML=t.innerHTML:"cssText"===i?r.styleSheet?r.styleSheet.cssText=t.cssText:r.appendChild(document.createTextNode(t.cssText)):r.setAttribute(i,void 0===t[i]?"":t[i]));r.setAttribute("data-rh","true"),a.some(function(e,t){return n=t,r.isEqualNode(e)})?a.splice(n,1):o.push(r)}),a.forEach(function(e){return e.parentNode.removeChild(e)}),o.forEach(function(e){return r.appendChild(e)}),{oldTags:a,newTags:o}},K=function(e,t){var n=document.getElementsByTagName(e)[0];if(n){for(var r=n.getAttribute("data-rh"),i=r?r.split(","):[],a=[].concat(i),o=Object.keys(t),s=0;s=0;u-=1)n.removeAttribute(a[u]);i.length===a.length?n.removeAttribute("data-rh"):n.getAttribute("data-rh")!==o.join(",")&&n.setAttribute("data-rh",o.join(","))}},U=function(e,t){var n=e.baseTag,r=e.htmlAttributes,i=e.linkTags,a=e.metaTags,o=e.noscriptTags,s=e.onChangeClientState,l=e.scriptTags,c=e.styleTags,d=e.title,u=e.titleAttributes;K(f.BODY,e.bodyAttributes),K(f.HTML,r),void 0!==d&&document.title!==d&&(document.title=C(d)),K(f.TITLE,u);var h={baseTag:W(f.BASE,n),linkTags:W(f.LINK,i),metaTags:W(f.META,a),noscriptTags:W(f.NOSCRIPT,o),scriptTags:W(f.SCRIPT,l),styleTags:W(f.STYLE,c)},p={},x={};Object.keys(h).forEach(function(e){var t=h[e],n=t.newTags,r=t.oldTags;n.length&&(p[e]=n),r.length&&(x[e]=h[e].oldTags)}),t&&t(),s(e,p,x)},V=null,G=function(e){function t(){for(var t,n=arguments.length,r=Array(n),i=0;i elements are self-closing and can not contain children. Refer to our API for more information.")}},n.flattenArrayTypeChildren=function(e){var t,n=e.child,r=e.arrayTypeChildren;return h({},r,((t={})[n.type]=[].concat(r[n.type]||[],[h({},e.newChildProps,this.mapNestedChildrenToProps(n,e.nestedChildren))]),t))},n.mapObjectTypeChildren=function(e){var t,n,r=e.child,i=e.newProps,a=e.newChildProps,o=e.nestedChildren;switch(r.type){case f.TITLE:return h({},i,((t={})[r.type]=o,t.titleAttributes=h({},a),t));case f.BODY:return h({},i,{bodyAttributes:h({},a)});case f.HTML:return h({},i,{htmlAttributes:h({},a)});default:return h({},i,((n={})[r.type]=h({},a),n))}},n.mapArrayTypeChildrenToProps=function(e,t){var n=h({},t);return Object.keys(e).forEach(function(t){var r;n=h({},n,((r={})[t]=e[t],r))}),n},n.warnOnInvalidChildren=function(e,t){return c()(b.some(function(t){return e.type===t}),"function"==typeof e.type?"You may be attempting to nest components within each other, which is not allowed. Refer to our API for more information.":"Only elements types "+b.join(", ")+" are allowed. Helmet does not support rendering <"+e.type+"> elements. Refer to our API for more information."),c()(!t||"string"==typeof t||Array.isArray(t)&&!t.some(function(e){return"string"!=typeof e}),"Helmet expects a string as a child of <"+e.type+">. Did you forget to wrap your children in braces? ( <"+e.type+">{``} ) Refer to our API for more information."),!0},n.mapChildrenToProps=function(e,t){var n=this,i={};return r.Children.forEach(e,function(e){if(e&&e.props){var r=e.props,a=r.children,o=m(r,Z),s=Object.keys(o).reduce(function(e,t){return e[k[t]||t]=o[t],e},{}),l=e.type;switch("symbol"==typeof l?l=l.toString():n.warnOnInvalidChildren(e,a),l){case f.FRAGMENT:t=n.mapChildrenToProps(a,t);break;case f.LINK:case f.META:case f.NOSCRIPT:case f.SCRIPT:case f.STYLE:i=n.flattenArrayTypeChildren({child:e,arrayTypeChildren:i,newChildProps:s,nestedChildren:a});break;default:t=n.mapObjectTypeChildren({child:e,newProps:t,newChildProps:s,nestedChildren:a})}}}),this.mapArrayTypeChildrenToProps(i,t)},n.render=function(){var e=this.props,t=e.children,n=m(e,J),i=h({},n),a=n.helmetData;return t&&(i=this.mapChildrenToProps(t,i)),!a||a instanceof L||(a=new L(a.context,a.instances)),a?r.createElement(G,h({},i,{context:a.value,helmetData:void 0})):r.createElement(M.Consumer,null,function(e){return r.createElement(G,h({},i,{context:e}))})},t}(r.Component);Q.propTypes={base:a().object,bodyAttributes:a().object,children:a().oneOfType([a().arrayOf(a().node),a().node]),defaultTitle:a().string,defer:a().bool,encodeSpecialCharacters:a().bool,htmlAttributes:a().object,link:a().arrayOf(a().object),meta:a().arrayOf(a().object),noscript:a().arrayOf(a().object),onChangeClientState:a().func,script:a().arrayOf(a().object),style:a().arrayOf(a().object),title:a().string,titleAttributes:a().object,titleTemplate:a().string,prioritizeSeoTags:a().bool,helmetData:a().object},Q.defaultProps={defer:!0,encodeSpecialCharacters:!0,prioritizeSeoTags:!1},Q.displayName="Helmet"},3040:function(e,t,n){"use strict";t.lazyWithPreload=void 0;var r=n(7294);t.lazyWithPreload=function(e){var t,n,i=(0,r.lazy)(e),a=(0,r.forwardRef)(function(e,n){var a=(0,r.useRef)(null!=t?t:i);return(0,r.createElement)(a.current,Object.assign(n?{ref:n}:{},e))});return a.preload=function(){return n||(n=e().then(function(e){return t=e.default})),n},a}},1318:function(e,t,n){"use strict";var r=n(5751);t.default=void 0,t.default=r(n(6979)).default},9031:function(e,t,n){"use strict";var r=n(5751);t.default=void 0,t.default=r(n(3336)).default},2041:function(e,t,n){"use strict";var r=n(5751);t.default=void 0,t.default=r(n(6155)).default},7852:function(e,t,n){"use strict";var r=n(5751);t.default=void 0,t.default=r(n(5950)).default},7893:function(e,t,n){"use strict";var r=n(5751);t.default=void 0,t.default=r(n(7041)).default},2521:function(e,t,n){"use strict";var r=n(5751);t.default=void 0,t.default=r(n(4979)).default},1215:function(e,t,n){"use strict";var r,i,a="object"==typeof globalThis?globalThis:"object"==typeof self?self:"object"==typeof window?window:"object"==typeof n.g?n.g:{},o=(i=(r="Prism"in a)?a.Prism:void 0,function(){r?a.Prism=i:delete a.Prism,r=void 0,i=void 0});a.Prism={manual:!0,disableWorkerMessageHandler:!0};var s=n(4862),l=n(2921),c=n(9216),d=n(2717),u=n(2049),h=n(9726),p=n(6155);o();var x={}.hasOwnProperty;function m(){}m.prototype=c;var f=new m;function g(e){if("function"!=typeof e||!e.displayName)throw Error("Expected `function` for `grammar`, got `"+e+"`");void 0===f.languages[e.displayName]&&e(f)}e.exports=f,f.highlight=function(e,t){var n,r=c.highlight;if("string"!=typeof e)throw Error("Expected `string` for `value`, got `"+e+"`");if("Object"===f.util.type(t))n=t,t=null;else{if("string"!=typeof t)throw Error("Expected `string` for `name`, got `"+t+"`");if(x.call(f.languages,t))n=f.languages[t];else throw Error("Unknown language: `"+t+"` is not registered")}return r.call(this,e,n,t)},f.register=g,f.alias=function(e,t){var n,r,i,a,o=f.languages,s=e;for(n in t&&((s={})[e]=t),s)for(i=(r="string"==typeof(r=s[n])?[r]:r).length,a=-1;++a>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:r},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:r},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:r.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:r.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var i=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],a=r.variable[1].inside,o=0;o]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}}e.exports=t,t.displayName="clike",t.aliases=[]},2049:function(e){"use strict";function t(e){var t,n;t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/,e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css,(n=e.languages.markup)&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}e.exports=t,t.displayName="css",t.aliases=[]},3336:function(e){"use strict";function t(e){var t;e.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]},Object.keys(t={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"}).forEach(function(n){var r=t[n],i=[];/^\w+$/.test(n)||i.push(/\w+/.exec(n)[0]),"diff"===n&&i.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+r+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:i,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(n)[0]}}}}),Object.defineProperty(e.languages.diff,"PREFIXES",{value:t})}e.exports=t,t.displayName="diff",t.aliases=[]},6155:function(e){"use strict";function t(e){e.languages.javascript=e.languages.extend("clike",{"class-name":[e.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+(/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source)+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),e.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,e.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:e.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:e.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:e.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:e.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:e.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),e.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:e.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),e.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),e.languages.markup&&(e.languages.markup.tag.addInlined("script","javascript"),e.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),e.languages.js=e.languages.javascript}e.exports=t,t.displayName="javascript",t.aliases=["js"]},5950:function(e){"use strict";function t(e){e.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},e.languages.webmanifest=e.languages.json}e.exports=t,t.displayName="json",t.aliases=["webmanifest"]},6412:function(e){"use strict";function t(e){!function(e){var t=e.util.clone(e.languages.javascript),n=/(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source,r=/(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source,i=/(?:\{*\.{3}(?:[^{}]|)*\})/.source;function a(e,t){return RegExp(e=e.replace(//g,function(){return n}).replace(//g,function(){return r}).replace(//g,function(){return i}),t)}i=a(i).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=a(/<\/?(?:[\w.:-]+(?:+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|))?|))**\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:a(//.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:a(/=/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var o=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(o).join(""):""},s=function(t){for(var n=[],r=0;r0&&n[n.length-1].tagName===o(i.content[0].content[1])&&n.pop():"/>"===i.content[i.content.length-1].content||n.push({tagName:o(i.content[0].content[1]),openedBraces:0}):n.length>0&&"punctuation"===i.type&&"{"===i.content?n[n.length-1].openedBraces++:n.length>0&&n[n.length-1].openedBraces>0&&"punctuation"===i.type&&"}"===i.content?n[n.length-1].openedBraces--:a=!0),(a||"string"==typeof i)&&n.length>0&&0===n[n.length-1].openedBraces){var l=o(i);r0&&("string"==typeof t[r-1]||"plain-text"===t[r-1].type)&&(l=o(t[r-1])+l,t.splice(r-1,1),r--),t[r]=new e.Token("plain-text",l,null,l)}i.content&&"string"!=typeof i.content&&s(i.content)}};e.hooks.add("after-tokenize",function(e){("jsx"===e.language||"tsx"===e.language)&&s(e.tokens)})}(e)}e.exports=t,t.displayName="jsx",t.aliases=[]},2717:function(e){"use strict";function t(e){e.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},e.languages.markup.tag.inside["attr-value"].inside.entity=e.languages.markup.entity,e.languages.markup.doctype.inside["internal-subset"].inside=e.languages.markup,e.hooks.add("wrap",function(e){"entity"===e.type&&(e.attributes.title=e.content.value.replace(/&/,"&"))}),Object.defineProperty(e.languages.markup.tag,"addInlined",{value:function(t,n){var r={};r["language-"+n]={pattern:/(^$)/i,lookbehind:!0,inside:e.languages[n]},r.cdata=/^$/i;var i={"included-cdata":{pattern://i,inside:r}};i["language-"+n]={pattern:/[\s\S]+/,inside:e.languages[n]};var a={};a[t]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,function(){return t}),"i"),lookbehind:!0,greedy:!0,inside:i},e.languages.insertBefore("markup","cdata",a)}}),Object.defineProperty(e.languages.markup.tag,"addAttribute",{value:function(t,n){e.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+t+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[n,"language-"+n],inside:e.languages[n]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),e.languages.html=e.languages.markup,e.languages.mathml=e.languages.markup,e.languages.svg=e.languages.markup,e.languages.xml=e.languages.extend("markup",{}),e.languages.ssml=e.languages.xml,e.languages.atom=e.languages.xml,e.languages.rss=e.languages.xml}e.exports=t,t.displayName="markup",t.aliases=["html","mathml","svg","xml","ssml","atom","rss"]},7041:function(e,t,n){"use strict";var r=n(6412),i=n(4979);function a(e){var t,n;e.register(r),e.register(i),t=e.util.clone(e.languages.typescript),e.languages.tsx=e.languages.extend("jsx",t),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"],(n=e.languages.tsx.tag).pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+n.pattern.source+")",n.pattern.flags),n.lookbehind=!0}e.exports=a,a.displayName="tsx",a.aliases=[]},4979:function(e){"use strict";function t(e){var t;e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"],t=e.languages.extend("typescript",{}),delete t["class-name"],e.languages.typescript["class-name"].inside=t,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t}}}}),e.languages.ts=e.languages.typescript}e.exports=t,t.displayName="typescript",t.aliases=["ts"]},166:function(e){"use strict";e.exports=function(e){var t="string"==typeof e?e.charCodeAt(0):e;return t>=97&&t<=122||t>=65&&t<=90}},2783:function(e,t,n){"use strict";var r=n(166),i=n(1250);e.exports=function(e){return r(e)||i(e)}},1250:function(e){"use strict";e.exports=function(e){var t="string"==typeof e?e.charCodeAt(0):e;return t>=48&&t<=57}},9956:function(e){"use strict";e.exports=function(e){var t="string"==typeof e?e.charCodeAt(0):e;return t>=97&&t<=102||t>=65&&t<=70||t>=48&&t<=57}},1e3:function(e){"use strict";var t;e.exports=function(e){var n,r="&"+e+";";return(t=t||document.createElement("i")).innerHTML=r,(59!==(n=t.textContent).charCodeAt(n.length-1)||"semi"===e)&&n!==r&&n}},2921:function(e,t,n){"use strict";var r=n(7854),i=n(1636),a=n(1250),o=n(9956),s=n(2783),l=n(1e3);e.exports=function(e,t){var n,a,o={};for(a in t||(t={}),h)n=t[a],o[a]=null==n?h[a]:n;return(o.position.indent||o.position.start)&&(o.indent=o.position.indent||[],o.position=o.position.start),function(e,t){var n,a,o,h,y,b,w,k,I,D,E,F,A,C,j,P,S,T,N,_,B,O=t.additional,R=t.nonTerminated,q=t.text,L=t.reference,M=t.warning,z=t.textContext,H=t.referenceContext,$=t.warningContext,W=t.position,K=t.indent||[],U=e.length,V=0,G=-1,Z=W.column||1,J=W.line||1,Q="",Y=[];for("string"==typeof O&&(O=O.charCodeAt(0)),T=X(),D=M?function(e,t){var n=X();n.column+=t,n.offset+=t,M.call($,v[e],n,e)}:u,V--,U++;++V=55296&&n<=57343||n>1114111?(D(7,_),k=d(65533)):k in i?(D(6,_),k=i[k]):(F="",((a=k)>=1&&a<=8||11===a||a>=13&&a<=31||a>=127&&a<=159||a>=64976&&a<=65007||(65535&a)==65535||(65535&a)==65534)&&D(6,_),k>65535&&(k-=65536,F+=d(k>>>10|55296),k=56320|1023&k),k=F+d(k))):P!==p&&D(4,_)}k?(ee(),T=X(),V=B-1,Z+=B-j+1,Y.push(k),N=X(),N.offset++,L&&L.call(H,k,{start:T,end:N},e.slice(j-1,B)),T=N):(b=e.slice(j-1,B),Q+=b,Z+=b.length,V=B-1)}else 10===w&&(J++,G++,Z=0),w==w?(Q+=d(w),Z++):ee();return Y.join("");function X(){return{line:J,column:Z,offset:V+(W.offset||0)}}function ee(){Q&&(Y.push(Q),q&&q.call(z,Q,{start:T,end:X()}),Q="")}}(e,o)};var c={}.hasOwnProperty,d=String.fromCharCode,u=Function.prototype,h={warning:null,reference:null,text:null,warningContext:null,referenceContext:null,textContext:null,position:{},additional:null,attribute:!1,nonTerminated:!0},p="named",x="hexadecimal",m="decimal",f={};f[x]=16,f[m]=10;var g={};g[p]=s,g[m]=a,g[x]=o;var v={};v[1]="Named character references must be terminated by a semicolon",v[2]="Numeric character references must be terminated by a semicolon",v[3]="Named character references cannot be empty",v[4]="Numeric character references cannot be empty",v[5]="Named character references must be known",v[6]="Numeric character references cannot be disallowed",v[7]="Numeric character references cannot be outside the permissible Unicode range"},9216:function(e,t,n){var r=function(e){var t=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,n=0,r={},i={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(t){return t instanceof a?new a(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/=d.reach));k+=w.value.length,w=w.next){var I,D=w.value;if(n.length>t.length)return;if(!(D instanceof a)){var E=1;if(g){if(!(I=o(b,k,t,f))||I.index>=t.length)break;var F=I.index,A=I.index+I[0].length,C=k;for(C+=w.value.length;F>=C;)C+=(w=w.next).value.length;if(C-=w.value.length,k=C,w.value instanceof a)continue;for(var j=w;j!==n.tail&&(Cd.reach&&(d.reach=N);var _=w.prev;if(S&&(_=l(n,_,S),k+=S.length),function(e,t,n){for(var r=t.next,i=0;i1){var B={cause:u+","+p,reach:N};e(t,n,r,w.prev,k,B),d&&B.reach>d.reach&&(d.reach=B.reach)}}}}}}(e,c,t,c.head,0),function(e){for(var t=[],n=e.head.next;n!==e.tail;)t.push(n.value),n=n.next;return t}(c)},hooks:{all:{},add:function(e,t){var n=i.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=i.hooks.all[e];if(n&&n.length)for(var r,a=0;r=n[a++];)r(t)}},Token:a};function a(e,t,n,r){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length}function o(e,t,n,r){e.lastIndex=t;var i=e.exec(n);if(i&&r&&i[1]){var a=i[1].length;i.index+=a,i[0]=i[0].slice(a)}return i}function s(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function l(e,t,n){var r=t.next,i={value:n,prev:t,next:r};return t.next=i,r.prev=i,e.length++,i}if(e.Prism=i,a.stringify=function e(t,n){if("string"==typeof t)return t;if(Array.isArray(t)){var r="";return t.forEach(function(t){r+=e(t,n)}),r}var a={type:t.type,content:e(t.content,n),tag:"span",classes:["token",t.type],attributes:{},language:n},o=t.alias;o&&(Array.isArray(o)?Array.prototype.push.apply(a.classes,o):a.classes.push(o)),i.hooks.run("wrap",a);var s="";for(var l in a.attributes)s+=" "+l+'="'+(a.attributes[l]||"").replace(/"/g,""")+'"';return"<"+a.tag+' class="'+a.classes.join(" ")+'"'+s+">"+a.content+""},!e.document)return e.addEventListener&&(i.disableWorkerMessageHandler||e.addEventListener("message",function(t){var n=JSON.parse(t.data),r=n.language,a=n.code,o=n.immediateClose;e.postMessage(i.highlight(a,i.languages[r],r)),o&&e.close()},!1)),i;var c=i.util.currentScript();function d(){i.manual||i.highlightAll()}if(c&&(i.filename=c.src,c.hasAttribute("data-manual")&&(i.manual=!0)),!i.manual){var u=document.readyState;"loading"===u||"interactive"===u&&c&&c.defer?document.addEventListener("DOMContentLoaded",d):window.requestAnimationFrame?window.requestAnimationFrame(d):window.setTimeout(d,16)}return i}("undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{});e.exports&&(e.exports=r),void 0!==n.g&&(n.g.Prism=r)},6774:function(e){e.exports=function(e,t,n,r){var i=n?n.call(r,e,t):void 0;if(void 0!==i)return!!i;if(e===t)return!0;if("object"!=typeof e||!e||"object"!=typeof t||!t)return!1;var a=Object.keys(e),o=Object.keys(t);if(a.length!==o.length)return!1;for(var s=Object.prototype.hasOwnProperty.bind(t),l=0;lr});let r={title:"React Native Testing Library",description:"Helps you to write better tests with less effort.",icon:"/img/owl.png",route:{cleanUrls:!0},themeConfig:{enableContentAnimation:!0,enableScrollToTop:!0,outlineTitle:"Contents",footer:{message:"Copyright \xa9 2026 Callstack Open Source"},socialLinks:[{icon:"github",mode:"link",content:"https://github.com/callstack/react-native-testing-library"}],locales:[],nav:{"12.x":[{text:"Docs",link:"/12.x/docs/start/intro",activeMatch:"^/docs/"},{text:"Cookbook",link:"/12.x/cookbook/",activeMatch:"^/cookbook/"},{text:"Examples",link:"https://github.com/callstack/react-native-testing-library/tree/main/examples"}],"13.x":[{text:"Docs",link:"/docs/start/intro",activeMatch:"^/docs/"},{text:"Cookbook",link:"/cookbook/",activeMatch:"^/cookbook/"},{text:"Examples",link:"https://github.com/callstack/react-native-testing-library/tree/main/examples"}],"14.x":[{text:"Docs",link:"/14.x/docs/start/intro",activeMatch:"^/docs/"},{text:"Cookbook",link:"/14.x/cookbook/",activeMatch:"^/cookbook/"},{text:"Examples",link:"https://github.com/callstack/react-native-testing-library/tree/main/examples"}]},sidebar:{"/12.x/cookbook":[{text:"Introduction",link:"/12.x/cookbook/index",_fileKey:"12.x/cookbook/index"},{text:"Basic Recipes",collapsible:!0,collapsed:!1,items:[{text:"Async tests",link:"/12.x/cookbook/basics/async-tests",_fileKey:"12.x/cookbook/basics/async-tests"},{text:"Custom `render` function",link:"/12.x/cookbook/basics/custom-render",_fileKey:"12.x/cookbook/basics/custom-render"}],link:"",_fileKey:""},{text:"Advanced Recipes",collapsible:!0,collapsed:!1,items:[{text:"Network Requests",link:"/12.x/cookbook/advanced/network-requests",_fileKey:"12.x/cookbook/advanced/network-requests"}],link:"",_fileKey:""},{text:"State Management Recipes",collapsible:!0,collapsed:!1,items:[{text:"Jotai",link:"/12.x/cookbook/state-management/jotai",_fileKey:"12.x/cookbook/state-management/jotai"}],link:"",_fileKey:""}],"/12.x/docs":[{text:"Getting started",collapsible:!0,collapsed:!1,items:[{text:"Introduction",link:"/12.x/docs/start/intro",_fileKey:"12.x/docs/start/intro"},{text:"Quick Start",link:"/12.x/docs/start/quick-start",_fileKey:"12.x/docs/start/quick-start"}],link:"",_fileKey:""},{text:"API reference",collapsible:!0,collapsed:!1,items:[{text:"Render function",link:"/12.x/docs/api/render",_fileKey:"12.x/docs/api/render"},{text:"Screen object",link:"/12.x/docs/api/screen",_fileKey:"12.x/docs/api/screen"},{text:"Queries",link:"/12.x/docs/api/queries",_fileKey:"12.x/docs/api/queries"},{text:"Jest matchers",link:"/12.x/docs/api/jest-matchers",_fileKey:"12.x/docs/api/jest-matchers"},{text:"Triggering events",collapsible:!0,collapsed:!1,items:[{text:"User Event",link:"/12.x/docs/api/events/user-event",_fileKey:"12.x/docs/api/events/user-event"},{text:"Fire Event",link:"/12.x/docs/api/events/fire-event",_fileKey:"12.x/docs/api/events/fire-event"}],link:"",_fileKey:""},{text:"Miscellaneous",collapsible:!0,collapsed:!1,items:[{text:"Render Hook function",link:"/12.x/docs/api/misc/render-hook",_fileKey:"12.x/docs/api/misc/render-hook"},{text:"Async utilities",link:"/12.x/docs/api/misc/async",_fileKey:"12.x/docs/api/misc/async"},{text:"Configuration",link:"/12.x/docs/api/misc/config",_fileKey:"12.x/docs/api/misc/config"},{text:"Accessibility",link:"/12.x/docs/api/misc/accessibility",_fileKey:"12.x/docs/api/misc/accessibility"},{text:"Other helpers",link:"/12.x/docs/api/misc/other",_fileKey:"12.x/docs/api/misc/other"}],link:"",_fileKey:""}],link:"/12.x/docs/api",_fileKey:"12.x/docs/api"},{text:"Guides",collapsible:!0,collapsed:!1,items:[{text:"How should I query?",link:"/12.x/docs/guides/how-to-query",_fileKey:"12.x/docs/guides/how-to-query"},{text:"Troubleshooting",link:"/12.x/docs/guides/troubleshooting",_fileKey:"12.x/docs/guides/troubleshooting"},{text:"FAQ",link:"/12.x/docs/guides/faq",_fileKey:"12.x/docs/guides/faq"},{text:"Community resources",link:"/12.x/docs/guides/community-resources",_fileKey:"12.x/docs/guides/community-resources"}],link:"",_fileKey:""},{text:"Advanced Guides",collapsible:!0,collapsed:!1,items:[{text:"Testing environment",link:"/12.x/docs/advanced/testing-env",_fileKey:"12.x/docs/advanced/testing-env"},{text:"Understanding `act` function",link:"/12.x/docs/advanced/understanding-act",_fileKey:"12.x/docs/advanced/understanding-act"}],link:"",_fileKey:""},{text:"Migration Guides",collapsible:!0,collapsed:!0,items:[{text:"Migration to 12.x",link:"/12.x/docs/migration/v12",_fileKey:"12.x/docs/migration/v12"},{text:"Migration to built-in Jest matchers",link:"/12.x/docs/migration/jest-matchers",_fileKey:"12.x/docs/migration/jest-matchers"},{text:"Previous versions",collapsible:!0,collapsed:!0,items:[{text:"Migration to 11.x",link:"/12.x/docs/migration/previous/v11",_fileKey:"12.x/docs/migration/previous/v11"},{text:"Migration to 9.x",link:"/12.x/docs/migration/previous/v9",_fileKey:"12.x/docs/migration/previous/v9"},{text:"Migration to 7.x",link:"/12.x/docs/migration/previous/v7",_fileKey:"12.x/docs/migration/previous/v7"},{text:"Migration to 2.x",link:"/12.x/docs/migration/previous/v2",_fileKey:"12.x/docs/migration/previous/v2"}],link:"",_fileKey:""}],link:"",_fileKey:""}],"/cookbook":[{text:"Introduction",link:"/cookbook/index",_fileKey:"13.x/cookbook/index"},{text:"Basic Recipes",collapsible:!0,collapsed:!1,items:[{text:"Async tests",link:"/cookbook/basics/async-tests",_fileKey:"13.x/cookbook/basics/async-tests"},{text:"Custom `render` function",link:"/cookbook/basics/custom-render",_fileKey:"13.x/cookbook/basics/custom-render"}],link:"",_fileKey:""},{text:"Advanced Recipes",collapsible:!0,collapsed:!1,items:[{text:"Network Requests",link:"/cookbook/advanced/network-requests",_fileKey:"13.x/cookbook/advanced/network-requests"}],link:"",_fileKey:""},{text:"State Management Recipes",collapsible:!0,collapsed:!1,items:[{text:"Jotai",link:"/cookbook/state-management/jotai",_fileKey:"13.x/cookbook/state-management/jotai"}],link:"",_fileKey:""}],"/docs":[{text:"Getting started",collapsible:!0,collapsed:!1,items:[{text:"Introduction",link:"/docs/start/intro",_fileKey:"13.x/docs/start/intro"},{text:"Quick Start",link:"/docs/start/quick-start",_fileKey:"13.x/docs/start/quick-start"}],link:"",_fileKey:""},{text:"API reference",collapsible:!0,collapsed:!1,items:[{text:"Render function",link:"/docs/api/render",_fileKey:"13.x/docs/api/render"},{text:"Screen object",link:"/docs/api/screen",_fileKey:"13.x/docs/api/screen"},{text:"Queries",link:"/docs/api/queries",_fileKey:"13.x/docs/api/queries"},{text:"Jest matchers",link:"/docs/api/jest-matchers",_fileKey:"13.x/docs/api/jest-matchers"},{text:"Triggering events",collapsible:!0,collapsed:!1,items:[{text:"User Event",link:"/docs/api/events/user-event",_fileKey:"13.x/docs/api/events/user-event"},{text:"Fire Event",link:"/docs/api/events/fire-event",_fileKey:"13.x/docs/api/events/fire-event"}],link:"",_fileKey:""},{text:"Miscellaneous",collapsible:!0,collapsed:!1,items:[{text:"Render Hook function",link:"/docs/api/misc/render-hook",_fileKey:"13.x/docs/api/misc/render-hook"},{text:"Async utilities",link:"/docs/api/misc/async",_fileKey:"13.x/docs/api/misc/async"},{text:"Configuration",link:"/docs/api/misc/config",_fileKey:"13.x/docs/api/misc/config"},{text:"Accessibility",link:"/docs/api/misc/accessibility",_fileKey:"13.x/docs/api/misc/accessibility"},{text:"Other helpers",link:"/docs/api/misc/other",_fileKey:"13.x/docs/api/misc/other"}],link:"",_fileKey:""}],link:"/docs/api",_fileKey:"13.x/docs/api"},{text:"Guides",collapsible:!0,collapsed:!1,items:[{text:"How should I query?",link:"/docs/guides/how-to-query",_fileKey:"13.x/docs/guides/how-to-query"},{text:"React 19 & Suspense Support",link:"/docs/guides/react-19",_fileKey:"13.x/docs/guides/react-19"},{text:"Troubleshooting",link:"/docs/guides/troubleshooting",_fileKey:"13.x/docs/guides/troubleshooting"},{text:"FAQ",link:"/docs/guides/faq",_fileKey:"13.x/docs/guides/faq"},{text:"Community resources",link:"/docs/guides/community-resources",_fileKey:"13.x/docs/guides/community-resources"}],link:"",_fileKey:""},{text:"Advanced Guides",collapsible:!0,collapsed:!1,items:[{text:"Testing environment",link:"/docs/advanced/testing-env",_fileKey:"13.x/docs/advanced/testing-env"},{text:"Understanding `act` function",link:"/docs/advanced/understanding-act",_fileKey:"13.x/docs/advanced/understanding-act"},{text:"Third-Party Library Integration",link:"/docs/advanced/third-party-integration",_fileKey:"13.x/docs/advanced/third-party-integration"}],link:"",_fileKey:""},{text:"Migration Guides",collapsible:!0,collapsed:!0,items:[{text:"Migration to 13.x",link:"/docs/migration/v13",_fileKey:"13.x/docs/migration/v13"},{text:"Migration to built-in Jest matchers",link:"/docs/migration/jest-matchers",_fileKey:"13.x/docs/migration/jest-matchers"},{text:"Previous versions",collapsible:!0,collapsed:!0,items:[{text:"Migration to 12.x",link:"/docs/migration/previous/v12",_fileKey:"13.x/docs/migration/previous/v12"},{text:"Migration to 11.x",link:"/docs/migration/previous/v11",_fileKey:"13.x/docs/migration/previous/v11"},{text:"Migration to 9.x",link:"/docs/migration/previous/v9",_fileKey:"13.x/docs/migration/previous/v9"},{text:"Migration to 7.x",link:"/docs/migration/previous/v7",_fileKey:"13.x/docs/migration/previous/v7"},{text:"Migration to 2.x",link:"/docs/migration/previous/v2",_fileKey:"13.x/docs/migration/previous/v2"}],link:"",_fileKey:""}],link:"",_fileKey:""}],"/14.x/cookbook":[{text:"Introduction",link:"/14.x/cookbook/index",_fileKey:"14.x/cookbook/index"},{text:"Basic Recipes",collapsible:!0,collapsed:!1,items:[{text:"Async Events",link:"/14.x/cookbook/basics/async-events",_fileKey:"14.x/cookbook/basics/async-events"},{text:"Custom `render` function",link:"/14.x/cookbook/basics/custom-render",_fileKey:"14.x/cookbook/basics/custom-render"}],link:"",_fileKey:""},{text:"Advanced Recipes",collapsible:!0,collapsed:!1,items:[{text:"Network Requests",link:"/14.x/cookbook/advanced/network-requests",_fileKey:"14.x/cookbook/advanced/network-requests"}],link:"",_fileKey:""},{text:"State Management Recipes",collapsible:!0,collapsed:!1,items:[{text:"Jotai",link:"/14.x/cookbook/state-management/jotai",_fileKey:"14.x/cookbook/state-management/jotai"}],link:"",_fileKey:""}],"/14.x/docs":[{text:"Getting started",collapsible:!0,collapsed:!1,items:[{text:"Introduction",link:"/14.x/docs/start/intro",_fileKey:"14.x/docs/start/intro"},{text:"Quick Start",link:"/14.x/docs/start/quick-start",_fileKey:"14.x/docs/start/quick-start"},{text:"v14 Migration",link:"/14.x/docs/migration/v14"}],link:"",_fileKey:""},{text:"API reference",collapsible:!0,collapsed:!1,items:[{text:"Render function",link:"/14.x/docs/api/render",_fileKey:"14.x/docs/api/render"},{text:"Screen object",link:"/14.x/docs/api/screen",_fileKey:"14.x/docs/api/screen"},{text:"Queries",link:"/14.x/docs/api/queries",_fileKey:"14.x/docs/api/queries"},{text:"Jest matchers",link:"/14.x/docs/api/jest-matchers",_fileKey:"14.x/docs/api/jest-matchers"},{text:"Triggering events",collapsible:!0,collapsed:!1,items:[{text:"User Event",link:"/14.x/docs/api/events/user-event",_fileKey:"14.x/docs/api/events/user-event"},{text:"Fire Event",link:"/14.x/docs/api/events/fire-event",_fileKey:"14.x/docs/api/events/fire-event"}],link:"",_fileKey:""},{text:"Miscellaneous",collapsible:!0,collapsed:!1,items:[{text:"Render Hook function",link:"/14.x/docs/api/misc/render-hook",_fileKey:"14.x/docs/api/misc/render-hook"},{text:"Async utilities",link:"/14.x/docs/api/misc/async",_fileKey:"14.x/docs/api/misc/async"},{text:"Configuration",link:"/14.x/docs/api/misc/config",_fileKey:"14.x/docs/api/misc/config"},{text:"Accessibility",link:"/14.x/docs/api/misc/accessibility",_fileKey:"14.x/docs/api/misc/accessibility"},{text:"Other helpers",link:"/14.x/docs/api/misc/other",_fileKey:"14.x/docs/api/misc/other"}],link:"",_fileKey:""}],link:"/14.x/docs/api",_fileKey:"14.x/docs/api"},{text:"Guides",collapsible:!0,collapsed:!1,items:[{text:"How should I query?",link:"/14.x/docs/guides/how-to-query",_fileKey:"14.x/docs/guides/how-to-query"},{text:"Troubleshooting",link:"/14.x/docs/guides/troubleshooting",_fileKey:"14.x/docs/guides/troubleshooting"},{text:"FAQ",link:"/14.x/docs/guides/faq",_fileKey:"14.x/docs/guides/faq"},{text:"Community resources",link:"/14.x/docs/guides/community-resources",_fileKey:"14.x/docs/guides/community-resources"}],link:"",_fileKey:""},{text:"Advanced Guides",collapsible:!0,collapsed:!1,items:[{text:"Testing environment",link:"/14.x/docs/advanced/testing-env",_fileKey:"14.x/docs/advanced/testing-env"},{text:"Understanding `act` function",link:"/14.x/docs/advanced/understanding-act",_fileKey:"14.x/docs/advanced/understanding-act"},{text:"Third-Party Library Integration",link:"/14.x/docs/advanced/third-party-integration",_fileKey:"14.x/docs/advanced/third-party-integration"}],link:"",_fileKey:""},{text:"Migration Guides",collapsible:!0,collapsed:!0,items:[{text:"Migration to 14.x",link:"/14.x/docs/migration/v14",_fileKey:"14.x/docs/migration/v14"},{text:"Migration to built-in Jest matchers",link:"/14.x/docs/migration/jest-matchers",_fileKey:"14.x/docs/migration/jest-matchers"},{text:"Migration to 13.x",link:"/14.x/docs/migration/v13",_fileKey:"14.x/docs/migration/v13"},{text:"Migration to 12.x",link:"/14.x/docs/migration/v12",_fileKey:"14.x/docs/migration/v12"},{text:"Migration to 11.x",link:"/14.x/docs/migration/v11",_fileKey:"14.x/docs/migration/v11"},{text:"Migration to 9.x",link:"/14.x/docs/migration/v9",_fileKey:"14.x/docs/migration/v9"},{text:"Migration to 7.x",link:"/14.x/docs/migration/v7",_fileKey:"14.x/docs/migration/v7"},{text:"Migration to 2.x",link:"/14.x/docs/migration/v2",_fileKey:"14.x/docs/migration/v2"}],link:"",_fileKey:""}]}},base:"/react-native-testing-library/",lang:"",locales:[],logo:"/img/owl.png",logoText:"React Native Testing Library",ssg:!0,multiVersion:{default:"13.x",versions:["12.x","13.x","14.x"]},search:{versioned:!0},pages:[{title:"Network Requests",routePath:"/react-native-testing-library/12.x/cookbook/advanced/network-requests",lang:"",toc:[{text:"Introduction",id:"introduction",depth:2,charIndex:3},{text:"Phonebook Example",id:"phonebook-example",depth:2,charIndex:568},{text:"Start testing with a simple test",id:"start-testing-with-a-simple-test",depth:2,charIndex:1294},{text:"Testing error handling",id:"testing-error-handling",depth:2,charIndex:2353},{text:"Global guarding against unwanted API requests",id:"global-guarding-against-unwanted-api-requests",depth:2,charIndex:2920},{text:"Conclusion",id:"conclusion",depth:2,charIndex:3508},{text:"Further Reading and Alternatives",id:"further-reading-and-alternatives",depth:2,charIndex:4130}],frontmatter:{},version:"12.x",_relativePath:"12.x/cookbook/advanced/network-requests.md"},{title:"Async tests",routePath:"/react-native-testing-library/12.x/cookbook/basics/async-tests",lang:"",toc:[{text:"Summary",id:"summary",depth:2,charIndex:3},{text:"Example",id:"example",depth:3,charIndex:911},{text:"Async utilities",id:"async-utilities",depth:2,charIndex:1008},{text:"`findBy*` queries",id:"findby-queries",depth:3,charIndex:-1},{text:"Example",id:"example-1",depth:4,charIndex:1622},{text:"`waitFor` function",id:"waitfor-function",depth:3,charIndex:-1},{text:"Example",id:"example-2",depth:4,charIndex:2128},{text:"`waitForElementToBeRemoved` function",id:"waitforelementtoberemoved-function",depth:3,charIndex:-1},{text:"Example",id:"example-3",depth:4,charIndex:2743},{text:"Fake Timers",id:"fake-timers",depth:2,charIndex:2756}],frontmatter:{},version:"12.x",_relativePath:"12.x/cookbook/basics/async-tests.md"},{title:"Custom `render` function",routePath:"/react-native-testing-library/12.x/cookbook/basics/custom-render",lang:"",toc:[{text:"Summary",id:"summary",depth:3,charIndex:25},{text:"Example",id:"example",depth:3,charIndex:318},{text:"More info",id:"more-info",depth:3,charIndex:360},{text:"Additional params",id:"additional-params",depth:4,charIndex:372},{text:"Multiple functions",id:"multiple-functions",depth:4,charIndex:571},{text:"Async function",id:"async-function",depth:4,charIndex:787}],frontmatter:{},version:"12.x",_relativePath:"12.x/cookbook/basics/custom-render.md"},{title:"Introduction",routePath:"/react-native-testing-library/12.x/cookbook/",lang:"",toc:[{text:"What's Inside the Cookbook?",id:"whats-inside-the-cookbook",depth:2,charIndex:434},{text:"What's Next?",id:"whats-next",depth:2,charIndex:1045}],frontmatter:{},version:"12.x",_relativePath:"12.x/cookbook/index.md"},{title:"Jotai",routePath:"/react-native-testing-library/12.x/cookbook/state-management/jotai",lang:"",toc:[{text:"Introduction",id:"introduction",depth:2,charIndex:3},{text:"Task List Example",id:"task-list-example",depth:2,charIndex:337},{text:"Starting with a Simple Test",id:"starting-with-a-simple-test",depth:2,charIndex:566},{text:"Custom Render Function to populate Jotai Atoms with Initial Values",id:"custom-render-function-to-populate-jotai-atoms-with-initial-values",depth:2,charIndex:860},{text:"Testing the `TaskList` Component with initial tasks",id:"testing-the-tasklist-component-with-initial-tasks",depth:2,charIndex:-1},{text:"Modifying atom outside of React components",id:"modifying-atom-outside-of-react-components",depth:2,charIndex:1773},{text:"Testing atom outside of React components",id:"testing-atom-outside-of-react-components",depth:2,charIndex:2022},{text:"Conclusion",id:"conclusion",depth:2,charIndex:2358}],frontmatter:{},version:"12.x",_relativePath:"12.x/cookbook/state-management/jotai.md"},{title:"Testing environment",routePath:"/react-native-testing-library/12.x/docs/advanced/testing-env",lang:"",toc:[{text:"React renderers",id:"react-renderers",depth:2,charIndex:659},{text:"React Test Renderer",id:"react-test-renderer",depth:2,charIndex:1382},{text:"Element tree",id:"element-tree",depth:2,charIndex:2783},{text:"Host and composite components",id:"host-and-composite-components",depth:2,charIndex:3389},{text:"Differentiating between host and composite elements",id:"differentiating-between-host-and-composite-elements",depth:3,charIndex:5113},{text:"Tree nodes",id:"tree-nodes",depth:2,charIndex:5538},{text:"Asserting props",id:"asserting-props",depth:3,charIndex:5854},{text:"Tree navigation",id:"tree-navigation",depth:2,charIndex:6557},{text:"Queries",id:"queries",depth:2,charIndex:7290}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/advanced/testing-env.mdx"},{title:"Understanding `act` function",routePath:"/react-native-testing-library/12.x/docs/advanced/understanding-act",lang:"",toc:[{text:"`act` warnings",id:"act-warnings",depth:2,charIndex:-1},{text:"Synchronous `act`",id:"synchronous-act",depth:2,charIndex:-1},{text:"Responsibility",id:"responsibility",depth:3,charIndex:575},{text:"When to use act",id:"when-to-use-act",depth:3,charIndex:1673},{text:"Implementation",id:"implementation",depth:3,charIndex:2765},{text:"Asynchronous `act`",id:"asynchronous-act",depth:2,charIndex:-1},{text:"Asynchronous code",id:"asynchronous-code",depth:3,charIndex:3756},{text:"Solution with fake timers",id:"solution-with-fake-timers",depth:3,charIndex:4462},{text:"Solution with real timers",id:"solution-with-real-timers",depth:3,charIndex:4772},{text:"Async act warning",id:"async-act-warning",depth:3,charIndex:5594},{text:"References",id:"references",depth:2,charIndex:6029}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/advanced/understanding-act.mdx"},{title:"API Overview",routePath:"/react-native-testing-library/12.x/docs/api",lang:"",toc:[],frontmatter:{uri:"/api"},version:"12.x",_relativePath:"12.x/docs/api.md"},{title:"Fire Event API",routePath:"/react-native-testing-library/12.x/docs/api/events/fire-event",lang:"",toc:[{text:"`fireEvent.press`",id:"fireeventpress",depth:3,charIndex:-1},{text:"`fireEvent.changeText`",id:"fireeventchangetext",depth:3,charIndex:-1},{text:"`fireEvent.scroll`",id:"fireeventscroll",depth:3,charIndex:-1},{text:"On a `ScrollView`",id:"on-a-scrollview",depth:4,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/events/fire-event.mdx"},{title:"User Event interactions",routePath:"/react-native-testing-library/12.x/docs/api/events/user-event",lang:"",toc:[{text:"Comparison with Fire Event API",id:"comparison-with-fire-event-api",depth:2,charIndex:81},{text:"`setup()`",id:"setup",depth:2,charIndex:-1},{text:"Options",id:"options",depth:3,charIndex:-1},{text:"`press()`",id:"press",depth:2,charIndex:-1},{text:"`longPress()`",id:"longpress",depth:2,charIndex:-1},{text:"Options",id:"options-1",depth:3,charIndex:-1},{text:"`type()`",id:"type",depth:2,charIndex:-1},{text:"Options",id:"options-2",depth:3,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events",depth:3,charIndex:-1},{text:"`clear()`",id:"clear",depth:2,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-1",depth:3,charIndex:-1},{text:"`paste()`",id:"paste",depth:2,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-2",depth:3,charIndex:-1},{text:"`scrollTo()`",id:"scroll-to",depth:2,charIndex:-1},{text:"Options",id:"options-3",depth:3,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-3",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/events/user-event.mdx"},{title:"Jest matchers",routePath:"/react-native-testing-library/12.x/docs/api/jest-matchers",lang:"",toc:[{text:"Setup",id:"setup",depth:2,charIndex:250},{text:"Migration from legacy Jest Native matchers.",id:"migration-from-legacy-jest-native-matchers",depth:2,charIndex:563},{text:"Checking element existence",id:"checking-element-existence",depth:2,charIndex:727},{text:"`toBeOnTheScreen()`",id:"tobeonthescreen",depth:3,charIndex:-1},{text:"Element Content",id:"element-content",depth:2,charIndex:981},{text:"`toHaveTextContent()`",id:"tohavetextcontent",depth:3,charIndex:-1},{text:"`toContainElement()`",id:"tocontainelement",depth:3,charIndex:-1},{text:"`toBeEmptyElement()`",id:"tobeemptyelement",depth:3,charIndex:-1},{text:"Checking element state",id:"checking-element-state",depth:2,charIndex:1467},{text:"`toHaveDisplayValue()`",id:"tohavedisplayvalue",depth:3,charIndex:-1},{text:"`toHaveAccessibilityValue()`",id:"tohaveaccessibilityvalue",depth:3,charIndex:-1},{text:"`toBeEnabled()` / `toBeDisabled`",id:"tobeenabled--tobedisabled",depth:3,charIndex:-1},{text:"`toBeSelected()`",id:"tobeselected",depth:3,charIndex:-1},{text:"`toBeChecked()` / `toBePartiallyChecked()`",id:"tobechecked--tobepartiallychecked",depth:3,charIndex:-1},{text:"`toBeExpanded()` / `toBeCollapsed()`",id:"tobeexpanded--tobecollapsed",depth:3,charIndex:-1},{text:"`toBeBusy()`",id:"tobebusy",depth:3,charIndex:-1},{text:"Checking element style",id:"checking-element-style",depth:2,charIndex:4079},{text:"`toBeVisible()`",id:"tobevisible",depth:3,charIndex:-1},{text:"`toHaveStyle()`",id:"tohavestyle",depth:3,charIndex:-1},{text:"Other matchers",id:"other-matchers",depth:2,charIndex:4468},{text:"`toHaveAccessibleName()`",id:"tohaveaccessiblename",depth:3,charIndex:-1},{text:"`toHaveProp()`",id:"tohaveprop",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/jest-matchers.mdx"},{title:"Accessibility",routePath:"/react-native-testing-library/12.x/docs/api/misc/accessibility",lang:"",toc:[{text:"`isHiddenFromAccessibility`",id:"ishiddenfromaccessibility",depth:2,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/misc/accessibility.mdx"},{title:"Async utilities",routePath:"/react-native-testing-library/12.x/docs/api/misc/async",lang:"",toc:[{text:"`findBy*` queries",id:"findby-queries",depth:2,charIndex:-1},{text:"`waitFor`",id:"waitfor",depth:2,charIndex:-1},{text:"Using a React Native version < 0.71 with Jest fake timers",id:"using-a-react-native-version--071-with-jest-fake-timers",depth:3,charIndex:1885},{text:"`waitForElementToBeRemoved`",id:"waitforelementtoberemoved",depth:2,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/misc/async.mdx"},{title:"Configuration",routePath:"/react-native-testing-library/12.x/docs/api/misc/config",lang:"",toc:[{text:"`configure`",id:"configure",depth:2,charIndex:-1},{text:"`asyncUtilTimeout` option",id:"asyncutiltimeout-option",depth:3,charIndex:-1},{text:"`defaultIncludeHiddenElements` option",id:"defaultincludehiddenelements-option",depth:3,charIndex:-1},{text:"`defaultDebugOptions` option",id:"defaultdebugoptions-option",depth:3,charIndex:-1},{text:"`concurrentRoot` option",id:"concurrentroot-option",depth:3,charIndex:-1},{text:"`resetToDefaults()`",id:"resettodefaults",depth:2,charIndex:-1},{text:"Environment variables",id:"environment-variables",depth:2,charIndex:945},{text:"`RNTL_SKIP_AUTO_CLEANUP`",id:"rntl_skip_auto_cleanup",depth:3,charIndex:-1},{text:"`RNTL_SKIP_AUTO_DETECT_FAKE_TIMERS`",id:"rntl_skip_auto_detect_fake_timers",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/misc/config.mdx"},{title:"Other helpers",routePath:"/react-native-testing-library/12.x/docs/api/misc/other",lang:"",toc:[{text:"`within`, `getQueriesForElement`",id:"within-getqueriesforelement",depth:2,charIndex:-1},{text:"`act`",id:"act",depth:2,charIndex:-1},{text:"`cleanup`",id:"cleanup",depth:2,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/misc/other.mdx"},{title:"`renderHook` function",routePath:"/react-native-testing-library/12.x/docs/api/misc/render-hook",lang:"",toc:[{text:"`options`",id:"options",depth:2,charIndex:-1},{text:"`initialProps`",id:"initialprops",depth:3,charIndex:-1},{text:"`wrapper`",id:"wrapper",depth:3,charIndex:-1},{text:"`RenderHookResult`",id:"renderhookresult",depth:2,charIndex:-1},{text:"`result`",id:"result",depth:3,charIndex:-1},{text:"`rerender`",id:"rerender",depth:3,charIndex:-1},{text:"`unmount`",id:"unmount",depth:3,charIndex:-1},{text:"Examples",id:"examples",depth:2,charIndex:1786},{text:"With `initialProps`",id:"with-initialprops",depth:3,charIndex:-1},{text:"With `wrapper`",id:"with-wrapper",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/misc/render-hook.mdx"},{title:"Queries",routePath:"/react-native-testing-library/12.x/docs/api/queries",lang:"",toc:[{text:"Accessing queries",id:"accessing-queries",depth:2,charIndex:226},{text:"Using `screen` object",id:"using-screen-object",depth:3,charIndex:-1},{text:"Using `render` result",id:"using-render-result",depth:3,charIndex:-1},{text:"Query parts",id:"query-parts",depth:2,charIndex:848},{text:"Query variant",id:"query-variant",depth:2,charIndex:1095},{text:"`getBy*` queries",id:"getby-queries",depth:3,charIndex:-1},{text:"`getAllBy*` queries",id:"getallby-queries",depth:3,charIndex:-1},{text:"`queryBy*` queries",id:"queryby-queries",depth:3,charIndex:-1},{text:"`queryAllBy*` queries",id:"queryallby-queries",depth:3,charIndex:-1},{text:"`findBy*` queries",id:"findby-queries",depth:3,charIndex:-1},{text:"`findAllBy*` queries",id:"findallby-queries",depth:3,charIndex:-1},{text:"Query predicates",id:"query-predicates",depth:2,charIndex:3631},{text:"`*ByRole`",id:"byrole",depth:3,charIndex:-1},{text:"Options",id:"options",depth:4,charIndex:-1},{text:"`*ByLabelText`",id:"bylabeltext",depth:3,charIndex:-1},{text:"`*ByPlaceholderText`",id:"byplaceholdertext",depth:3,charIndex:-1},{text:"`*ByDisplayValue`",id:"bydisplayvalue",depth:3,charIndex:-1},{text:"`*ByText`",id:"bytext",depth:3,charIndex:-1},{text:"`*ByHintText`",id:"byhinttext",depth:3,charIndex:-1},{text:"`*ByTestId`",id:"bytestid",depth:3,charIndex:-1},{text:"Common options",id:"common-options",depth:3,charIndex:9754},{text:"`includeHiddenElements` option",id:"includehiddenelements-option",depth:4,charIndex:-1},{text:"TextMatch type",id:"textmatch-type",depth:2,charIndex:10468},{text:"Examples",id:"examples",depth:3,charIndex:10603},{text:"Options",id:"options-1",depth:3,charIndex:-1},{text:"Precision",id:"precision",depth:4,charIndex:10704},{text:"Normalization",id:"normalization",depth:4,charIndex:11487},{text:"Legacy unit testing helpers",id:"legacy-unit-testing-helpers",depth:2,charIndex:12753},{text:"`UNSAFE_ByType`",id:"unsafe_bytype",depth:3,charIndex:-1},{text:"`UNSAFE_ByProps`",id:"unsafe_byprops",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/queries.mdx"},{title:"`render` function",routePath:"/react-native-testing-library/12.x/docs/api/render",lang:"",toc:[{text:"Options",id:"options",depth:3,charIndex:-1},{text:"`wrapper` option",id:"wrapper-option",depth:4,charIndex:-1},{text:"`concurrentRoot` option",id:"concurrentroot-option",depth:4,charIndex:-1},{text:"`createNodeMock` option",id:"createnodemock-option",depth:4,charIndex:-1},{text:"`unstable_validateStringsRenderedWithinText` option",id:"unstable_validatestringsrenderedwithintext-option",depth:4,charIndex:-1},{text:"Result",id:"result",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/render.mdx"},{title:"`screen` object",routePath:"/react-native-testing-library/12.x/docs/api/screen",lang:"",toc:[{text:"`...queries`",id:"queries",depth:3,charIndex:-1},{text:"Example",id:"example",depth:4,charIndex:549},{text:"`rerender`",id:"rerender",depth:3,charIndex:-1},{text:"`unmount`",id:"unmount",depth:3,charIndex:-1},{text:"`debug`",id:"debug",depth:3,charIndex:-1},{text:"`message` option",id:"message-option",depth:4,charIndex:-1},{text:"`mapProps` option",id:"mapprops-option",depth:4,charIndex:-1},{text:"`toJSON`",id:"tojson",depth:3,charIndex:-1},{text:"`root`",id:"root",depth:3,charIndex:-1},{text:"`UNSAFE_root`",id:"unsafe_root",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/screen.mdx"},{title:"Community resources",routePath:"/react-native-testing-library/12.x/docs/guides/community-resources",lang:"",toc:[{text:"Recommended content",id:"recommended-content",depth:2,charIndex:3},{text:"Older, potentially outdated content",id:"older-potentially-outdated-content",depth:2,charIndex:601}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/guides/community-resources.mdx"},{title:"FAQ",routePath:"/react-native-testing-library/12.x/docs/guides/faq",lang:"",toc:[{text:"Can I test the native features of React Native apps?",id:"can-i-test-the-native-features-of-react-native-apps",depth:2,charIndex:3},{text:"Should I use/migrate to `screen` queries?",id:"should-i-usemigrate-to-screen-queries",depth:2,charIndex:-1},{text:"Should I use/migrate to User Event interactions?",id:"should-i-usemigrate-to-user-event-interactions",depth:2,charIndex:1595}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/guides/faq.mdx"},{title:"How should I query?",routePath:"/react-native-testing-library/12.x/docs/guides/how-to-query",lang:"",toc:[{text:"Query parts",id:"query-parts",depth:2,charIndex:273},{text:"Query variant",id:"query-variant",depth:2,charIndex:521},{text:"Idiomatic query variants",id:"idiomatic-query-variants",depth:3,charIndex:1386},{text:"Query predicate",id:"query-predicate",depth:2,charIndex:2339},{text:"Idiomatic query predicates",id:"idiomatic-query-predicates",depth:3,charIndex:3113},{text:"1. By Role query",id:"1-by-role-query",depth:3,charIndex:-1},{text:"Name option",id:"name-option",depth:4,charIndex:-1},{text:"2. Text input queries",id:"2-text-input-queries",depth:3,charIndex:-1},{text:"3. Other accessible queries",id:"3-other-accessible-queries",depth:3,charIndex:-1},{text:"4. Test ID query",id:"4-test-id-query",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/guides/how-to-query.mdx"},{title:"Troubleshooting",routePath:"/react-native-testing-library/12.x/docs/guides/troubleshooting",lang:"",toc:[{text:"Matching React Native, React & React Test Renderer versions",id:"matching-react-native-react--react-test-renderer-versions",depth:2,charIndex:116},{text:"Example repository",id:"example-repository",depth:2,charIndex:1005},{text:"Undefined component error",id:"undefined-component-error",depth:2,charIndex:1254},{text:"Mocking React Native",id:"mocking-react-native",depth:3,charIndex:2110},{text:"Act warnings",id:"act-warnings",depth:2,charIndex:2372}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/guides/troubleshooting.mdx"},{title:"Migration to built-in Jest matchers",routePath:"/react-native-testing-library/12.x/docs/migration/jest-matchers",lang:"",toc:[{text:"General notes",id:"general-notes",depth:2,charIndex:119},{text:"Usage",id:"usage",depth:2,charIndex:533},{text:"Gradual migration",id:"gradual-migration",depth:3,charIndex:674},{text:"Migration details",id:"migration-details",depth:2,charIndex:905},{text:"Matchers not requiring changes",id:"matchers-not-requiring-changes",depth:3,charIndex:926},{text:"Replaced matchers",id:"replaced-matchers",depth:3,charIndex:1233},{text:"Added matchers",id:"added-matchers",depth:3,charIndex:1626},{text:"Noteworthy details",id:"noteworthy-details",depth:3,charIndex:1688}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/migration/jest-matchers.mdx"},{title:"Migration to 11.x",routePath:"/react-native-testing-library/12.x/docs/migration/previous/v11",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:153},{text:"Update to Jest 28 if you use fake timers",id:"update-to-jest-28-if-you-use-fake-timers",depth:3,charIndex:173},{text:"Refactor legacy `waitForOptions` position",id:"refactor-legacy-waitforoptions-position",depth:3,charIndex:-1},{text:'Triggering non-touch events on targets with `pointerEvents="box-none"` prop',id:"triggering-non-touch-events-on-targets-with-pointereventsbox-none-prop",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:1263}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/migration/previous/v11.mdx"},{title:"Migration to 2.x",routePath:"/react-native-testing-library/12.x/docs/migration/previous/v2",lang:"",toc:[{text:"Dropping Node 8",id:"dropping-node-8",depth:2,charIndex:100},{text:"Auto Cleanup",id:"auto-cleanup",depth:2,charIndex:325},{text:"WaitFor API changes",id:"waitfor-api-changes",depth:2,charIndex:1248},{text:"Removed global `debug` function",id:"removed-global-debug-function",depth:2,charIndex:-1},{text:"Removed global `shallow` function",id:"removed-global-shallow-function",depth:2,charIndex:-1},{text:"Removed functions",id:"removed-functions",depth:2,charIndex:2145},{text:"Some `ByTestId` queries behavior changes",id:"some-bytestid-queries-behavior-changes",depth:2,charIndex:-1},{text:"Deprecated `flushMicrotasksQueue`",id:"deprecated-flushmicrotasksqueue",depth:2,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/migration/previous/v2.mdx"},{title:"Migration to 7.x",routePath:"/react-native-testing-library/12.x/docs/migration/previous/v7",lang:"",toc:[{text:"Guide for `react-native-testing-library` users",id:"guide-for-react-native-testing-library-users",depth:2,charIndex:-1},{text:"Renaming the library",id:"renaming-the-library",depth:3,charIndex:452},{text:"New aliases",id:"new-aliases",depth:3,charIndex:1352},{text:"Renaming `ByPlaceholder` queries",id:"renaming-byplaceholder-queries",depth:3,charIndex:-1},{text:"`fireEvent` support for disabled components",id:"fireevent-support-for-disabled-components",depth:3,charIndex:-1},{text:"Guide for `@testing-library/react-native` users",id:"guide-for-testing-libraryreact-native-users",depth:2,charIndex:-1},{text:'Renaming "wait" helpers',id:"renaming-wait-helpers",depth:3,charIndex:2874},{text:"Changes to `ByTestId` queries",id:"changes-to-bytestid-queries",depth:3,charIndex:-1},{text:"No `ByTitle` queries",id:"no-bytitle-queries",depth:3,charIndex:-1},{text:"No custom Jest configuration",id:"no-custom-jest-configuration",depth:3,charIndex:3628},{text:"Cleanup is included by default",id:"cleanup-is-included-by-default",depth:3,charIndex:3917},{text:"No NativeTestInstance abstraction",id:"no-nativetestinstance-abstraction",depth:3,charIndex:4313},{text:"No `container` nor `baseElement` returned from `render`",id:"no-container-nor-baseelement-returned-from-render",depth:3,charIndex:-1},{text:"Firing events changes",id:"firing-events-changes",depth:3,charIndex:4823}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/migration/previous/v7.mdx"},{title:"Migration to 9.x",routePath:"/react-native-testing-library/12.x/docs/migration/previous/v9",lang:"",toc:[{text:"Support for text match options a.k.a string precision API",id:"support-for-text-match-options-aka-string-precision-api",depth:2,charIndex:284},{text:"Reverted matching text across several nodes",id:"reverted-matching-text-across-several-nodes",depth:2,charIndex:924},{text:"Future plans",id:"future-plans",depth:2,charIndex:1437}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/migration/previous/v9.mdx"},{title:"Migration to 12.x",routePath:"/react-native-testing-library/12.x/docs/migration/v12",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:484},{text:"1. All queries exclude elements hidden from accessibility by default",id:"1-all-queries-exclude-elements-hidden-from-accessibility-by-default",depth:3,charIndex:504},{text:"2. `*ByRole` queries now return only accessibility elements",id:"2-byrole-queries-now-return-only-accessibility-elements",depth:3,charIndex:-1},{text:"Examples",id:"examples",depth:4,charIndex:1510},{text:"3. `*ByText`, `*ByDisplayValue`, `*ByPlaceholderText` queries now return host elements",id:"3-bytext-bydisplayvalue-byplaceholdertext-queries-now-return-host-elements",depth:3,charIndex:-1},{text:"4. `container` API has been renamed to `UNSAFE_root`.",id:"4-container-api-has-been-renamed-to-unsafe_root",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:2923}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/migration/v12.mdx"},{title:"Introduction",routePath:"/react-native-testing-library/12.x/docs/start/intro",lang:"",toc:[{text:"The problem",id:"the-problem",depth:2,charIndex:3},{text:"This solution",id:"this-solution",depth:2,charIndex:479},{text:"Example",id:"example",depth:2,charIndex:988}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/start/intro.md"},{title:"Quick Start",routePath:"/react-native-testing-library/12.x/docs/start/quick-start",lang:"",toc:[{text:"Installation",id:"installation",depth:2,charIndex:3},{text:"Jest matchers",id:"jest-matchers",depth:3,charIndex:223},{text:"ESLint plugin",id:"eslint-plugin",depth:3,charIndex:379}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/start/quick-start.mdx"},{title:"",routePath:"/react-native-testing-library/12.x/",lang:"",toc:[],frontmatter:{pageType:"home",hero:{name:"React Native",text:"Testing Library",image:{src:"/img/owl.png"},tagline:"Helps you to write better tests with less effort.",actions:[{theme:"brand",text:"Quick Start",link:"/docs/start/quick-start"},{theme:"alt",text:"Explore API",link:"/docs/api"}]},features:[{title:"Maintainable",details:"Write maintainable tests for your React Native apps.",icon:"✨"},{title:"Reliable",details:"Promotes testing public APIs and avoiding implementation details.",icon:"βœ…"},{title:"Community Driven",details:"Supported by React Native community and its core contributors.",icon:"❀️"}]},version:"12.x",_relativePath:"12.x/index.md"},{title:"Network Requests",routePath:"/react-native-testing-library/cookbook/advanced/network-requests",lang:"",toc:[{text:"Introduction",id:"introduction",depth:2,charIndex:3},{text:"Phonebook Example",id:"phonebook-example",depth:2,charIndex:568},{text:"Start testing with a simple test",id:"start-testing-with-a-simple-test",depth:2,charIndex:1294},{text:"Testing error handling",id:"testing-error-handling",depth:2,charIndex:2353},{text:"Global guarding against unwanted API requests",id:"global-guarding-against-unwanted-api-requests",depth:2,charIndex:2920},{text:"Conclusion",id:"conclusion",depth:2,charIndex:3508},{text:"Further Reading and Alternatives",id:"further-reading-and-alternatives",depth:2,charIndex:4130}],frontmatter:{},version:"13.x",_relativePath:"13.x/cookbook/advanced/network-requests.md"},{title:"Async tests",routePath:"/react-native-testing-library/cookbook/basics/async-tests",lang:"",toc:[{text:"Summary",id:"summary",depth:2,charIndex:3},{text:"Example",id:"example",depth:3,charIndex:911},{text:"Async utilities",id:"async-utilities",depth:2,charIndex:1008},{text:"`findBy*` queries",id:"findby-queries",depth:3,charIndex:-1},{text:"Example",id:"example-1",depth:4,charIndex:1622},{text:"`waitFor` function",id:"waitfor-function",depth:3,charIndex:-1},{text:"Example",id:"example-2",depth:4,charIndex:2128},{text:"`waitForElementToBeRemoved` function",id:"waitforelementtoberemoved-function",depth:3,charIndex:-1},{text:"Example",id:"example-3",depth:4,charIndex:2743},{text:"Fake Timers",id:"fake-timers",depth:2,charIndex:2756}],frontmatter:{},version:"13.x",_relativePath:"13.x/cookbook/basics/async-tests.md"},{title:"Custom `render` function",routePath:"/react-native-testing-library/cookbook/basics/custom-render",lang:"",toc:[{text:"Summary",id:"summary",depth:3,charIndex:25},{text:"Example",id:"example",depth:3,charIndex:318},{text:"More info",id:"more-info",depth:3,charIndex:360},{text:"Additional params",id:"additional-params",depth:4,charIndex:372},{text:"Multiple functions",id:"multiple-functions",depth:4,charIndex:571},{text:"Async function",id:"async-function",depth:4,charIndex:787}],frontmatter:{},version:"13.x",_relativePath:"13.x/cookbook/basics/custom-render.md"},{title:"Introduction",routePath:"/react-native-testing-library/cookbook/",lang:"",toc:[{text:"What's Inside the Cookbook?",id:"whats-inside-the-cookbook",depth:2,charIndex:434},{text:"What's Next?",id:"whats-next",depth:2,charIndex:1045}],frontmatter:{},version:"13.x",_relativePath:"13.x/cookbook/index.md"},{title:"Jotai",routePath:"/react-native-testing-library/cookbook/state-management/jotai",lang:"",toc:[{text:"Introduction",id:"introduction",depth:2,charIndex:3},{text:"Task List Example",id:"task-list-example",depth:2,charIndex:337},{text:"Starting with a Simple Test",id:"starting-with-a-simple-test",depth:2,charIndex:566},{text:"Custom Render Function to populate Jotai Atoms with Initial Values",id:"custom-render-function-to-populate-jotai-atoms-with-initial-values",depth:2,charIndex:860},{text:"Testing the `TaskList` Component with initial tasks",id:"testing-the-tasklist-component-with-initial-tasks",depth:2,charIndex:-1},{text:"Modifying atom outside of React components",id:"modifying-atom-outside-of-react-components",depth:2,charIndex:1773},{text:"Testing atom outside of React components",id:"testing-atom-outside-of-react-components",depth:2,charIndex:2022},{text:"Conclusion",id:"conclusion",depth:2,charIndex:2358}],frontmatter:{},version:"13.x",_relativePath:"13.x/cookbook/state-management/jotai.md"},{title:"Testing environment",routePath:"/react-native-testing-library/docs/advanced/testing-env",lang:"",toc:[{text:"React renderers",id:"react-renderers",depth:2,charIndex:659},{text:"React Test Renderer",id:"react-test-renderer",depth:2,charIndex:1382},{text:"Element tree",id:"element-tree",depth:2,charIndex:2783},{text:"Host and composite components",id:"host-and-composite-components",depth:2,charIndex:3389},{text:"Differentiating between host and composite elements",id:"differentiating-between-host-and-composite-elements",depth:3,charIndex:5113},{text:"Tree nodes",id:"tree-nodes",depth:2,charIndex:5538},{text:"Asserting props",id:"asserting-props",depth:3,charIndex:5854},{text:"Tree navigation",id:"tree-navigation",depth:2,charIndex:6557},{text:"Queries",id:"queries",depth:2,charIndex:7290}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/advanced/testing-env.mdx"},{title:"Third-Party Library Integration",routePath:"/react-native-testing-library/docs/advanced/third-party-integration",lang:"",toc:[{text:"Handling Events in Third-Party Libraries",id:"handling-events-in-third-party-libraries",depth:2,charIndex:234},{text:"Example: React Native Gesture Handler",id:"example-react-native-gesture-handler",depth:3,charIndex:1026}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/advanced/third-party-integration.mdx"},{title:"Understanding `act` function",routePath:"/react-native-testing-library/docs/advanced/understanding-act",lang:"",toc:[{text:"`act` warnings",id:"act-warnings",depth:2,charIndex:-1},{text:"Synchronous `act`",id:"synchronous-act",depth:2,charIndex:-1},{text:"Responsibility",id:"responsibility",depth:3,charIndex:575},{text:"When to use act",id:"when-to-use-act",depth:3,charIndex:1673},{text:"Implementation",id:"implementation",depth:3,charIndex:2765},{text:"Asynchronous `act`",id:"asynchronous-act",depth:2,charIndex:-1},{text:"Asynchronous code",id:"asynchronous-code",depth:3,charIndex:3756},{text:"Solution with fake timers",id:"solution-with-fake-timers",depth:3,charIndex:4462},{text:"Solution with real timers",id:"solution-with-real-timers",depth:3,charIndex:4772},{text:"Async act warning",id:"async-act-warning",depth:3,charIndex:5594},{text:"References",id:"references",depth:2,charIndex:6029}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/advanced/understanding-act.mdx"},{title:"API Overview",routePath:"/react-native-testing-library/docs/api",lang:"",toc:[],frontmatter:{uri:"/api"},version:"13.x",_relativePath:"13.x/docs/api.md"},{title:"Fire Event API",routePath:"/react-native-testing-library/docs/api/events/fire-event",lang:"",toc:[{text:"`fireEvent`",id:"fireevent",depth:2,charIndex:-1},{text:"`fireEvent.press`",id:"fireeventpress",depth:3,charIndex:-1},{text:"`fireEvent.changeText`",id:"fireeventchangetext",depth:3,charIndex:-1},{text:"`fireEvent.scroll`",id:"fireeventscroll",depth:3,charIndex:-1},{text:"On a `ScrollView`",id:"on-a-scrollview",depth:4,charIndex:-1},{text:"`fireEventAsync`",id:"fireeventasync",depth:2,charIndex:-1},{text:"`fireEventAsync.press`",id:"fireeventasyncpress",depth:3,charIndex:-1},{text:"`fireEventAsync.changeText`",id:"fireeventasyncchangetext",depth:3,charIndex:-1},{text:"`fireEventAsync.scroll`",id:"fireeventasyncscroll",depth:3,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/events/fire-event.mdx"},{title:"User Event interactions",routePath:"/react-native-testing-library/docs/api/events/user-event",lang:"",toc:[{text:"Comparison with Fire Event API",id:"comparison-with-fire-event-api",depth:2,charIndex:3},{text:"`setup()`",id:"setup",depth:2,charIndex:-1},{text:"Options",id:"options",depth:3,charIndex:-1},{text:"`press()`",id:"press",depth:2,charIndex:-1},{text:"`longPress()`",id:"longpress",depth:2,charIndex:-1},{text:"Options",id:"options-1",depth:3,charIndex:-1},{text:"`type()`",id:"type",depth:2,charIndex:-1},{text:"Options",id:"options-2",depth:3,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events",depth:3,charIndex:-1},{text:"`clear()`",id:"clear",depth:2,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-1",depth:3,charIndex:-1},{text:"`paste()`",id:"paste",depth:2,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-2",depth:3,charIndex:-1},{text:"`scrollTo()`",id:"scroll-to",depth:2,charIndex:-1},{text:"Options",id:"options-3",depth:3,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-3",depth:3,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/events/user-event.mdx"},{title:"Jest matchers",routePath:"/react-native-testing-library/docs/api/jest-matchers",lang:"",toc:[{text:"Setup",id:"setup",depth:2,charIndex:173},{text:"Migration from legacy Jest Native matchers.",id:"migration-from-legacy-jest-native-matchers",depth:2,charIndex:355},{text:"Checking element existence",id:"checking-element-existence",depth:2,charIndex:519},{text:"`toBeOnTheScreen()`",id:"tobeonthescreen",depth:3,charIndex:-1},{text:"Element Content",id:"element-content",depth:2,charIndex:773},{text:"`toHaveTextContent()`",id:"tohavetextcontent",depth:3,charIndex:-1},{text:"`toContainElement()`",id:"tocontainelement",depth:3,charIndex:-1},{text:"`toBeEmptyElement()`",id:"tobeemptyelement",depth:3,charIndex:-1},{text:"Checking element state",id:"checking-element-state",depth:2,charIndex:1259},{text:"`toHaveDisplayValue()`",id:"tohavedisplayvalue",depth:3,charIndex:-1},{text:"`toHaveAccessibilityValue()`",id:"tohaveaccessibilityvalue",depth:3,charIndex:-1},{text:"`toBeEnabled()` / `toBeDisabled`",id:"tobeenabled--tobedisabled",depth:3,charIndex:-1},{text:"`toBeSelected()`",id:"tobeselected",depth:3,charIndex:-1},{text:"`toBeChecked()` / `toBePartiallyChecked()`",id:"tobechecked--tobepartiallychecked",depth:3,charIndex:-1},{text:"`toBeExpanded()` / `toBeCollapsed()`",id:"tobeexpanded--tobecollapsed",depth:3,charIndex:-1},{text:"`toBeBusy()`",id:"tobebusy",depth:3,charIndex:-1},{text:"Checking element style",id:"checking-element-style",depth:2,charIndex:3871},{text:"`toBeVisible()`",id:"tobevisible",depth:3,charIndex:-1},{text:"`toHaveStyle()`",id:"tohavestyle",depth:3,charIndex:-1},{text:"Other matchers",id:"other-matchers",depth:2,charIndex:4260},{text:"`toHaveAccessibleName()`",id:"tohaveaccessiblename",depth:3,charIndex:-1},{text:"`toHaveProp()`",id:"tohaveprop",depth:3,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/jest-matchers.mdx"},{title:"Accessibility",routePath:"/react-native-testing-library/docs/api/misc/accessibility",lang:"",toc:[{text:"`isHiddenFromAccessibility`",id:"ishiddenfromaccessibility",depth:2,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/misc/accessibility.mdx"},{title:"Async utilities",routePath:"/react-native-testing-library/docs/api/misc/async",lang:"",toc:[{text:"`findBy*` queries",id:"findby-queries",depth:2,charIndex:-1},{text:"`waitFor`",id:"waitfor",depth:2,charIndex:-1},{text:"`waitForElementToBeRemoved`",id:"waitforelementtoberemoved",depth:2,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/misc/async.mdx"},{title:"Configuration",routePath:"/react-native-testing-library/docs/api/misc/config",lang:"",toc:[{text:"`configure`",id:"configure",depth:2,charIndex:-1},{text:"`asyncUtilTimeout` option",id:"asyncutiltimeout-option",depth:3,charIndex:-1},{text:"`defaultIncludeHiddenElements` option",id:"defaultincludehiddenelements-option",depth:3,charIndex:-1},{text:"`defaultDebugOptions` option",id:"defaultdebugoptions-option",depth:3,charIndex:-1},{text:"`concurrentRoot` option",id:"concurrentroot-option",depth:3,charIndex:-1},{text:"`resetToDefaults()`",id:"resettodefaults",depth:2,charIndex:-1},{text:"Environment variables",id:"environment-variables",depth:2,charIndex:946},{text:"`RNTL_SKIP_AUTO_CLEANUP`",id:"rntl_skip_auto_cleanup",depth:3,charIndex:-1},{text:"`RNTL_SKIP_AUTO_DETECT_FAKE_TIMERS`",id:"rntl_skip_auto_detect_fake_timers",depth:3,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/misc/config.mdx"},{title:"Other helpers",routePath:"/react-native-testing-library/docs/api/misc/other",lang:"",toc:[{text:"`within`, `getQueriesForElement`",id:"within-getqueriesforelement",depth:2,charIndex:-1},{text:"`act`",id:"act",depth:2,charIndex:-1},{text:"`cleanup`",id:"cleanup",depth:2,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/misc/other.mdx"},{title:"`renderHook` function",routePath:"/react-native-testing-library/docs/api/misc/render-hook",lang:"",toc:[{text:"`renderHook`",id:"renderhook",depth:2,charIndex:-1},{text:"`options`",id:"options",depth:3,charIndex:-1},{text:"`initialProps`",id:"initialprops",depth:4,charIndex:-1},{text:"`wrapper`",id:"wrapper",depth:4,charIndex:-1},{text:"`concurrentRoot`",id:"concurrentroot",depth:3,charIndex:-1},{text:"Result",id:"result",depth:3,charIndex:1240},{text:"`result`",id:"result-1",depth:4,charIndex:-1},{text:"`rerender`",id:"rerender",depth:4,charIndex:-1},{text:"`unmount`",id:"unmount",depth:4,charIndex:-1},{text:"Examples",id:"examples",depth:3,charIndex:1956},{text:"With `initialProps`",id:"with-initialprops",depth:4,charIndex:-1},{text:"With `wrapper`",id:"with-wrapper",depth:4,charIndex:-1},{text:"`renderHookAsync` function",id:"renderhookasync-function",depth:2,charIndex:-1},{text:"Result",id:"result-2",depth:3,charIndex:1240}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/misc/render-hook.mdx"},{title:"Queries",routePath:"/react-native-testing-library/docs/api/queries",lang:"",toc:[{text:"Accessing queries",id:"accessing-queries",depth:2,charIndex:226},{text:"Using `screen` object",id:"using-screen-object",depth:3,charIndex:-1},{text:"Using `render` result",id:"using-render-result",depth:3,charIndex:-1},{text:"Query parts",id:"query-parts",depth:2,charIndex:848},{text:"Query variant",id:"query-variant",depth:2,charIndex:1095},{text:"`getBy*` queries",id:"getby-queries",depth:3,charIndex:-1},{text:"`getAllBy*` queries",id:"getallby-queries",depth:3,charIndex:-1},{text:"`queryBy*` queries",id:"queryby-queries",depth:3,charIndex:-1},{text:"`queryAllBy*` queries",id:"queryallby-queries",depth:3,charIndex:-1},{text:"`findBy*` queries",id:"findby-queries",depth:3,charIndex:-1},{text:"`findAllBy*` queries",id:"findallby-queries",depth:3,charIndex:-1},{text:"Query predicates",id:"query-predicates",depth:2,charIndex:3631},{text:"`*ByRole`",id:"byrole",depth:3,charIndex:-1},{text:"Options",id:"options",depth:4,charIndex:-1},{text:"`*ByLabelText`",id:"bylabeltext",depth:3,charIndex:-1},{text:"`*ByPlaceholderText`",id:"byplaceholdertext",depth:3,charIndex:-1},{text:"`*ByDisplayValue`",id:"bydisplayvalue",depth:3,charIndex:-1},{text:"`*ByText`",id:"bytext",depth:3,charIndex:-1},{text:"`*ByHintText`",id:"byhinttext",depth:3,charIndex:-1},{text:"`*ByTestId`",id:"bytestid",depth:3,charIndex:-1},{text:"Common options",id:"common-options",depth:3,charIndex:9754},{text:"`includeHiddenElements` option",id:"includehiddenelements-option",depth:4,charIndex:-1},{text:"TextMatch type",id:"textmatch-type",depth:2,charIndex:10468},{text:"Examples",id:"examples",depth:3,charIndex:10603},{text:"Options",id:"options-1",depth:3,charIndex:-1},{text:"Precision",id:"precision",depth:4,charIndex:10704},{text:"Normalization",id:"normalization",depth:4,charIndex:11487},{text:"Legacy unit testing helpers",id:"legacy-unit-testing-helpers",depth:2,charIndex:12753},{text:"`UNSAFE_ByType`",id:"unsafe_bytype",depth:3,charIndex:-1},{text:"`UNSAFE_ByProps`",id:"unsafe_byprops",depth:3,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/queries.mdx"},{title:"`render` API",routePath:"/react-native-testing-library/docs/api/render",lang:"",toc:[{text:"`render` function",id:"render-function",depth:2,charIndex:-1},{text:"Options",id:"options",depth:3,charIndex:470},{text:"`wrapper`",id:"wrapper",depth:4,charIndex:-1},{text:"`concurrentRoot`",id:"concurrentroot",depth:4,charIndex:-1},{text:"`createNodeMock`",id:"createnodemock",depth:4,charIndex:-1},{text:"`unstable_validateStringsRenderedWithinText`",id:"unstable_validatestringsrenderedwithintext",depth:4,charIndex:-1},{text:"Result",id:"result",depth:3,charIndex:1982},{text:"`renderAsync` function",id:"renderasync-function",depth:2,charIndex:-1},{text:"Options",id:"options-1",depth:3,charIndex:2521},{text:"Result",id:"result-1",depth:3,charIndex:2581}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/render.mdx"},{title:"`screen` object",routePath:"/react-native-testing-library/docs/api/screen",lang:"",toc:[{text:"`...queries`",id:"queries",depth:3,charIndex:-1},{text:"Example",id:"example",depth:4,charIndex:549},{text:"`rerender`",id:"rerender",depth:3,charIndex:-1},{text:"`rerenderAsync`",id:"rerenderasync",depth:3,charIndex:-1},{text:"`unmount`",id:"unmount",depth:3,charIndex:-1},{text:"`unmountAsync`",id:"unmountasync",depth:3,charIndex:-1},{text:"`debug`",id:"debug",depth:3,charIndex:-1},{text:"`message` option",id:"message-option",depth:4,charIndex:-1},{text:"`mapProps` option",id:"mapprops-option",depth:4,charIndex:-1},{text:"`toJSON`",id:"tojson",depth:3,charIndex:-1},{text:"`root`",id:"root",depth:3,charIndex:-1},{text:"`UNSAFE_root`",id:"unsafe_root",depth:3,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/screen.mdx"},{title:"Community resources",routePath:"/react-native-testing-library/docs/guides/community-resources",lang:"",toc:[{text:"Recommended content",id:"recommended-content",depth:2,charIndex:3},{text:"Older, potentially outdated content",id:"older-potentially-outdated-content",depth:2,charIndex:601}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/guides/community-resources.mdx"},{title:"FAQ",routePath:"/react-native-testing-library/docs/guides/faq",lang:"",toc:[{text:"Can I test the native features of React Native apps?",id:"can-i-test-the-native-features-of-react-native-apps",depth:2,charIndex:3},{text:"Should I use/migrate to `screen` queries?",id:"should-i-usemigrate-to-screen-queries",depth:2,charIndex:-1},{text:"Should I use/migrate to User Event interactions?",id:"should-i-usemigrate-to-user-event-interactions",depth:2,charIndex:1595}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/guides/faq.mdx"},{title:"How should I query?",routePath:"/react-native-testing-library/docs/guides/how-to-query",lang:"",toc:[{text:"Query parts",id:"query-parts",depth:2,charIndex:273},{text:"Query variant",id:"query-variant",depth:2,charIndex:521},{text:"Idiomatic query variants",id:"idiomatic-query-variants",depth:3,charIndex:1386},{text:"Query predicate",id:"query-predicate",depth:2,charIndex:2339},{text:"Idiomatic query predicates",id:"idiomatic-query-predicates",depth:3,charIndex:3113},{text:"1. By Role query",id:"1-by-role-query",depth:3,charIndex:-1},{text:"Name option",id:"name-option",depth:4,charIndex:-1},{text:"2. Text input queries",id:"2-text-input-queries",depth:3,charIndex:-1},{text:"3. Other accessible queries",id:"3-other-accessible-queries",depth:3,charIndex:-1},{text:"4. Test ID query",id:"4-test-id-query",depth:3,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/guides/how-to-query.mdx"},{title:"React 19 & Suspense Support",routePath:"/react-native-testing-library/docs/guides/react-19",lang:"",toc:[{text:"New async APIs",id:"new-async-apis",depth:2,charIndex:384},{text:"APIs that remain unchanged",id:"apis-that-remain-unchanged",depth:2,charIndex:738},{text:"What changes in your tests",id:"what-changes-in-your-tests",depth:2,charIndex:1053},{text:"Making tests async",id:"making-tests-async",depth:3,charIndex:1083},{text:"When to use async APIs",id:"when-to-use-async-apis",depth:3,charIndex:1253},{text:"Migration strategy",id:"migration-strategy",depth:2,charIndex:1492},{text:"New projects",id:"new-projects",depth:3,charIndex:1514},{text:"Existing projects",id:"existing-projects",depth:3,charIndex:1662},{text:"Future direction",id:"future-direction",depth:3,charIndex:1874}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/guides/react-19.mdx"},{title:"Troubleshooting",routePath:"/react-native-testing-library/docs/guides/troubleshooting",lang:"",toc:[{text:"Matching React Native, React & React Test Renderer versions",id:"matching-react-native-react--react-test-renderer-versions",depth:2,charIndex:116},{text:"Example repository",id:"example-repository",depth:2,charIndex:1005},{text:"Undefined component error",id:"undefined-component-error",depth:2,charIndex:1254},{text:"Mocking React Native",id:"mocking-react-native",depth:3,charIndex:2110},{text:"Act warnings",id:"act-warnings",depth:2,charIndex:2372}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/guides/troubleshooting.mdx"},{title:"Migration to built-in Jest matchers",routePath:"/react-native-testing-library/docs/migration/jest-matchers",lang:"",toc:[{text:"General notes",id:"general-notes",depth:2,charIndex:119},{text:"Usage",id:"usage",depth:2,charIndex:533},{text:"Gradual migration",id:"gradual-migration",depth:3,charIndex:715},{text:"Migration details",id:"migration-details",depth:2,charIndex:946},{text:"Matchers not requiring changes",id:"matchers-not-requiring-changes",depth:3,charIndex:967},{text:"Replaced matchers",id:"replaced-matchers",depth:3,charIndex:1274},{text:"Added matchers",id:"added-matchers",depth:3,charIndex:1667},{text:"Noteworthy details",id:"noteworthy-details",depth:3,charIndex:1729}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/migration/jest-matchers.mdx"},{title:"Migration to 11.x",routePath:"/react-native-testing-library/docs/migration/previous/v11",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:153},{text:"Update to Jest 28 if you use fake timers",id:"update-to-jest-28-if-you-use-fake-timers",depth:3,charIndex:173},{text:"Refactor legacy `waitForOptions` position",id:"refactor-legacy-waitforoptions-position",depth:3,charIndex:-1},{text:'Triggering non-touch events on targets with `pointerEvents="box-none"` prop',id:"triggering-non-touch-events-on-targets-with-pointereventsbox-none-prop",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:1263}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/migration/previous/v11.mdx"},{title:"Migration to 12.x",routePath:"/react-native-testing-library/docs/migration/previous/v12",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:484},{text:"1. All queries exclude elements hidden from accessibility by default",id:"1-all-queries-exclude-elements-hidden-from-accessibility-by-default",depth:3,charIndex:504},{text:"2. `*ByRole` queries now return only accessibility elements",id:"2-byrole-queries-now-return-only-accessibility-elements",depth:3,charIndex:-1},{text:"Examples",id:"examples",depth:4,charIndex:1510},{text:"3. `*ByText`, `*ByDisplayValue`, `*ByPlaceholderText` queries now return host elements",id:"3-bytext-bydisplayvalue-byplaceholdertext-queries-now-return-host-elements",depth:3,charIndex:-1},{text:"4. `container` API has been renamed to `UNSAFE_root`.",id:"4-container-api-has-been-renamed-to-unsafe_root",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:2923}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/migration/previous/v12.mdx"},{title:"Migration to 2.x",routePath:"/react-native-testing-library/docs/migration/previous/v2",lang:"",toc:[{text:"Dropping Node 8",id:"dropping-node-8",depth:2,charIndex:100},{text:"Auto Cleanup",id:"auto-cleanup",depth:2,charIndex:325},{text:"WaitFor API changes",id:"waitfor-api-changes",depth:2,charIndex:1248},{text:"Removed global `debug` function",id:"removed-global-debug-function",depth:2,charIndex:-1},{text:"Removed global `shallow` function",id:"removed-global-shallow-function",depth:2,charIndex:-1},{text:"Removed functions",id:"removed-functions",depth:2,charIndex:2145},{text:"Some `ByTestId` queries behavior changes",id:"some-bytestid-queries-behavior-changes",depth:2,charIndex:-1},{text:"Deprecated `flushMicrotasksQueue`",id:"deprecated-flushmicrotasksqueue",depth:2,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/migration/previous/v2.mdx"},{title:"Migration to 7.x",routePath:"/react-native-testing-library/docs/migration/previous/v7",lang:"",toc:[{text:"Guide for `react-native-testing-library` users",id:"guide-for-react-native-testing-library-users",depth:2,charIndex:-1},{text:"Renaming the library",id:"renaming-the-library",depth:3,charIndex:452},{text:"New aliases",id:"new-aliases",depth:3,charIndex:1352},{text:"Renaming `ByPlaceholder` queries",id:"renaming-byplaceholder-queries",depth:3,charIndex:-1},{text:"`fireEvent` support for disabled components",id:"fireevent-support-for-disabled-components",depth:3,charIndex:-1},{text:"Guide for `@testing-library/react-native` users",id:"guide-for-testing-libraryreact-native-users",depth:2,charIndex:-1},{text:'Renaming "wait" helpers',id:"renaming-wait-helpers",depth:3,charIndex:2874},{text:"Changes to `ByTestId` queries",id:"changes-to-bytestid-queries",depth:3,charIndex:-1},{text:"No `ByTitle` queries",id:"no-bytitle-queries",depth:3,charIndex:-1},{text:"No custom Jest configuration",id:"no-custom-jest-configuration",depth:3,charIndex:3628},{text:"Cleanup is included by default",id:"cleanup-is-included-by-default",depth:3,charIndex:3917},{text:"No NativeTestInstance abstraction",id:"no-nativetestinstance-abstraction",depth:3,charIndex:4313},{text:"No `container` nor `baseElement` returned from `render`",id:"no-container-nor-baseelement-returned-from-render",depth:3,charIndex:-1},{text:"Firing events changes",id:"firing-events-changes",depth:3,charIndex:4823}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/migration/previous/v7.mdx"},{title:"Migration to 9.x",routePath:"/react-native-testing-library/docs/migration/previous/v9",lang:"",toc:[{text:"Support for text match options a.k.a string precision API",id:"support-for-text-match-options-aka-string-precision-api",depth:2,charIndex:284},{text:"Reverted matching text across several nodes",id:"reverted-matching-text-across-several-nodes",depth:2,charIndex:924},{text:"Future plans",id:"future-plans",depth:2,charIndex:1437}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/migration/previous/v9.mdx"},{title:"Migration to 13.x",routePath:"/react-native-testing-library/docs/migration/v13",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:228},{text:"Supported React and React Native versions",id:"supported-react-and-react-native-versions",depth:3,charIndex:248},{text:"Concurrent rendering by default",id:"concurrent-rendering-by-default",depth:3,charIndex:593},{text:"Extend Jest matchers by default",id:"extend-jest-matchers-by-default",depth:3,charIndex:980},{text:"Removed deprecated `*ByAccessibilityState` queries",id:"removed-deprecated-byaccessibilitystate-queries",depth:3,charIndex:-1},{text:"Removed deprecated `*ByAccessibilityValue` queries",id:"removed-deprecated-byaccessibilityvalue-queries",depth:3,charIndex:-1},{text:"Removed Jest preset",id:"removed-jest-preset",depth:3,charIndex:2245},{text:"Removed `debug.shallow`",id:"removed-debugshallow",depth:3,charIndex:-1},{text:"Changes to accessibility label calculation",id:"changes-to-accessibility-label-calculation",depth:3,charIndex:2565},{text:"Other changes",id:"other-changes",depth:2,charIndex:2798},{text:"Removed host component names autodetection",id:"removed-host-component-names-autodetection",depth:3,charIndex:2815},{text:"Use React implementation of `act` instead of React Test Renderer one",id:"use-react-implementation-of-act-instead-of-react-test-renderer-one",depth:3,charIndex:-1},{text:"Updated `flushMicroTasks` internal method",id:"updated-flushmicrotasks-internal-method",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:3147}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/migration/v13.mdx"},{title:"Introduction",routePath:"/react-native-testing-library/docs/start/intro",lang:"",toc:[{text:"The problem",id:"the-problem",depth:2,charIndex:3},{text:"This solution",id:"this-solution",depth:2,charIndex:479},{text:"Example",id:"example",depth:2,charIndex:988}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/start/intro.md"},{title:"Quick Start",routePath:"/react-native-testing-library/docs/start/quick-start",lang:"",toc:[{text:"Installation",id:"installation",depth:2,charIndex:3},{text:"Jest matchers",id:"jest-matchers",depth:3,charIndex:223},{text:"ESLint plugin",id:"eslint-plugin",depth:3,charIndex:461}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/start/quick-start.mdx"},{title:"",routePath:"/react-native-testing-library/",lang:"",toc:[],frontmatter:{pageType:"home",hero:{name:"React Native",text:"Testing Library",image:{src:"/img/owl.png"},tagline:"Helps you to write better tests with less effort.",actions:[{theme:"brand",text:"Quick Start",link:"/docs/start/quick-start"},{theme:"alt",text:"Explore API",link:"/docs/api"}]},features:[{title:"Maintainable",details:"Write maintainable tests for your React Native apps.",icon:"✨"},{title:"Reliable",details:"Promotes testing public APIs and avoiding implementation details.",icon:"βœ…"},{title:"Community Driven",details:"Supported by React Native community and its core contributors.",icon:"❀️"}]},version:"13.x",_relativePath:"13.x/index.md"},{title:"Network Requests",routePath:"/react-native-testing-library/14.x/cookbook/advanced/network-requests",lang:"",toc:[{text:"Introduction",id:"introduction",depth:2,charIndex:3},{text:"Phonebook Example",id:"phonebook-example",depth:2,charIndex:568},{text:"Start testing with a simple test",id:"start-testing-with-a-simple-test",depth:2,charIndex:1294},{text:"Testing error handling",id:"testing-error-handling",depth:2,charIndex:2353},{text:"Global guarding against unwanted API requests",id:"global-guarding-against-unwanted-api-requests",depth:2,charIndex:2920},{text:"Conclusion",id:"conclusion",depth:2,charIndex:3508},{text:"Further Reading and Alternatives",id:"further-reading-and-alternatives",depth:2,charIndex:4130}],frontmatter:{},version:"14.x",_relativePath:"14.x/cookbook/advanced/network-requests.md"},{title:"Async Events",routePath:"/react-native-testing-library/14.x/cookbook/basics/async-events",lang:"",toc:[{text:"Summary",id:"summary",depth:2,charIndex:3},{text:"Example",id:"example",depth:3,charIndex:665},{text:"Async utilities",id:"async-utilities",depth:2,charIndex:743},{text:"`findBy*` queries",id:"findby-queries",depth:3,charIndex:-1},{text:"Example",id:"example-1",depth:4,charIndex:1357},{text:"`waitFor` function",id:"waitfor-function",depth:3,charIndex:-1},{text:"Example",id:"example-2",depth:4,charIndex:1863},{text:"`waitForElementToBeRemoved` function",id:"waitforelementtoberemoved-function",depth:3,charIndex:-1},{text:"Example",id:"example-3",depth:4,charIndex:2478},{text:"Fake Timers",id:"fake-timers",depth:2,charIndex:2491}],frontmatter:{},version:"14.x",_relativePath:"14.x/cookbook/basics/async-events.md"},{title:"Custom `render` function",routePath:"/react-native-testing-library/14.x/cookbook/basics/custom-render",lang:"",toc:[{text:"Summary",id:"summary",depth:3,charIndex:25},{text:"Example",id:"example",depth:3,charIndex:318},{text:"More info",id:"more-info",depth:3,charIndex:360},{text:"Additional params",id:"additional-params",depth:4,charIndex:372},{text:"Multiple functions",id:"multiple-functions",depth:4,charIndex:571},{text:"Async setup",id:"async-setup",depth:4,charIndex:787}],frontmatter:{},version:"14.x",_relativePath:"14.x/cookbook/basics/custom-render.md"},{title:"Introduction",routePath:"/react-native-testing-library/14.x/cookbook/",lang:"",toc:[{text:"What's Inside the Cookbook?",id:"whats-inside-the-cookbook",depth:2,charIndex:434},{text:"What's Next?",id:"whats-next",depth:2,charIndex:1045}],frontmatter:{},version:"14.x",_relativePath:"14.x/cookbook/index.md"},{title:"Jotai",routePath:"/react-native-testing-library/14.x/cookbook/state-management/jotai",lang:"",toc:[{text:"Introduction",id:"introduction",depth:2,charIndex:3},{text:"Task List Example",id:"task-list-example",depth:2,charIndex:337},{text:"Starting with a Simple Test",id:"starting-with-a-simple-test",depth:2,charIndex:566},{text:"Custom Render Function to populate Jotai Atoms with Initial Values",id:"custom-render-function-to-populate-jotai-atoms-with-initial-values",depth:2,charIndex:860},{text:"Testing the `TaskList` Component with initial tasks",id:"testing-the-tasklist-component-with-initial-tasks",depth:2,charIndex:-1},{text:"Modifying atom outside of React components",id:"modifying-atom-outside-of-react-components",depth:2,charIndex:1773},{text:"Testing atom outside of React components",id:"testing-atom-outside-of-react-components",depth:2,charIndex:2022},{text:"Conclusion",id:"conclusion",depth:2,charIndex:2358}],frontmatter:{},version:"14.x",_relativePath:"14.x/cookbook/state-management/jotai.md"},{title:"Testing environment",routePath:"/react-native-testing-library/14.x/docs/advanced/testing-env",lang:"",toc:[{text:"React renderers",id:"react-renderers",depth:2,charIndex:659},{text:"Test Renderer",id:"test-renderer",depth:2,charIndex:1382},{text:"Element tree",id:"element-tree",depth:2,charIndex:2921},{text:"Host and composite components",id:"host-and-composite-components",depth:2,charIndex:3417},{text:"Host-only element tree",id:"host-only-element-tree",depth:3,charIndex:5126},{text:"Tree nodes",id:"tree-nodes",depth:2,charIndex:5665},{text:"Understanding props",id:"understanding-props",depth:3,charIndex:5992},{text:"Tree navigation",id:"tree-navigation",depth:2,charIndex:6522},{text:"Queries",id:"queries",depth:2,charIndex:7004}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/advanced/testing-env.mdx"},{title:"Third-Party Library Integration",routePath:"/react-native-testing-library/14.x/docs/advanced/third-party-integration",lang:"",toc:[{text:"Handling Events in Third-Party Libraries",id:"handling-events-in-third-party-libraries",depth:2,charIndex:234},{text:"Example: React Native Gesture Handler",id:"example-react-native-gesture-handler",depth:3,charIndex:1026}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/advanced/third-party-integration.mdx"},{title:"Understanding `act` function",routePath:"/react-native-testing-library/14.x/docs/advanced/understanding-act",lang:"",toc:[{text:"`act` warning",id:"act-warning",depth:2,charIndex:-1},{text:"Understanding `act`",id:"understanding-act",depth:2,charIndex:-1},{text:"Responsibility",id:"responsibility",depth:3,charIndex:401},{text:"When to use act",id:"when-to-use-act",depth:3,charIndex:1607},{text:"Implementation",id:"implementation",depth:3,charIndex:2669},{text:"Asynchronous code",id:"asynchronous-code",depth:2,charIndex:3491},{text:"Handling asynchronous operations",id:"handling-asynchronous-operations",depth:3,charIndex:3917},{text:"Solution with fake timers",id:"solution-with-fake-timers",depth:3,charIndex:4426},{text:"Solution with real timers",id:"solution-with-real-timers",depth:3,charIndex:4741},{text:"References",id:"references",depth:2,charIndex:5563}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/advanced/understanding-act.mdx"},{title:"API Overview",routePath:"/react-native-testing-library/14.x/docs/api",lang:"",toc:[],frontmatter:{uri:"/api"},version:"14.x",_relativePath:"14.x/docs/api.md"},{title:"Fire Event API",routePath:"/react-native-testing-library/14.x/docs/api/events/fire-event",lang:"",toc:[{text:"`fireEvent`",id:"fireevent",depth:2,charIndex:-1},{text:"`fireEvent.press`",id:"fireeventpress",depth:3,charIndex:-1},{text:"`fireEvent.changeText`",id:"fireeventchangetext",depth:3,charIndex:-1},{text:"`fireEvent.scroll`",id:"fireeventscroll",depth:3,charIndex:-1},{text:"On a `ScrollView`",id:"on-a-scrollview",depth:4,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/events/fire-event.mdx"},{title:"User Event interactions",routePath:"/react-native-testing-library/14.x/docs/api/events/user-event",lang:"",toc:[{text:"Comparison with Fire Event API",id:"comparison-with-fire-event-api",depth:2,charIndex:3},{text:"`setup()`",id:"setup",depth:2,charIndex:-1},{text:"Options",id:"options",depth:3,charIndex:-1},{text:"`press()`",id:"press",depth:2,charIndex:-1},{text:"`longPress()`",id:"longpress",depth:2,charIndex:-1},{text:"Options",id:"options-1",depth:3,charIndex:-1},{text:"`type()`",id:"type",depth:2,charIndex:-1},{text:"Options",id:"options-2",depth:3,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events",depth:3,charIndex:-1},{text:"`clear()`",id:"clear",depth:2,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-1",depth:3,charIndex:-1},{text:"`paste()`",id:"paste",depth:2,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-2",depth:3,charIndex:-1},{text:"`scrollTo()`",id:"scroll-to",depth:2,charIndex:-1},{text:"Options",id:"options-3",depth:3,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-3",depth:3,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/events/user-event.mdx"},{title:"Jest matchers",routePath:"/react-native-testing-library/14.x/docs/api/jest-matchers",lang:"",toc:[{text:"Setup",id:"setup",depth:2,charIndex:173},{text:"Migration from legacy Jest Native matchers.",id:"migration-from-legacy-jest-native-matchers",depth:2,charIndex:355},{text:"Checking element existence",id:"checking-element-existence",depth:2,charIndex:519},{text:"`toBeOnTheScreen()`",id:"tobeonthescreen",depth:3,charIndex:-1},{text:"Element Content",id:"element-content",depth:2,charIndex:773},{text:"`toHaveTextContent()`",id:"tohavetextcontent",depth:3,charIndex:-1},{text:"`toContainElement()`",id:"tocontainelement",depth:3,charIndex:-1},{text:"`toBeEmptyElement()`",id:"tobeemptyelement",depth:3,charIndex:-1},{text:"Checking element state",id:"checking-element-state",depth:2,charIndex:1259},{text:"`toHaveDisplayValue()`",id:"tohavedisplayvalue",depth:3,charIndex:-1},{text:"`toHaveAccessibilityValue()`",id:"tohaveaccessibilityvalue",depth:3,charIndex:-1},{text:"`toBeEnabled()` / `toBeDisabled`",id:"tobeenabled--tobedisabled",depth:3,charIndex:-1},{text:"`toBeSelected()`",id:"tobeselected",depth:3,charIndex:-1},{text:"`toBeChecked()` / `toBePartiallyChecked()`",id:"tobechecked--tobepartiallychecked",depth:3,charIndex:-1},{text:"`toBeExpanded()` / `toBeCollapsed()`",id:"tobeexpanded--tobecollapsed",depth:3,charIndex:-1},{text:"`toBeBusy()`",id:"tobebusy",depth:3,charIndex:-1},{text:"Checking element style",id:"checking-element-style",depth:2,charIndex:3866},{text:"`toBeVisible()`",id:"tobevisible",depth:3,charIndex:-1},{text:"`toHaveStyle()`",id:"tohavestyle",depth:3,charIndex:-1},{text:"Other matchers",id:"other-matchers",depth:2,charIndex:4255},{text:"`toHaveAccessibleName()`",id:"tohaveaccessiblename",depth:3,charIndex:-1},{text:"`toHaveProp()`",id:"tohaveprop",depth:3,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/jest-matchers.mdx"},{title:"Accessibility",routePath:"/react-native-testing-library/14.x/docs/api/misc/accessibility",lang:"",toc:[{text:"`isHiddenFromAccessibility`",id:"ishiddenfromaccessibility",depth:2,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/misc/accessibility.mdx"},{title:"Async utilities",routePath:"/react-native-testing-library/14.x/docs/api/misc/async",lang:"",toc:[{text:"`findBy*` queries",id:"findby-queries",depth:2,charIndex:-1},{text:"`waitFor`",id:"waitfor",depth:2,charIndex:-1},{text:"Options",id:"options",depth:3,charIndex:2506},{text:"`waitForElementToBeRemoved`",id:"waitforelementtoberemoved",depth:2,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/misc/async.mdx"},{title:"Configuration",routePath:"/react-native-testing-library/14.x/docs/api/misc/config",lang:"",toc:[{text:"`configure`",id:"configure",depth:2,charIndex:-1},{text:"`asyncUtilTimeout` option",id:"asyncutiltimeout-option",depth:3,charIndex:-1},{text:"`defaultIncludeHiddenElements` option",id:"defaultincludehiddenelements-option",depth:3,charIndex:-1},{text:"`defaultDebugOptions` option",id:"defaultdebugoptions-option",depth:3,charIndex:-1},{text:"`resetToDefaults()`",id:"resettodefaults",depth:2,charIndex:-1},{text:"Environment variables",id:"environment-variables",depth:2,charIndex:769},{text:"`RNTL_SKIP_AUTO_CLEANUP`",id:"rntl_skip_auto_cleanup",depth:3,charIndex:-1},{text:"`RNTL_SKIP_AUTO_DETECT_FAKE_TIMERS`",id:"rntl_skip_auto_detect_fake_timers",depth:3,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/misc/config.mdx"},{title:"Other helpers",routePath:"/react-native-testing-library/14.x/docs/api/misc/other",lang:"",toc:[{text:"`within`",id:"within",depth:2,charIndex:-1},{text:"`act`",id:"act",depth:2,charIndex:-1},{text:"`cleanup`",id:"cleanup",depth:2,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/misc/other.mdx"},{title:"`renderHook` function",routePath:"/react-native-testing-library/14.x/docs/api/misc/render-hook",lang:"",toc:[{text:"`renderHook`",id:"renderhook",depth:2,charIndex:-1},{text:"`options`",id:"options",depth:3,charIndex:-1},{text:"`initialProps`",id:"initialprops",depth:4,charIndex:-1},{text:"`wrapper`",id:"wrapper",depth:4,charIndex:-1},{text:"Result",id:"result",depth:3,charIndex:1534},{text:"`result`",id:"result-1",depth:4,charIndex:-1},{text:"`rerender`",id:"rerender",depth:4,charIndex:-1},{text:"`unmount`",id:"unmount",depth:4,charIndex:-1},{text:"Examples",id:"examples",depth:3,charIndex:2498},{text:"With `initialProps`",id:"with-initialprops",depth:4,charIndex:-1},{text:"With `wrapper`",id:"with-wrapper",depth:4,charIndex:-1},{text:"With React Suspense",id:"with-react-suspense",depth:4,charIndex:2610}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/misc/render-hook.mdx"},{title:"Queries",routePath:"/react-native-testing-library/14.x/docs/api/queries",lang:"",toc:[{text:"Accessing queries",id:"accessing-queries",depth:2,charIndex:226},{text:"Using `screen` object",id:"using-screen-object",depth:3,charIndex:-1},{text:"Using `render` result",id:"using-render-result",depth:3,charIndex:-1},{text:"Query parts",id:"query-parts",depth:2,charIndex:848},{text:"Query variant",id:"query-variant",depth:2,charIndex:1095},{text:"`getBy*` queries",id:"getby-queries",depth:3,charIndex:-1},{text:"`getAllBy*` queries",id:"getallby-queries",depth:3,charIndex:-1},{text:"`queryBy*` queries",id:"queryby-queries",depth:3,charIndex:-1},{text:"`queryAllBy*` queries",id:"queryallby-queries",depth:3,charIndex:-1},{text:"`findBy*` queries",id:"findby-queries",depth:3,charIndex:-1},{text:"`findAllBy*` queries",id:"findallby-queries",depth:3,charIndex:-1},{text:"Query predicates",id:"query-predicates",depth:2,charIndex:3589},{text:"`*ByRole`",id:"byrole",depth:3,charIndex:-1},{text:"Options",id:"options",depth:4,charIndex:-1},{text:"`*ByLabelText`",id:"bylabeltext",depth:3,charIndex:-1},{text:"`*ByPlaceholderText`",id:"byplaceholdertext",depth:3,charIndex:-1},{text:"`*ByDisplayValue`",id:"bydisplayvalue",depth:3,charIndex:-1},{text:"`*ByText`",id:"bytext",depth:3,charIndex:-1},{text:"`*ByHintText`",id:"byhinttext",depth:3,charIndex:-1},{text:"`*ByTestId`",id:"bytestid",depth:3,charIndex:-1},{text:"Common options",id:"common-options",depth:3,charIndex:9713},{text:"`includeHiddenElements` option",id:"includehiddenelements-option",depth:4,charIndex:-1},{text:"TextMatch type",id:"textmatch-type",depth:2,charIndex:10427},{text:"Examples",id:"examples",depth:3,charIndex:10562},{text:"Options",id:"options-1",depth:3,charIndex:-1},{text:"Precision",id:"precision",depth:4,charIndex:10663},{text:"Normalization",id:"normalization",depth:4,charIndex:11446}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/queries.mdx"},{title:"`render` API",routePath:"/react-native-testing-library/14.x/docs/api/render",lang:"",toc:[{text:"`render` function",id:"render-function",depth:2,charIndex:-1},{text:"Options",id:"options",depth:3,charIndex:686},{text:"`wrapper`",id:"wrapper",depth:4,charIndex:-1},{text:"`createNodeMock`",id:"createnodemock",depth:4,charIndex:-1},{text:"Result",id:"result",depth:3,charIndex:1799}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/render.mdx"},{title:"`screen` object",routePath:"/react-native-testing-library/14.x/docs/api/screen",lang:"",toc:[{text:"`...queries`",id:"queries",depth:3,charIndex:-1},{text:"Example",id:"example",depth:4,charIndex:549},{text:"`rerender`",id:"rerender",depth:3,charIndex:-1},{text:"`unmount`",id:"unmount",depth:3,charIndex:-1},{text:"`debug`",id:"debug",depth:3,charIndex:-1},{text:"`message` option",id:"message-option",depth:4,charIndex:-1},{text:"`mapProps` option",id:"mapprops-option",depth:4,charIndex:-1},{text:"`toJSON`",id:"tojson",depth:3,charIndex:-1},{text:"`container`",id:"container",depth:3,charIndex:-1},{text:"`root`",id:"root",depth:3,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/screen.mdx"},{title:"Community resources",routePath:"/react-native-testing-library/14.x/docs/guides/community-resources",lang:"",toc:[{text:"Recommended content",id:"recommended-content",depth:2,charIndex:3},{text:"Older, potentially outdated content",id:"older-potentially-outdated-content",depth:2,charIndex:601}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/guides/community-resources.mdx"},{title:"FAQ",routePath:"/react-native-testing-library/14.x/docs/guides/faq",lang:"",toc:[{text:"Can I test the native features of React Native apps?",id:"can-i-test-the-native-features-of-react-native-apps",depth:2,charIndex:3},{text:"Should I use/migrate to `screen` queries?",id:"should-i-usemigrate-to-screen-queries",depth:2,charIndex:-1},{text:"Should I use/migrate to User Event interactions?",id:"should-i-usemigrate-to-user-event-interactions",depth:2,charIndex:1589}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/guides/faq.mdx"},{title:"How should I query?",routePath:"/react-native-testing-library/14.x/docs/guides/how-to-query",lang:"",toc:[{text:"Query parts",id:"query-parts",depth:2,charIndex:273},{text:"Query variant",id:"query-variant",depth:2,charIndex:521},{text:"Idiomatic query variants",id:"idiomatic-query-variants",depth:3,charIndex:1344},{text:"Query predicate",id:"query-predicate",depth:2,charIndex:2297},{text:"Idiomatic query predicates",id:"idiomatic-query-predicates",depth:3,charIndex:3088},{text:"1. By Role query",id:"1-by-role-query",depth:3,charIndex:-1},{text:"Name option",id:"name-option",depth:4,charIndex:-1},{text:"2. Text input queries",id:"2-text-input-queries",depth:3,charIndex:-1},{text:"3. Other accessible queries",id:"3-other-accessible-queries",depth:3,charIndex:-1},{text:"4. Test ID query",id:"4-test-id-query",depth:3,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/guides/how-to-query.mdx"},{title:"Troubleshooting",routePath:"/react-native-testing-library/14.x/docs/guides/troubleshooting",lang:"",toc:[{text:"Example repository",id:"example-repository",depth:2,charIndex:116},{text:"Undefined component error",id:"undefined-component-error",depth:2,charIndex:365},{text:"Mocking React Native",id:"mocking-react-native",depth:3,charIndex:1221},{text:"Act warnings",id:"act-warnings",depth:2,charIndex:1483}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/guides/troubleshooting.mdx"},{title:"Migration to built-in Jest matchers",routePath:"/react-native-testing-library/14.x/docs/migration/jest-matchers",lang:"",toc:[{text:"General notes",id:"general-notes",depth:2,charIndex:119},{text:"Usage",id:"usage",depth:2,charIndex:533},{text:"Gradual migration",id:"gradual-migration",depth:3,charIndex:715},{text:"Migration details",id:"migration-details",depth:2,charIndex:946},{text:"Matchers not requiring changes",id:"matchers-not-requiring-changes",depth:3,charIndex:967},{text:"Replaced matchers",id:"replaced-matchers",depth:3,charIndex:1274},{text:"Added matchers",id:"added-matchers",depth:3,charIndex:1667},{text:"Noteworthy details",id:"noteworthy-details",depth:3,charIndex:1729}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/jest-matchers.mdx"},{title:"Migration to 11.x",routePath:"/react-native-testing-library/14.x/docs/migration/v11",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:153},{text:"Update to Jest 28 if you use fake timers",id:"update-to-jest-28-if-you-use-fake-timers",depth:3,charIndex:173},{text:"Refactor legacy `waitForOptions` position",id:"refactor-legacy-waitforoptions-position",depth:3,charIndex:-1},{text:'Triggering non-touch events on targets with `pointerEvents="box-none"` prop',id:"triggering-non-touch-events-on-targets-with-pointereventsbox-none-prop",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:1263}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/v11.mdx"},{title:"Migration to 12.x",routePath:"/react-native-testing-library/14.x/docs/migration/v12",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:484},{text:"1. All queries exclude elements hidden from accessibility by default",id:"1-all-queries-exclude-elements-hidden-from-accessibility-by-default",depth:3,charIndex:504},{text:"2. `*ByRole` queries now return only accessibility elements",id:"2-byrole-queries-now-return-only-accessibility-elements",depth:3,charIndex:-1},{text:"Examples",id:"examples",depth:4,charIndex:1510},{text:"3. `*ByText`, `*ByDisplayValue`, `*ByPlaceholderText` queries now return host elements",id:"3-bytext-bydisplayvalue-byplaceholdertext-queries-now-return-host-elements",depth:3,charIndex:-1},{text:"4. `container` API has been renamed to `UNSAFE_root`.",id:"4-container-api-has-been-renamed-to-unsafe_root",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:2917}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/v12.mdx"},{title:"Migration to 13.x",routePath:"/react-native-testing-library/14.x/docs/migration/v13",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:228},{text:"Supported React and React Native versions",id:"supported-react-and-react-native-versions",depth:3,charIndex:248},{text:"Concurrent rendering by default",id:"concurrent-rendering-by-default",depth:3,charIndex:593},{text:"Extend Jest matchers by default",id:"extend-jest-matchers-by-default",depth:3,charIndex:980},{text:"Removed deprecated `*ByAccessibilityState` queries",id:"removed-deprecated-byaccessibilitystate-queries",depth:3,charIndex:-1},{text:"Removed deprecated `*ByAccessibilityValue` queries",id:"removed-deprecated-byaccessibilityvalue-queries",depth:3,charIndex:-1},{text:"Removed Jest preset",id:"removed-jest-preset",depth:3,charIndex:2245},{text:"Removed `debug.shallow`",id:"removed-debugshallow",depth:3,charIndex:-1},{text:"Changes to accessibility label calculation",id:"changes-to-accessibility-label-calculation",depth:3,charIndex:2565},{text:"Other changes",id:"other-changes",depth:2,charIndex:2798},{text:"Removed host component names autodetection",id:"removed-host-component-names-autodetection",depth:3,charIndex:2815},{text:"Use React implementation of `act` instead of React Test Renderer one",id:"use-react-implementation-of-act-instead-of-react-test-renderer-one",depth:3,charIndex:-1},{text:"Updated `flushMicroTasks` internal method",id:"updated-flushmicrotasks-internal-method",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:3147}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/v13.mdx"},{title:"Migration to 14.x",routePath:"/react-native-testing-library/14.x/docs/migration/v14",lang:"",toc:[{text:"Overview",id:"overview",depth:2,charIndex:101},{text:"Quick Migration",id:"quick-migration",depth:2,charIndex:764},{text:"Breaking Changes",id:"breaking-changes",depth:2,charIndex:971},{text:"Supported React and React Native versions",id:"supported-react-and-react-native-versions",depth:3,charIndex:991},{text:"Test Renderer replaces React Test Renderer",id:"test-renderer-replaces-react-test-renderer",depth:3,charIndex:1294},{text:"1. Update dependencies",id:"1-update-dependencies",depth:4,charIndex:1894},{text:"2. Update type imports (if needed)",id:"2-update-type-imports-if-needed",depth:4,charIndex:2080},{text:"Async APIs by Default",id:"async-apis-by-default",depth:3,charIndex:2404},{text:"`render` is now async",id:"render-is-now-async",depth:4,charIndex:-1},{text:"`renderHook` is now async",id:"renderhook-is-now-async",depth:4,charIndex:-1},{text:"`fireEvent` is now async",id:"fireevent-is-now-async",depth:4,charIndex:-1},{text:"`act` is now async",id:"act-is-now-async",depth:4,charIndex:-1},{text:"Benefits of Async APIs",id:"benefits-of-async-apis",depth:4,charIndex:4392},{text:"Removed APIs",id:"removed-apis",depth:3,charIndex:4721},{text:"`update` alias removed",id:"update-alias-removed",depth:4,charIndex:-1},{text:"`getQueriesForElement` export removed",id:"getqueriesforelement-export-removed",depth:4,charIndex:-1},{text:"`UNSAFE_root` removed",id:"unsafe_root-removed",depth:4,charIndex:-1},{text:"Legacy `UNSAFE_*` queries removed",id:"legacy-unsafe_-queries-removed",depth:4,charIndex:-1},{text:"`concurrentRoot` option removed",id:"concurrentroot-option-removed",depth:4,charIndex:-1},{text:"`container` API reintroduced",id:"container-api-reintroduced",depth:3,charIndex:-1},{text:"Text string validation enforced by default",id:"text-string-validation-enforced-by-default",depth:3,charIndex:7029},{text:"Codemods",id:"codemods",depth:2,charIndex:8152},{text:"`rntl-v14-update-deps`",id:"rntl-v14-update-deps",depth:3,charIndex:-1},{text:"`rntl-v14-async-functions`",id:"rntl-v14-async-functions",depth:3,charIndex:-1},{text:"Custom render functions",id:"custom-render-functions",depth:4,charIndex:8783},{text:"Limitations",id:"limitations",depth:4,charIndex:9146},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:9291}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/v14.mdx"},{title:"Migration to 2.x",routePath:"/react-native-testing-library/14.x/docs/migration/v2",lang:"",toc:[{text:"Dropping Node 8",id:"dropping-node-8",depth:2,charIndex:100},{text:"Auto Cleanup",id:"auto-cleanup",depth:2,charIndex:325},{text:"WaitFor API changes",id:"waitfor-api-changes",depth:2,charIndex:1248},{text:"Removed global `debug` function",id:"removed-global-debug-function",depth:2,charIndex:-1},{text:"Removed global `shallow` function",id:"removed-global-shallow-function",depth:2,charIndex:-1},{text:"Removed functions",id:"removed-functions",depth:2,charIndex:2145},{text:"Some `ByTestId` queries behavior changes",id:"some-bytestid-queries-behavior-changes",depth:2,charIndex:-1},{text:"Deprecated `flushMicrotasksQueue`",id:"deprecated-flushmicrotasksqueue",depth:2,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/v2.mdx"},{title:"Migration to 7.x",routePath:"/react-native-testing-library/14.x/docs/migration/v7",lang:"",toc:[{text:"Guide for `react-native-testing-library` users",id:"guide-for-react-native-testing-library-users",depth:2,charIndex:-1},{text:"Renaming the library",id:"renaming-the-library",depth:3,charIndex:452},{text:"New aliases",id:"new-aliases",depth:3,charIndex:1352},{text:"Renaming `ByPlaceholder` queries",id:"renaming-byplaceholder-queries",depth:3,charIndex:-1},{text:"`fireEvent` support for disabled components",id:"fireevent-support-for-disabled-components",depth:3,charIndex:-1},{text:"Guide for `@testing-library/react-native` users",id:"guide-for-testing-libraryreact-native-users",depth:2,charIndex:-1},{text:'Renaming "wait" helpers',id:"renaming-wait-helpers",depth:3,charIndex:2874},{text:"Changes to `ByTestId` queries",id:"changes-to-bytestid-queries",depth:3,charIndex:-1},{text:"No `ByTitle` queries",id:"no-bytitle-queries",depth:3,charIndex:-1},{text:"No custom Jest configuration",id:"no-custom-jest-configuration",depth:3,charIndex:3628},{text:"Cleanup is included by default",id:"cleanup-is-included-by-default",depth:3,charIndex:3917},{text:"No NativeTestInstance abstraction",id:"no-nativetestinstance-abstraction",depth:3,charIndex:4313},{text:"No `container` nor `baseElement` returned from `render`",id:"no-container-nor-baseelement-returned-from-render",depth:3,charIndex:-1},{text:"Firing events changes",id:"firing-events-changes",depth:3,charIndex:4817}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/v7.mdx"},{title:"Migration to 9.x",routePath:"/react-native-testing-library/14.x/docs/migration/v9",lang:"",toc:[{text:"Support for text match options a.k.a string precision API",id:"support-for-text-match-options-aka-string-precision-api",depth:2,charIndex:284},{text:"Reverted matching text across several nodes",id:"reverted-matching-text-across-several-nodes",depth:2,charIndex:924},{text:"Future plans",id:"future-plans",depth:2,charIndex:1437}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/v9.mdx"},{title:"Introduction",routePath:"/react-native-testing-library/14.x/docs/start/intro",lang:"",toc:[{text:"The problem",id:"the-problem",depth:2,charIndex:3},{text:"This solution",id:"this-solution",depth:2,charIndex:479},{text:"Example",id:"example",depth:2,charIndex:992}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/start/intro.md"},{title:"Quick Start",routePath:"/react-native-testing-library/14.x/docs/start/quick-start",lang:"",toc:[{text:"Installation",id:"installation",depth:2,charIndex:3},{text:"Jest matchers",id:"jest-matchers",depth:3,charIndex:281},{text:"ESLint plugin",id:"eslint-plugin",depth:3,charIndex:515}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/start/quick-start.mdx"},{title:"",routePath:"/react-native-testing-library/14.x/",lang:"",toc:[],frontmatter:{pageType:"home",hero:{name:"React Native",text:"Testing Library",image:{src:"/img/owl.png"},tagline:"Helps you to write better tests with less effort.",actions:[{theme:"brand",text:"Quick Start",link:"/docs/start/quick-start"},{theme:"alt",text:"Explore API",link:"/docs/api"}]},features:[{title:"Maintainable",details:"Write maintainable tests for your React Native apps.",icon:"✨"},{title:"Reliable",details:"Promotes testing public APIs and avoiding implementation details.",icon:"βœ…"},{title:"Community Driven",details:"Supported by React Native community and its core contributors.",icon:"❀️"}]},version:"14.x",_relativePath:"14.x/index.md"},{title:"",routePath:"/react-native-testing-library/404",lang:"",toc:[],frontmatter:{pageType:"custom"},version:"13.x",_relativePath:"404.mdx"}],markdown:{showLineNumbers:!1,defaultWrapCode:!1,codeHighlighter:"prism"}}},5365:function(e,t,n){"use strict";var r=n(3935),i=n.t(r,2),a=n(745),o=n.t(a,2),s=n(5893),l=n(436),c=n(8995),d=n(5552),u=n(7294),h=n(5378),p=n(405),x=Object.assign||function(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{},r=window.Promise||function(e){function t(){}e(t,t)},i=function(){for(var e=arguments.length,t=Array(e),n=0;n0&&void 0!==arguments[0]?arguments[0]:{},t=e.target,n=function(){var e={width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,left:0,top:0,right:0,bottom:0},t=void 0,n=void 0;if(h.container)if(h.container instanceof Object)t=(e=x({},e,h.container)).width-e.left-e.right-2*h.margin,n=e.height-e.top-e.bottom-2*h.margin;else{var r=(f(h.container)?h.container:document.querySelector(h.container)).getBoundingClientRect();e=x({},e,{width:r.width,height:r.height,left:r.left,top:r.top})}t=t||e.width-2*h.margin,n=n||e.height-2*h.margin;var i=p.zoomedHd||p.original,a=g(i)?t:i.naturalWidth||t,o=g(i)?n:i.naturalHeight||n,s=i.getBoundingClientRect(),l=s.top,c=s.left,d=s.width,u=s.height,m=Math.min(Math.min(Math.max(d,a),t)/d,Math.min(Math.max(u,o),n)/u),v=(-c+(t-d)/2+h.margin+e.left)/m,y=(-l+(n-u)/2+h.margin+e.top)/m,b="scale("+m+") translate3d("+v+"px, "+y+"px, 0)";p.zoomed.style.transform=b,p.zoomedHd&&(p.zoomedHd.style.transform=b)};return new r(function(e){if(t&&-1===l.indexOf(t)||p.zoomed)return void e(k);if(t)p.original=t;else{if(!(l.length>0))return void e(k);p.original=l[0]}if(p.original.dispatchEvent(w("medium-zoom:open",{detail:{zoom:k}})),u=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,d=!0,p.zoomed=b(p.original),document.body.appendChild(m),h.template){var r=f(h.template)?h.template:document.querySelector(h.template);p.template=document.createElement("div"),p.template.appendChild(r.content.cloneNode(!0)),document.body.appendChild(p.template)}if(p.original.parentElement&&"PICTURE"===p.original.parentElement.tagName&&p.original.currentSrc&&(p.zoomed.src=p.original.currentSrc),document.body.appendChild(p.zoomed),window.requestAnimationFrame(function(){document.body.classList.add("medium-zoom--opened")}),p.original.classList.add("medium-zoom-image--hidden"),p.zoomed.classList.add("medium-zoom-image--opened"),p.zoomed.addEventListener("click",o),p.zoomed.addEventListener("transitionend",function t(){d=!1,p.zoomed.removeEventListener("transitionend",t),p.original.dispatchEvent(w("medium-zoom:opened",{detail:{zoom:k}})),e(k)}),p.original.getAttribute("data-zoom-src")){p.zoomedHd=p.zoomed.cloneNode(),p.zoomedHd.removeAttribute("srcset"),p.zoomedHd.removeAttribute("sizes"),p.zoomedHd.removeAttribute("loading"),p.zoomedHd.src=p.zoomed.getAttribute("data-zoom-src"),p.zoomedHd.onerror=function(){clearInterval(i),console.warn("Unable to reach the zoom image target "+p.zoomedHd.src),p.zoomedHd=null,n()};var i=setInterval(function(){p.zoomedHd.complete&&(clearInterval(i),p.zoomedHd.classList.add("medium-zoom-image--opened"),p.zoomedHd.addEventListener("click",o),document.body.appendChild(p.zoomedHd),n())},10)}else if(p.original.hasAttribute("srcset")){p.zoomedHd=p.zoomed.cloneNode(),p.zoomedHd.removeAttribute("sizes"),p.zoomedHd.removeAttribute("loading");var a=p.zoomedHd.addEventListener("load",function(){p.zoomedHd.removeEventListener("load",a),p.zoomedHd.classList.add("medium-zoom-image--opened"),p.zoomedHd.addEventListener("click",o),document.body.appendChild(p.zoomedHd),n()})}else n()})},o=function(){return new r(function(e){if(d||!p.original)return void e(k);d=!0,document.body.classList.remove("medium-zoom--opened"),p.zoomed.style.transform="",p.zoomedHd&&(p.zoomedHd.style.transform=""),p.template&&(p.template.style.transition="opacity 150ms",p.template.style.opacity=0),p.original.dispatchEvent(w("medium-zoom:close",{detail:{zoom:k}})),p.zoomed.addEventListener("transitionend",function t(){p.original.classList.remove("medium-zoom-image--hidden"),document.body.removeChild(p.zoomed),p.zoomedHd&&document.body.removeChild(p.zoomedHd),document.body.removeChild(m),p.zoomed.classList.remove("medium-zoom-image--opened"),p.template&&document.body.removeChild(p.template),d=!1,p.zoomed.removeEventListener("transitionend",t),p.original.dispatchEvent(w("medium-zoom:closed",{detail:{zoom:k}})),p.original=null,p.zoomed=null,p.zoomedHd=null,p.template=null,e(k)})})},s=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.target;return p.original?o():a({target:t})},l=[],c=[],d=!1,u=0,h=n,p={original:null,zoomed:null,zoomedHd:null,template:null};"[object Object]"===Object.prototype.toString.call(t)?h=t:(t||"string"==typeof t)&&i(t);var m=y((h=x({margin:0,background:"#fff",scrollOffset:40,container:null,template:null},h)).background);document.addEventListener("click",function(e){var t=e.target;if(t===m)return void o();-1!==l.indexOf(t)&&s({target:t})}),document.addEventListener("keyup",function(e){var t=e.key||e.keyCode;("Escape"===t||"Esc"===t||27===t)&&o()}),document.addEventListener("scroll",function(){if(!d&&p.original){var e=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;Math.abs(u-e)>h.scrollOffset&&setTimeout(o,150)}}),window.addEventListener("resize",o);var k={open:a,close:o,toggle:s,update:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(e.background&&(m.style.background=e.background),e.container&&e.container instanceof Object&&(e.container=x({},h.container,e.container)),e.template){var t=f(e.template)?e.template:document.querySelector(e.template);e.template=t}return h=x({},h,e),l.forEach(function(e){e.dispatchEvent(w("medium-zoom:update",{detail:{zoom:k}}))}),k},clone:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return e(x({},h,t))},attach:i,detach:function(){for(var e=arguments.length,t=Array(e),n=0;n0?t.reduce(function(e,t){return[].concat(e,v(t))},[]):l;return r.forEach(function(e){e.classList.remove("medium-zoom-image"),e.dispatchEvent(w("medium-zoom:detach",{detail:{zoom:k}}))}),l=l.filter(function(e){return -1===r.indexOf(e)}),k},on:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return l.forEach(function(r){r.addEventListener("medium-zoom:"+e,t,n)}),c.push({type:"medium-zoom:"+e,listener:t,options:n}),k},off:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return l.forEach(function(r){r.removeEventListener("medium-zoom:"+e,t,n)}),c=c.filter(function(n){return n.type!=="medium-zoom:"+e||n.listener.toString()!==t.toString()}),k},getOptions:function(){return h},getImages:function(){return l},getZoomedImage:function(){return p.original}};return k};n(8046);var I=()=>{window.va||(window.va=function(...e){(window.vaq=window.vaq||[]).push(e)})};function D(){return"undefined"!=typeof window}function E(){return"production"}function F(){return(D()?window.vam:E())||"production"}function A(){return"development"===F()}var C=function(e={debug:!0}){var t;if(!D())return;!function(e="auto"){if("auto"===e){window.vam=E();return}window.vam=e}(e.mode),I(),e.beforeSend&&(null==(t=window.va)||t.call(window,"beforeSend",e.beforeSend));let n=e.scriptSrc?e.scriptSrc:A()?"https://va.vercel-scripts.com/v1/script.debug.js":e.basePath?`${e.basePath}/insights/script.js`:"/_vercel/insights/script.js";if(document.head.querySelector(`script[src*="${n}"]`))return;let r=document.createElement("script");r.src=n,r.defer=!0,r.dataset.sdkn="@vercel/analytics"+(e.framework?`/${e.framework}`:""),r.dataset.sdkv="1.5.0",e.disableAutoTrack&&(r.dataset.disableAutoTrack="1"),e.endpoint?r.dataset.endpoint=e.endpoint:e.basePath&&(r.dataset.endpoint=`${e.basePath}/insights`),e.dsn&&(r.dataset.dsn=e.dsn),r.onerror=()=>{let e=A()?"Please check if any ad blockers are enabled and try again.":"Be sure to enable Web Analytics for your project and deploy again. See https://vercel.com/docs/analytics/quickstart for more information.";console.log(`[Vercel Web Analytics] Failed to load script from ${n}. ${e}`)},A()&&!1===e.debug&&(r.dataset.debug="false"),document.head.appendChild(r)};let j=[[function(e){let{pathname:t}=(0,l.TH)(),{selector:n=".rspress-doc img",options:r={}}=e;return(0,u.useEffect)(()=>{let e,t=setTimeout(()=>{e=k(document.querySelectorAll(n),{...r,background:"var(--rp-c-bg)"})},100);return()=>{clearTimeout(t),null==e||e.detach(),null==e||e.close()}},[t]),null},{}],[function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return u.useLayoutEffect(()=>{C(e)},[]),null},{mode:"production"}]];async function P(e){var t,n;let r=(0,l.Ww)(e);if(r){let e=await r.preload(),t=(0,c.bw)(r.filePath),i=h.Z.pages.find(e=>{let t=e=>e.replace(/\/$/,"").toLowerCase();return(0,l.pV)(t(e.routePath),t(r.path))}),a=encodeURIComponent(t),o=(null==(n=e.default.__RSPRESS_PAGE_META)?void 0:n[a])||{},{toc:s=[],title:d="",frontmatter:u={},...p}=c.I6.test(r.filePath)?o:e;return{siteData:h.Z,page:{...p,pagePath:t,...i,pageType:(null==u?void 0:u.pageType)||"doc",title:d,frontmatter:u,toc:s}}}let i=h.Z.lang||"",a=(null==(t=h.Z.multiVersion)?void 0:t.default)||"";if(h.Z.lang&&"undefined"!=typeof window){let e=location.pathname.replace(h.Z.base,"").split("/").slice(0,2);if(h.Z.locales.length){let t=h.Z.locales.find(t=>{let{lang:n}=t;return e.includes(n)});t&&(i=t.lang)}if(h.Z.multiVersion.versions){let t=h.Z.multiVersion.versions.find(t=>e.includes(t));t&&(a=t)}}return{siteData:h.Z,page:{pagePath:"",pageType:"404",routePath:"/404",lang:i,frontmatter:{},title:"404",toc:[],version:a,_filepath:"",_relativePath:""}}}function S(e){let{helmetContext:t}=e,{setData:n,data:r}=(0,u.useContext)(l.R0),i=r.page.frontmatter||{},{pathname:a,search:o}=(0,l.TH)(),c=new URLSearchParams(o),h="globalUIComponents",x=!1===i[h]||"0"===c.get(h);return(0,u.useLayoutEffect)(()=>{!async function(){try{let e=await P(a);null==n||n(e)}catch(e){console.log(e)}}()},[a,n]),(0,s.jsxs)(p.B6,{context:t,children:[(0,s.jsx)(d.ZP.Layout,{}),!x&&j.map((e,t)=>{if(Array.isArray(e)){let[n,r]=e;return u.createElement(n,{key:t,...r})}return u.createElement(e,{key:t})})]})}n(6297),n(149);var T={"react-dom":function(e){e.exports=i},"react-dom/client":function(e){e.exports=o}},N={};let _=h.Z.ssg;!async function(){let e=document.getElementById("root"),t=async()=>{let e=await P(window.location.pathname);return function(){let[t,n]=(0,u.useState)(e),[r,i]=(0,d.ls)();return(0,s.jsx)(l.Ni.Provider,{value:(0,u.useMemo)(()=>({theme:r,setTheme:i}),[r,i]),children:(0,s.jsx)(l.R0.Provider,{value:(0,u.useMemo)(()=>({data:t,setData:n}),[t,n]),children:(0,s.jsx)(l.VK,{children:(0,s.jsx)(S,{})})})})}},n=await t();{let{createRoot:t,hydrateRoot:r}=function e(t){var n=N[t];if(void 0!==n)return n.exports;var r=N[t]={exports:{}};return T[t](r,r.exports,e),r.exports}("react-dom/client");(0,c.yv)()&&_?r(e,(0,s.jsx)(n,{})):t(e).render((0,s.jsx)(n,{}))}}()},5751:function(e){e.exports=function(e){return e&&e.__esModule?e:{default:e}},e.exports.__esModule=!0,e.exports.default=e.exports},65:function(e,t,n){"use strict";n.d(t,{Zo:()=>s,ah:()=>a});var r=n(7294);let i=r.createContext({});function a(e){let t=r.useContext(i);return r.useMemo(()=>"function"==typeof e?e(t):{...t,...e},[t,e])}let o={};function s({components:e,children:t,disableParentContext:n}){let s;return s=n?"function"==typeof e?e({}):e||o:a(e),r.createElement(i.Provider,{value:s},t)}},8995:function(e,t,n){"use strict";n.d(t,{$U:()=>v,E9:()=>D,I6:()=>a,Kw:()=>m,Qj:()=>x,_f:()=>u,bw:()=>c,lm:()=>d,mi:()=>p,nY:()=>h,pJ:()=>I,pZ:()=>g,rp:()=>o,t6:()=>s,tz:()=>k,xM:()=>y,xf:()=>f,yc:()=>w,yv:()=>l});let r=/\?.*$/s,i=/#.*$/s,a=/\.mdx?$/,o="rspress-theme-appearance",s="search_index",l=()=>!0,c=e=>e.replace(i,"").replace(r,"");function d(e){return e.replace(/#.*$/,"")}let u=()=>!0;function h(e){return"/"===e.charAt(0)||f(e)?e:`/${e}`}function p(e){return"/"===e.charAt(e.length-1)?e:`${e}/`}function x(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function m(e){return x(h(function(e){let t=e.replace(/\\/g,"/"),n=t.startsWith("/"),r=t.split("/"),i=[];for(let e of r)"."===e||""===e||(".."===e?i.length>0&&".."!==i[i.length-1]?i.pop():n&&i.push(".."):i.push(e));let a=i.join("/");return n&&(a=`/${a}`),a}(e)))}function f(e=""){return e.startsWith("http://")||e.startsWith("https://")||e.startsWith("mailto:")||e.startsWith("tel:")}function g(e=""){return/^\s*data:/i.test(e)}function v(e,t,n,r="",i=!1,a=!1){let o=D(e,r);(!o||a)&&(o=i?"/index":"/index.html"),o.endsWith("/")&&(o+=i?"/index":"/index.html");let s="",l="",c="",d=o.split("/").filter(Boolean);return n.current&&n.current!==n.default&&(s=d.shift()||""),t.target!==t.default?(l=t.target,t.current!==t.default&&d.shift()):d.shift(),c=d.join("/")||"",(s||l)&&!c&&(c=i?"index":"index.html"),I(h([s,l,c].filter(Boolean).join("/")),r)}function y(e,t,n="",r=!1,i=!1){let a=D(e,n);(!a||i)&&(a=r?"/index":"/index.html");let o="",s=a.split("/").filter(Boolean);t.target!==t.default?(o=t.target,t.current!==t.default&&s.shift()):s.shift();let l=s.join("/")||"";return o&&!l&&(l=r?"index":"index.html"),I(h([o,l].filter(Boolean).join("/")),n)}let b=e=>{let[t,n=""]=e.split("#");return{url:t,hash:n}};function w(e,t=!1){if(!e)return"/";if(f(e))return e;let{url:n,hash:r}=b(decodeURIComponent(e));return t||n.endsWith(".html")||(n.endsWith("/")?n+="index.html":n+=".html"),t&&n.endsWith("/")&&(n+="index"),t&&n.endsWith(".html")&&(n=n.replace(/\.html$/,"")),h(r?`${n}#${r}`:n)}function k(e,t){return h(e).replace(m(t),"")}function I(e,t){let n=h(e),r=m(t);return n.startsWith(r)?n:`${r}${n}`}function D(e,t){return h(e).replace(RegExp(`^${m(t)}`),"")}},5552:function(e,t,n){"use strict";let r;n.d(t,{qx:()=>nS,g2:()=>r0,zx:()=>rh,xK:()=>rv,JL:()=>rZ,SU:()=>r7,ls:()=>rd,rU:()=>nm,xB:()=>rb,pU:()=>it,OK:()=>io,TJ:()=>nY,Qe:()=>r9,mQ:()=>ia,O9:()=>rk,BZ:()=>rg,mi:()=>rx,ZP:()=>ig,Vp:()=>im,ol:()=>ix});var i,a,o,s,l={};n.r(l),n.d(l,{onSearch:()=>tB}),n(6612);var c=n(5893),d=n(65),u=n(436);let h=/[\0-\x1F!-,\.\/:-@\[-\^`\{-\xA9\xAB-\xB4\xB6-\xB9\xBB-\xBF\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0378\u0379\u037E\u0380-\u0385\u0387\u038B\u038D\u03A2\u03F6\u0482\u0530\u0557\u0558\u055A-\u055F\u0589-\u0590\u05BE\u05C0\u05C3\u05C6\u05C8-\u05CF\u05EB-\u05EE\u05F3-\u060F\u061B-\u061F\u066A-\u066D\u06D4\u06DD\u06DE\u06E9\u06FD\u06FE\u0700-\u070F\u074B\u074C\u07B2-\u07BF\u07F6-\u07F9\u07FB\u07FC\u07FE\u07FF\u082E-\u083F\u085C-\u085F\u086B-\u089F\u08B5\u08C8-\u08D2\u08E2\u0964\u0965\u0970\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09F2-\u09FB\u09FD\u09FF\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A76-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF0-\u0AF8\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B54\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B70\u0B72-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BF0-\u0BFF\u0C0D\u0C11\u0C29\u0C3A-\u0C3C\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5B-\u0C5F\u0C64\u0C65\u0C70-\u0C7F\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDD\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0CFF\u0D0D\u0D11\u0D45\u0D49\u0D4F-\u0D53\u0D58-\u0D5E\u0D64\u0D65\u0D70-\u0D79\u0D80\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DE5\u0DF0\u0DF1\u0DF4-\u0E00\u0E3B-\u0E3F\u0E4F\u0E5A-\u0E80\u0E83\u0E85\u0E8B\u0EA4\u0EA6\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F01-\u0F17\u0F1A-\u0F1F\u0F2A-\u0F34\u0F36\u0F38\u0F3A-\u0F3D\u0F48\u0F6D-\u0F70\u0F85\u0F98\u0FBD-\u0FC5\u0FC7-\u0FFF\u104A-\u104F\u109E\u109F\u10C6\u10C8-\u10CC\u10CE\u10CF\u10FB\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u1360-\u137F\u1390-\u139F\u13F6\u13F7\u13FE-\u1400\u166D\u166E\u1680\u169B-\u169F\u16EB-\u16ED\u16F9-\u16FF\u170D\u1715-\u171F\u1735-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17D4-\u17D6\u17D8-\u17DB\u17DE\u17DF\u17EA-\u180A\u180E\u180F\u181A-\u181F\u1879-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191F\u192C-\u192F\u193C-\u1945\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DA-\u19FF\u1A1C-\u1A1F\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1AA6\u1AA8-\u1AAF\u1AC1-\u1AFF\u1B4C-\u1B4F\u1B5A-\u1B6A\u1B74-\u1B7F\u1BF4-\u1BFF\u1C38-\u1C3F\u1C4A-\u1C4C\u1C7E\u1C7F\u1C89-\u1C8F\u1CBB\u1CBC\u1CC0-\u1CCF\u1CD3\u1CFB-\u1CFF\u1DFA\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FBD\u1FBF-\u1FC1\u1FC5\u1FCD-\u1FCF\u1FD4\u1FD5\u1FDC-\u1FDF\u1FED-\u1FF1\u1FF5\u1FFD-\u203E\u2041-\u2053\u2055-\u2070\u2072-\u207E\u2080-\u208F\u209D-\u20CF\u20F1-\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F-\u215F\u2189-\u24B5\u24EA-\u2BFF\u2C2F\u2C5F\u2CE5-\u2CEA\u2CF4-\u2CFF\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D70-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E00-\u2E2E\u2E30-\u3004\u3008-\u3020\u3030\u3036\u3037\u303D-\u3040\u3097\u3098\u309B\u309C\u30A0\u30FB\u3100-\u3104\u3130\u318F-\u319F\u31C0-\u31EF\u3200-\u33FF\u4DC0-\u4DFF\u9FFD-\u9FFF\uA48D-\uA4CF\uA4FE\uA4FF\uA60D-\uA60F\uA62C-\uA63F\uA673\uA67E\uA6F2-\uA716\uA720\uA721\uA789\uA78A\uA7C0\uA7C1\uA7CB-\uA7F4\uA828-\uA82B\uA82D-\uA83F\uA874-\uA87F\uA8C6-\uA8CF\uA8DA-\uA8DF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA954-\uA95F\uA97D-\uA97F\uA9C1-\uA9CE\uA9DA-\uA9DF\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A-\uAA5F\uAA77-\uAA79\uAAC3-\uAADA\uAADE\uAADF\uAAF0\uAAF1\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F\uAB5B\uAB6A-\uAB6F\uABEB\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uE000-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB29\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBB2-\uFBD2\uFD3E-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFC-\uFDFF\uFE10-\uFE1F\uFE30-\uFE32\uFE35-\uFE4C\uFE50-\uFE6F\uFE75\uFEFD-\uFF0F\uFF1A-\uFF20\uFF3B-\uFF3E\uFF40\uFF5B-\uFF65\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFFF]|\uD800[\uDC0C\uDC27\uDC3B\uDC3E\uDC4E\uDC4F\uDC5E-\uDC7F\uDCFB-\uDD3F\uDD75-\uDDFC\uDDFE-\uDE7F\uDE9D-\uDE9F\uDED1-\uDEDF\uDEE1-\uDEFF\uDF20-\uDF2C\uDF4B-\uDF4F\uDF7B-\uDF7F\uDF9E\uDF9F\uDFC4-\uDFC7\uDFD0\uDFD6-\uDFFF]|\uD801[\uDC9E\uDC9F\uDCAA-\uDCAF\uDCD4-\uDCD7\uDCFC-\uDCFF\uDD28-\uDD2F\uDD64-\uDDFF\uDF37-\uDF3F\uDF56-\uDF5F\uDF68-\uDFFF]|\uD802[\uDC06\uDC07\uDC09\uDC36\uDC39-\uDC3B\uDC3D\uDC3E\uDC56-\uDC5F\uDC77-\uDC7F\uDC9F-\uDCDF\uDCF3\uDCF6-\uDCFF\uDD16-\uDD1F\uDD3A-\uDD7F\uDDB8-\uDDBD\uDDC0-\uDDFF\uDE04\uDE07-\uDE0B\uDE14\uDE18\uDE36\uDE37\uDE3B-\uDE3E\uDE40-\uDE5F\uDE7D-\uDE7F\uDE9D-\uDEBF\uDEC8\uDEE7-\uDEFF\uDF36-\uDF3F\uDF56-\uDF5F\uDF73-\uDF7F\uDF92-\uDFFF]|\uD803[\uDC49-\uDC7F\uDCB3-\uDCBF\uDCF3-\uDCFF\uDD28-\uDD2F\uDD3A-\uDE7F\uDEAA\uDEAD-\uDEAF\uDEB2-\uDEFF\uDF1D-\uDF26\uDF28-\uDF2F\uDF51-\uDFAF\uDFC5-\uDFDF\uDFF7-\uDFFF]|\uD804[\uDC47-\uDC65\uDC70-\uDC7E\uDCBB-\uDCCF\uDCE9-\uDCEF\uDCFA-\uDCFF\uDD35\uDD40-\uDD43\uDD48-\uDD4F\uDD74\uDD75\uDD77-\uDD7F\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDFF\uDE12\uDE38-\uDE3D\uDE3F-\uDE7F\uDE87\uDE89\uDE8E\uDE9E\uDEA9-\uDEAF\uDEEB-\uDEEF\uDEFA-\uDEFF\uDF04\uDF0D\uDF0E\uDF11\uDF12\uDF29\uDF31\uDF34\uDF3A\uDF45\uDF46\uDF49\uDF4A\uDF4E\uDF4F\uDF51-\uDF56\uDF58-\uDF5C\uDF64\uDF65\uDF6D-\uDF6F\uDF75-\uDFFF]|\uD805[\uDC4B-\uDC4F\uDC5A-\uDC5D\uDC62-\uDC7F\uDCC6\uDCC8-\uDCCF\uDCDA-\uDD7F\uDDB6\uDDB7\uDDC1-\uDDD7\uDDDE-\uDDFF\uDE41-\uDE43\uDE45-\uDE4F\uDE5A-\uDE7F\uDEB9-\uDEBF\uDECA-\uDEFF\uDF1B\uDF1C\uDF2C-\uDF2F\uDF3A-\uDFFF]|\uD806[\uDC3B-\uDC9F\uDCEA-\uDCFE\uDD07\uDD08\uDD0A\uDD0B\uDD14\uDD17\uDD36\uDD39\uDD3A\uDD44-\uDD4F\uDD5A-\uDD9F\uDDA8\uDDA9\uDDD8\uDDD9\uDDE2\uDDE5-\uDDFF\uDE3F-\uDE46\uDE48-\uDE4F\uDE9A-\uDE9C\uDE9E-\uDEBF\uDEF9-\uDFFF]|\uD807[\uDC09\uDC37\uDC41-\uDC4F\uDC5A-\uDC71\uDC90\uDC91\uDCA8\uDCB7-\uDCFF\uDD07\uDD0A\uDD37-\uDD39\uDD3B\uDD3E\uDD48-\uDD4F\uDD5A-\uDD5F\uDD66\uDD69\uDD8F\uDD92\uDD99-\uDD9F\uDDAA-\uDEDF\uDEF7-\uDFAF\uDFB1-\uDFFF]|\uD808[\uDF9A-\uDFFF]|\uD809[\uDC6F-\uDC7F\uDD44-\uDFFF]|[\uD80A\uD80B\uD80E-\uD810\uD812-\uD819\uD824-\uD82B\uD82D\uD82E\uD830-\uD833\uD837\uD839\uD83D\uD83F\uD87B-\uD87D\uD87F\uD885-\uDB3F\uDB41-\uDBFF][\uDC00-\uDFFF]|\uD80D[\uDC2F-\uDFFF]|\uD811[\uDE47-\uDFFF]|\uD81A[\uDE39-\uDE3F\uDE5F\uDE6A-\uDECF\uDEEE\uDEEF\uDEF5-\uDEFF\uDF37-\uDF3F\uDF44-\uDF4F\uDF5A-\uDF62\uDF78-\uDF7C\uDF90-\uDFFF]|\uD81B[\uDC00-\uDE3F\uDE80-\uDEFF\uDF4B-\uDF4E\uDF88-\uDF8E\uDFA0-\uDFDF\uDFE2\uDFE5-\uDFEF\uDFF2-\uDFFF]|\uD821[\uDFF8-\uDFFF]|\uD823[\uDCD6-\uDCFF\uDD09-\uDFFF]|\uD82C[\uDD1F-\uDD4F\uDD53-\uDD63\uDD68-\uDD6F\uDEFC-\uDFFF]|\uD82F[\uDC6B-\uDC6F\uDC7D-\uDC7F\uDC89-\uDC8F\uDC9A-\uDC9C\uDC9F-\uDFFF]|\uD834[\uDC00-\uDD64\uDD6A-\uDD6C\uDD73-\uDD7A\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDE41\uDE45-\uDFFF]|\uD835[\uDC55\uDC9D\uDCA0\uDCA1\uDCA3\uDCA4\uDCA7\uDCA8\uDCAD\uDCBA\uDCBC\uDCC4\uDD06\uDD0B\uDD0C\uDD15\uDD1D\uDD3A\uDD3F\uDD45\uDD47-\uDD49\uDD51\uDEA6\uDEA7\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3\uDFCC\uDFCD]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85-\uDE9A\uDEA0\uDEB0-\uDFFF]|\uD838[\uDC07\uDC19\uDC1A\uDC22\uDC25\uDC2B-\uDCFF\uDD2D-\uDD2F\uDD3E\uDD3F\uDD4A-\uDD4D\uDD4F-\uDEBF\uDEFA-\uDFFF]|\uD83A[\uDCC5-\uDCCF\uDCD7-\uDCFF\uDD4C-\uDD4F\uDD5A-\uDFFF]|\uD83B[\uDC00-\uDDFF\uDE04\uDE20\uDE23\uDE25\uDE26\uDE28\uDE33\uDE38\uDE3A\uDE3C-\uDE41\uDE43-\uDE46\uDE48\uDE4A\uDE4C\uDE50\uDE53\uDE55\uDE56\uDE58\uDE5A\uDE5C\uDE5E\uDE60\uDE63\uDE65\uDE66\uDE6B\uDE73\uDE78\uDE7D\uDE7F\uDE8A\uDE9C-\uDEA0\uDEA4\uDEAA\uDEBC-\uDFFF]|\uD83C[\uDC00-\uDD2F\uDD4A-\uDD4F\uDD6A-\uDD6F\uDD8A-\uDFFF]|\uD83E[\uDC00-\uDFEF\uDFFA-\uDFFF]|\uD869[\uDEDE-\uDEFF]|\uD86D[\uDF35-\uDF3F]|\uD86E[\uDC1E\uDC1F]|\uD873[\uDEA2-\uDEAF]|\uD87A[\uDFE1-\uDFFF]|\uD87E[\uDE1E-\uDFFF]|\uD884[\uDF4B-\uDFFF]|\uDB40[\uDC00-\uDCFF\uDDF0-\uDFFF]/g;var p=n(7294),x=n(8995);let m=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)};var f="object"==typeof global&&global&&global.Object===Object&&global,g="object"==typeof self&&self&&self.Object===Object&&self,v=f||g||Function("return this")();let y=function(){return v.Date.now()};var b=/\s/;let w=function(e){for(var t=e.length;t--&&b.test(e.charAt(t)););return t};var k=/^\s+/,I=v.Symbol,D=Object.prototype,E=D.hasOwnProperty,F=D.toString,A=I?I.toStringTag:void 0;let C=function(e){var t=E.call(e,A),n=e[A];try{e[A]=void 0;var r=!0}catch(e){}var i=F.call(e);return r&&(t?e[A]=n:delete e[A]),i};var j=Object.prototype.toString,P=I?I.toStringTag:void 0;let S=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":P&&P in Object(e)?C(e):j.call(e)},T=function(e){return"symbol"==typeof e||null!=e&&"object"==typeof e&&"[object Symbol]"==S(e)};var N=0/0,_=/^[-+]0x[0-9a-f]+$/i,B=/^0b[01]+$/i,O=/^0o[0-7]+$/i,R=parseInt;let q=function(e){if("number"==typeof e)return e;if(T(e))return N;if(m(e)){var t,n="function"==typeof e.valueOf?e.valueOf():e;e=m(n)?n+"":n}if("string"!=typeof e)return 0===e?e:+e;e=(t=e)?t.slice(0,w(t)+1).replace(k,""):t;var r=B.test(e);return r||O.test(e)?R(e.slice(2),r?2:8):_.test(e)?N:+e};var L=Math.max,M=Math.min;let z=function(e,t,n){var r,i,a,o,s,l,c=0,d=!1,u=!1,h=!0;if("function"!=typeof e)throw TypeError("Expected a function");function p(t){var n=r,a=i;return r=i=void 0,c=t,o=e.apply(a,n)}function x(e){var n=e-l,r=e-c;return void 0===l||n>=t||n<0||u&&r>=a}function f(){var e,n,r,i=y();if(x(i))return g(i);s=setTimeout(f,(e=i-l,n=i-c,r=t-e,u?M(r,a-n):r))}function g(e){return(s=void 0,h&&r)?p(e):(r=i=void 0,o)}function v(){var e,n=y(),a=x(n);if(r=arguments,i=this,l=n,a){if(void 0===s)return c=e=l,s=setTimeout(f,t),d?p(e):o;if(u)return clearTimeout(s),s=setTimeout(f,t),p(l)}return void 0===s&&(s=setTimeout(f,t)),o}return t=q(t)||0,m(n)&&(d=!!n.leading,a=(u="maxWait"in n)?L(q(n.maxWait)||0,t):a,h="trailing"in n?!!n.trailing:h),v.cancel=function(){void 0!==s&&clearTimeout(s),c=0,r=l=i=s=void 0},v.flush=function(){return void 0===s?o:g(y())},v},H=function(e,t,n){var r=!0,i=!0;if("function"!=typeof e)throw TypeError("Expected a function");return m(n)&&(r="leading"in n?!!n.leading:r,i="trailing"in n?!!n.trailing:i),z(e,t,{leading:r,maxWait:t,trailing:i})};var $=n(5598);let W=e=>(0,c.jsx)("svg",{width:"1em",height:"1em",viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M22 16 12 26l-1.4-1.4 8.6-8.6-8.6-8.6L12 6z"})}),K=e=>(0,c.jsx)("svg",{width:"1em",height:"1em",viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M4 6h24v2H4zm0 18h24v2H4zm0-12h24v2H4zm0 6h24v2H4z"})});var U=n(4865);n(9284);var V=n(405);let G=e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:32,height:32,viewBox:"0 0 24 24",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M16 7H3V5h13zM3 19h13v-2H3zm19-7-4-3v2H3v2h15v2z"})}),Z=e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:32,height:32,viewBox:"0 0 24 24",...e,children:(0,c.jsx)("path",{fill:"#22a041",d:"M21 5H3v2h18zM3 19h7v-2H3zm0-6h15c1 0 2 .43 2 2s-1 2-2 2h-2v-2l-4 3 4 3v-2h2c2.95 0 4-1.27 4-4 0-2.72-1-4-4-4H3z"})}),J=e=>(0,c.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:32,height:32,viewBox:"0 0 30 30",...e,children:[(0,c.jsx)("path",{fill:"currentColor",d:"M28 10v18H10V10zm0-2H10a2 2 0 0 0-2 2v18a2 2 0 0 0 2 2h18a2 2 0 0 0 2-2V10a2 2 0 0 0-2-2"}),(0,c.jsx)("path",{fill:"currentColor",d:"M4 18H2V4a2 2 0 0 1 2-2h14v2H4Z"})]}),Q=e=>(0,c.jsx)("svg",{width:32,height:32,viewBox:"0 0 30 30",...e,children:(0,c.jsx)("path",{fill:"#49cd37",d:"m13 24-9-9 1.414-1.414L13 21.171 26.586 7.586 28 9z"})});var Y=n(640);function X(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0;return(function(e){if(0===e.length||1===e.length)return e;var t,n=e.join(".");return eo[n]||(eo[n]=0===(t=e.length)||1===t?e:2===t?[e[0],e[1],"".concat(e[0],".").concat(e[1]),"".concat(e[1],".").concat(e[0])]:3===t?[e[0],e[1],e[2],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0])]:t>=4?[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]:void 0),eo[n]})(e.filter(function(e){return"token"!==e})).reduce(function(e,t){return ea(ea({},e),n[t])},t)}(s.className,Object.assign({},s.style,void 0===i?{}:i),r)})}else h=ea(ea({},s),{},{className:s.className.join(" ")});var v=x(n.children);return p.createElement(c,er({key:o},h),v)}}({node:e,stylesheet:n,useInlineStyles:r,key:"code-segement".concat(t)})})}function ef(e){return e&&void 0!==e.highlightAuto}var eg=n(1215),ev=n.n(eg),ey=(i=ev(),a={},function(e){var t=e.language,n=e.children,r=e.style,o=void 0===r?a:r,s=e.customStyle,l=void 0===s?{}:s,c=e.codeTagProps,d=void 0===c?{className:t?"language-".concat(t):void 0,style:ec(ec({},o['code[class*="language-"]']),o['code[class*="language-'.concat(t,'"]')])}:c,u=e.useInlineStyles,h=void 0===u||u,x=e.showLineNumbers,m=void 0!==x&&x,f=e.showInlineLineNumbers,g=void 0===f||f,v=e.startingLineNumber,y=void 0===v?1:v,b=e.lineNumberContainerStyle,w=e.lineNumberStyle,k=void 0===w?{}:w,I=e.wrapLines,D=e.wrapLongLines,E=void 0!==D&&D,F=e.lineProps,A=e.renderer,C=e.PreTag,j=void 0===C?"pre":C,P=e.CodeTag,S=void 0===P?"code":P,T=e.code,N=void 0===T?(Array.isArray(n)?n[0]:n)||"":T,_=e.astGenerator,B=function(e,t){if(null==e)return{};var n,r,i=function(e,t){if(null==e)return{};var n={};for(var r in e)if(({}).hasOwnProperty.call(e,r)){if(-1!==t.indexOf(r))continue;n[r]=e[r]}return n}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r1&&void 0!==arguments[1]?arguments[1]:[],r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],i=0;i2&&void 0!==arguments[2]?arguments[2]:[];return t||c.length>0?function(e,a){var c=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return ex({children:e,lineNumber:a,lineNumberStyle:s,largestLineNumber:o,showInlineLineNumbers:i,lineProps:n,className:c,showLineNumbers:r,wrapLongLines:l,wrapLines:t})}(e,a,c):function(e,t){if(r&&t&&i){var n=ep(s,t,o);e.unshift(eh(t,n))}return e}(e,a)}for(;p=r))));t++);if(n)return a?eJ(l,r,0):void(t[t.length]=l)}return!n&&l}function eJ(e,t,n){return e=1===e.length?e[0]:[].concat.apply([],e),n||e.length>t?e.slice(n,n+t):e}function eQ(e,t,n,r){return e=n?(e=e[(r=r&&t>n)?t:n])&&e[r?n:t]:e[t]}function eY(e,t,n,r,i){let a=0;if(e.constructor===Array)if(i)-1!==(t=e.indexOf(t))?1=this.B&&(u||!d[x])){var a=eV(h,r,p),o="";switch(this.G){case"full":if(2a;s--)if(s-a>=this.B){var l=eV(h,r,p,i,a);eG(this,d,o=x.substring(a,s),l,e,n)}break}case"reverse":if(1=this.B&&eG(this,d,o,eV(h,r,p,i,s),e,n);o=""}case"forward":if(1=this.B&&eG(this,d,o,a,e,n);break}default:if(this.C&&(a=Math.min(a/this.C(t,x,p)|0,h-1)),eG(this,d,x,a,e,n),u&&1=this.B&&!i[x]){i[x]=1;let t=this.l&&x>a;eG(this,c,t?a:x,eV(o+(r/2>o?0:1),r,p,s-1,l-1),e,n,t?x:a)}}}}}this.m||(this.register[e]=1)}}return this},s.search=function(e,t,n){let r,i,a;n||(!t&&eA(e)?e=(n=e).query:eA(t)&&(n=t));let o=[],s,l,c=0;if(n){e=n.query||e,t=n.limit,c=n.offset||0;var d=n.context;l=n.suggest}if(e&&1<(s=(e=this.encode(""+e)).length)){n=eD();var u=[];for(let t=0,r=0,i;t=this.B&&!n[i])if(!this.s&&!l&&!this.map[i])return o;else u[r++]=i,n[i]=1;s=(e=u).length}if(!s)return o;for(t||(t=100),d=this.depth&&1{a=e})),i||(i=0)){case 0:if(o="reg",this.m)for(let e in s=eD(),this.register)s[e]=1;else s=this.register;break;case 1:o="cfg",s={doc:0,opt:+!!this.s};break;case 2:o="map",s=this.map;break;case 3:o="ctx",s=this.h;break;default:void 0===n&&a&&a();return}return eK(e,t||this,n,o,r,i,s,a),l},s.import=function(e,t){if(t)switch(eF(t)&&(t=JSON.parse(t)),e){case"cfg":this.s=!!t.opt;break;case"reg":this.m=!1,this.register=t;break;case"map":this.map=t;break;case"ctx":this.h=t}},eL(eU.prototype);let e1=0;function e0(e){var t;if(!(this instanceof e0))return new e0(e);e?eC(t=e.encode)&&(e.encode=t.toString()):e={},(t=(self||window)._factory)&&(t=t.toString());let r="undefined"==typeof window&&self.exports,i=this;this.o=function(e,t,r){let i;try{i=t?new(n(7770)).Worker("//node/node.js"):e?new Worker(URL.createObjectURL(new Blob(["onmessage="+eX.toString()],{type:"text/javascript"}))):new Worker(eF(r)?r:"worker/worker.js",{type:"module"})}catch(e){}return i}(t,r,e.worker),this.h=eD(),this.o&&(r?this.o.on("message",function(e){i.h[e.id](e.msg),delete i.h[e.id]}):this.o.onmessage=function(e){e=e.data,i.h[e.id](e.msg),delete i.h[e.id]},this.o.postMessage({task:"init",factory:t,options:e}))}function e2(e){e0.prototype[e]=e0.prototype[e+"Async"]=function(){let t,n=this,r=[].slice.call(arguments);var i=r[r.length-1];return eC(i)&&(t=i,r.splice(r.length-1,1)),i=new Promise(function(t){setTimeout(function(){n.h[++e1]=t,n.o.postMessage({task:e,id:e1,args:r})})}),t?(i.then(t),this):i}}function e3(e){if(!(this instanceof e3))return new e3(e);var t,n=e.document||e.doc||e;this.K=[],this.h=[],this.A=[],this.register=eD(),this.key=(t=n.key||n.id)&&e4(t,this.A)||"id",this.m=ek(e.fastupdate),this.C=(t=n.store)&&!0!==t&&[],this.store=t&&eD(),this.I=(t=n.tag)&&e4(t,this.A),this.l=t&&eD(),this.cache=(t=e.cache)&&new eH(t),e.cache=!1,this.o=e.worker,this.async=!1,t=eD();let r=n.index||n.field||n;eF(r)&&(r=[r]);for(let n=0,i,a;nt||n)&&(i=i.slice(n,n+t)),r&&(i=e7.call(this,i)),{tag:e,result:i}}function e7(e){let t=Array(e.length);for(let n=0,r;n{a=e})),i||(i=0),r||(r=0),r(0,c.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:32,height:32,viewBox:"0 0 32 32",...e,children:[(0,c.jsx)("circle",{cx:8,cy:16,r:2,fill:"currentColor"}),(0,c.jsx)("circle",{cx:16,cy:16,r:2,fill:"currentColor"}),(0,c.jsx)("circle",{cx:24,cy:16,r:2,fill:"currentColor"})]});var tc=!1;if("undefined"!=typeof window){var td={get passive(){tc=!0;return}};window.addEventListener("testPassive",null,td),window.removeEventListener("testPassive",null,td)}var tu="undefined"!=typeof window&&window.navigator&&window.navigator.platform&&(/iP(ad|hone|od)/.test(window.navigator.platform)||"MacIntel"===window.navigator.platform&&window.navigator.maxTouchPoints>1),th=[],tp=!1,tx=-1,tm=void 0,tf=void 0,tg=void 0,tv=function(e){return th.some(function(t){return!!(t.options.allowTouchMove&&t.options.allowTouchMove(e))})},ty=function(e){var t=e||window.event;return!!tv(t.target)||t.touches.length>1||(t.preventDefault&&t.preventDefault(),!1)},tb=function(e){if(void 0===tg){var t=!!e&&!0===e.reserveScrollBarGap,n=window.innerWidth-document.documentElement.clientWidth;if(t&&n>0){var r=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right"),10);tg=document.body.style.paddingRight,document.body.style.paddingRight=r+n+"px"}}void 0===tm&&(tm=document.body.style.overflow,document.body.style.overflow="hidden")},tw=function(){void 0!==tg&&(document.body.style.paddingRight=tg,tg=void 0),void 0!==tm&&(document.body.style.overflow=tm,tm=void 0)},tk=function(){if(void 0!==tf){var e=-parseInt(document.body.style.top,10),t=-parseInt(document.body.style.left,10);document.body.style.position=tf.position,document.body.style.top=tf.top,document.body.style.left=tf.left,window.scrollTo(t,e),tf=void 0}},tI=function(e,t){var n=e.targetTouches[0].clientY-tx;return!tv(e.target)&&(t&&0===t.scrollTop&&n>0?ty(e):t&&t.scrollHeight-t.scrollTop<=t.clientHeight&&n<0?ty(e):(e.stopPropagation(),!0))},tD=function(e,t){if(!e)return void console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.");!th.some(function(t){return t.targetElement===e})&&(th=[].concat(function(e){if(!Array.isArray(e))return Array.from(e);for(var t=0,n=Array(e.length);t=r&&(document.body.style.top=-(t+e))})},300)}}):tb(t),tu&&(e.ontouchstart=function(e){1===e.targetTouches.length&&(tx=e.targetTouches[0].clientY)},e.ontouchmove=function(t){1===t.targetTouches.length&&tI(t,e)},tp||(document.addEventListener("touchmove",ty,tc?{passive:!1}:void 0),tp=!0)))},tE=function(){tu&&(th.forEach(function(e){e.targetElement.ontouchstart=null,e.targetElement.ontouchmove=null}),tp&&(document.removeEventListener("touchmove",ty,tc?{passive:!1}:void 0),tp=!1),tx=-1),tu?tk():tw(),th=[]};let tF=e=>(0,c.jsx)("svg",{width:18,height:18,viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M27.85 29H30l-6-15h-2.35l-6 15h2.15l1.6-4h6.85zm-7.65-6 2.62-6.56L25.45 23zM18 7V5h-7V2H9v3H2v2h10.74a14.7 14.7 0 0 1-3.19 6.18A13.5 13.5 0 0 1 7.26 9h-2.1a16.5 16.5 0 0 0 3 5.58A16.8 16.8 0 0 1 3 18l.75 1.86A18.5 18.5 0 0 0 9.53 16a16.9 16.9 0 0 0 5.76 3.84L16 18a14.5 14.5 0 0 1-5.12-3.37A17.64 17.64 0 0 0 14.8 7z"})}),tA=e=>(0,c.jsx)("svg",{width:"1em",height:"1em",viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M16 22 6 12l1.4-1.4 8.6 8.6 8.6-8.6L26 12z"})}),tC=e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",viewBox:"0 0 24 24",...e,children:(0,c.jsx)("path",{d:"M12.1 22h-.9c-5.5-.5-9.5-5.4-9-10.9.4-4.8 4.2-8.6 9-9 .4 0 .8.2 1 .5s.2.8-.1 1.1c-2 2.7-1.4 6.4 1.3 8.4 2.1 1.6 5 1.6 7.1 0 .3-.2.7-.3 1.1-.1.3.2.5.6.5 1-.2 2.7-1.5 5.1-3.6 6.8-1.9 1.4-4.1 2.2-6.4 2.2M9.3 4.4c-2.9 1-5 3.6-5.2 6.8-.4 4.4 2.8 8.3 7.2 8.7 2.1.2 4.2-.4 5.8-1.8 1.1-.9 1.9-2.1 2.4-3.4-2.5.9-5.3.5-7.5-1.1-2.8-2.2-3.9-5.9-2.7-9.2"})}),tj=e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",viewBox:"0 0 24 24",...e,children:(0,c.jsx)("path",{d:"M12 18c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6m0-10c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4M12 4c-.6 0-1-.4-1-1V1c0-.6.4-1 1-1s1 .4 1 1v2c0 .6-.4 1-1 1M12 24c-.6 0-1-.4-1-1v-2c0-.6.4-1 1-1s1 .4 1 1v2c0 .6-.4 1-1 1M5.6 6.6c-.3 0-.5-.1-.7-.3L3.5 4.9c-.4-.4-.4-1 0-1.4s1-.4 1.4 0l1.4 1.4c.4.4.4 1 0 1.4-.1.2-.4.3-.7.3M19.8 20.8c-.3 0-.5-.1-.7-.3l-1.4-1.4c-.4-.4-.4-1 0-1.4s1-.4 1.4 0l1.4 1.4c.4.4.4 1 0 1.4-.2.2-.5.3-.7.3M3 13H1c-.6 0-1-.4-1-1s.4-1 1-1h2c.6 0 1 .4 1 1s-.4 1-1 1M23 13h-2c-.6 0-1-.4-1-1s.4-1 1-1h2c.6 0 1 .4 1 1s-.4 1-1 1M4.2 20.8c-.3 0-.5-.1-.7-.3-.4-.4-.4-1 0-1.4l1.4-1.4c.4-.4 1-.4 1.4 0s.4 1 0 1.4l-1.4 1.4c-.2.2-.4.3-.7.3M18.4 6.6c-.3 0-.5-.1-.7-.3-.4-.4-.4-1 0-1.4l1.4-1.4c.4-.4 1-.4 1.4 0s.4 1 0 1.4l-1.4 1.4c-.2.2-.5.3-.7.3"})});var tP=n(3935);let tS=e=>(0,c.jsx)("svg",{width:"1em",height:"1em",viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M16 22 6 12l1.4-1.4 8.6 8.6 8.6-8.6L26 12z"})}),tT=e=>(0,c.jsx)("svg",{width:24,height:24,viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"var(--rp-c-gray)",d:"m29 27.586-7.552-7.552a11.018 11.018 0 1 0-1.414 1.414L27.586 29ZM4 13a9 9 0 1 1 9 9 9.01 9.01 0 0 1-9-9"})}),tN=e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M24 9.4 22.6 8 16 14.6 9.4 8 8 9.4l6.6 6.6L8 22.6 9.4 24l6.6-6.6 6.6 6.6 1.4-1.4-6.6-6.6z"})}),t_=e=>(0,c.jsx)("svg",{width:32,height:32,viewBox:"0 0 24 24",...e,children:(0,c.jsxs)("g",{fill:"none",stroke:"var(--rp-c-brand)",strokeLinecap:"round",strokeWidth:2,children:[(0,c.jsx)("path",{strokeDasharray:60,strokeDashoffset:60,strokeOpacity:.3,d:"M12 3a9 9 0 1 1 0 18 9 9 0 0 1 0-18Z",children:(0,c.jsx)("animate",{fill:"freeze",attributeName:"stroke-dashoffset",dur:"1.3s",values:"60;0"})}),(0,c.jsxs)("path",{strokeDasharray:15,strokeDashoffset:15,d:"M12 3a9 9 0 0 1 9 9",children:[(0,c.jsx)("animate",{fill:"freeze",attributeName:"stroke-dashoffset",dur:"0.3s",values:"15;0"}),(0,c.jsx)("animateTransform",{attributeName:"transform",dur:"1.5s",repeatCount:"indefinite",type:"rotate",values:"0 12 12;360 12 12"})]})]})}),tB=()=>{},tO=e=>(0,c.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:48,height:48,fill:"none",viewBox:"0 0 48 48",...e,children:[(0,c.jsx)("path",{stroke:"currentColor",strokeWidth:4,d:"M24 5v6m7 1 4-4m-18 4-4-4m27 33H8a2 2 0 0 1-2-2v-8.46a2 2 0 0 1 .272-1.007l6.15-10.54A2 2 0 0 1 14.148 18H33.85a2 2 0 0 1 1.728.992l6.149 10.541A2 2 0 0 1 42 30.541V39a2 2 0 0 1-2 2Z"}),(0,c.jsx)("path",{stroke:"currentColor",strokeWidth:4,d:"M41.5 30H28s-1 3-4 3-4-3-4-3H6.5"})]}),tR=e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M13.414 17.586 18 22.172V8H8V6h10a2 2 0 0 1 2 2v14.172l4.586-4.586L26 19l-7 7-7-7Z"})});function tq(){let{siteData:{themeConfig:e}}=(0,u.Vi)(),t=e.hideNavbar??"never",[n,r]=(0,p.useState)(!1),{pathname:i}=(0,u.TH)(),a=(0,p.useRef)(0);return"never"!==t&&("always"===t||((0,p.useEffect)(()=>{r(!1);let e=H(()=>{let{scrollTop:e}=document.documentElement;e!==a.current&&(r(a.current>0&&e-a.current>0),a.current=e<=0?0:e)},200);return window.addEventListener("scroll",e),()=>{window.removeEventListener("scroll",e)}},[i]),n))}function tL(){let e=(0,u.Vi)(),{page:{lang:t}}=e,n=e?.siteData?.themeConfig??{},r=e.siteData.lang??"",i=n?.locales;return i&&0!==i.length?{...i.find(e=>e.lang===t),langRoutePrefix:t===r?"/":(0,x.mi)(t)}:{nav:n.nav,sidebar:n.sidebar,prevPageText:n.prevPageText,nextPageText:n.nextPageText,sourceCodeText:n.sourceCodeText,searchPlaceholderText:n.searchPlaceholderText,searchNoResultsText:n.searchNoResultsText,searchSuggestedQueryText:n.searchSuggestedQueryText,overview:n.overview}}function tM(){let{page:e,siteData:t}=(0,u.Vi)(),{frontmatter:n}=e,{themeConfig:r}=t,i=tL(),a=(0,u.TH)(),o=n?.overview??!1,s=()=>{let e="undefined"==typeof window||window.top===window.self;return(n?.outline??r?.outline??e)&&!o},[l,c]=function(){let{siteData:{themeConfig:e},page:{frontmatter:t={}}}=(0,u.Vi)(),n=(t?.navbar??!0)&&e?.hideNavbar!=="always",[r,i]=(0,p.useState)(n);return[r,i]}(),d=tq(),[h,x]=(0,p.useState)(s()),[m,f]=(0,p.useState)(n?.footer??!0),g=i.sidebar||{},v=n?.sidebar!==!1&&Object.keys(g).length>0,{width:y}=(0,u.iP)(),b=y<=960||y<=1280&&e.toc.length>0;(0,p.useEffect)(()=>{x(s())},[e,t]),(0,p.useEffect)(()=>{let e=new URLSearchParams(a.search),t=document.documentElement.style,n=t.getPropertyValue("--rp-sidebar-width"),r=t.getPropertyValue("--rp-aside-width"),i=e.get("navbar"),o=e.get("sidebar"),s=e.get("outline"),d=e.get("footer");return"0"===i&&c(!1),"0"===o&&document.documentElement.style.setProperty("--rp-sidebar-width","0px"),"0"===s&&document.documentElement.style.setProperty("--rp-aside-width","0px"),"0"===d&&f(!1),()=>{document.documentElement.style.setProperty("--rp-sidebar-width",n),document.documentElement.style.setProperty("--rp-aside-width",r),c(l),f(m)}},[a.search]);let w=d?0:y<=768?56:72,k=46*!!b;return{showAside:h,showNavbar:l,showSidebar:v,showSidebarMenu:b,showDocFooter:m,navbarHeight:w,sidebarMenuHeight:k,scrollPaddingTop:w+k}}function tz(e,t){let n=Number.parseInt(window.getComputedStyle(e).paddingTop,10);return Math.round(window.scrollY+e.getBoundingClientRect().top-t-n)}function tH(e,t,n){window.scrollTo({left:0,top:tz(e,n),...t?{behavior:"smooth"}:{}})}function t$(e){let{scrollPaddingTop:t}=tM();(0,p.useEffect)(()=>{let n=document.getElementById("aside-container"),r=Array.from(document.querySelectorAll(".rspress-doc .header-anchor")).filter(e=>e.parentElement?.tagName!=="H1");if(!n||!r.length||!e.length)return;let i=null,a=(e,t)=>{if(e[t]){let r=e[t].getAttribute("href"),a=n?.querySelector(`a[href="#${r?.slice(1)}"]`);a&&(i&&i.classList.remove("aside-active"),(i=a).classList.add("aside-active"))}},o=()=>{if(document.documentElement.scrollTop+window.innerHeight>=document.documentElement.scrollHeight)a(r,r.length-1);else for(let e=0;e=s&&o{i&&i.classList.remove("aside-active"),window.removeEventListener("scroll",s)}},[t,e.length])}function tW(){if((0,x._f)()){let{scrollPaddingTop:e}=tM();(0,p.useEffect)(()=>{window.addEventListener("click",t=>{let n=t.target.closest("a");if(!n)return;let{origin:r,hash:i,target:a,pathname:o,search:s}=n,l=window.location;i&&"_blank"!==a&&r===l.origin&&(o===l.pathname&&s===l.search&&i&&n.classList.contains("header-anchor")?(t.preventDefault(),history.pushState(null,"",i),function(e,t,n=!1,r){let i=null;try{i=e.classList.contains("header-anchor")?e:document.getElementById(decodeURIComponent(t.slice(1)))}catch(e){console.warn(e)}i&&tH(i,n,r)}(n,i,!0,e),window.dispatchEvent(new Event("hashchange"))):window.addEventListener("RspressReloadContent",()=>{location.hash.length>1&&tH(document.getElementById(location.hash.slice(1)),!1,e)}))},{capture:!0}),window.addEventListener("hashchange",e=>{e.preventDefault()})},[e])}}function tK(e){return e?"number"==typeof e?e:/<([a-z]+)([^<]*)(?:>(.*?)<\/\1>|\s*\/>)/i.test(e)?$(e):e.replace(/\\/g,">").replace(/</g,"<").replace(/>/g,">"):""}let tU=/`(.*?)`/g,tV=/\*{2}(?!\*)(.*?)\*{2}(?!\*)/g,tG=/\*(?!\*)(.*?)\*(?!\*)/g,tZ=/\~{2}(.*?)\~{2}/g;function tJ(e){return tK(e.replace(/`[^`]+`/g,e=>e.replace(/$1").replace(tG,"$1").replace(tZ,"$1").replace(tU,"$1"))}let tQ=({header:e,baseHeaderLevel:t})=>(0,c.jsx)("li",{children:(0,c.jsx)("a",{href:`#${e.id}`,title:e.text.replace(tV,"$1").replace(tG,"$1").replace(tZ,"$1").replace(tU,"$1"),className:"aside-link transition-all duration-300 hover:text-text-1 text-text-2 block",style:{marginLeft:(e.depth-t)*12,fontWeight:"semibold"},onClick:t=>{t.preventDefault(),window.location.hash=e.id},children:(0,c.jsx)("span",{className:"aside-link-text block",children:tJ(e.text)})})});function tY({headers:e,outlineTitle:t}){let{scrollPaddingTop:n}=tM(),r=e[0]?.depth||2,{hash:i="",pathname:a}=(0,u.TH)(),o=(0,p.useMemo)(()=>decodeURIComponent(i),[i]);return t$(e),(0,p.useEffect)(()=>{if(0===o.length)window.scrollTo(0,0);else{let e=document.getElementById(o.slice(1));e&&tH(e,!1,n)}},[o,e,a]),(0,c.jsx)("div",{className:"flex flex-col",children:(0,c.jsxs)("div",{id:"aside-container",className:"relative text-sm font-medium",children:[(0,c.jsx)("div",{className:"leading-7 block text-sm font-semibold pl-3",children:t}),(0,c.jsx)("nav",{className:"mt-1",children:(0,c.jsx)("ul",{className:"relative",children:e.map(e=>(0,c.jsx)(tQ,{baseHeaderLevel:r,header:e},`${a}#${e.id}`))})})]})})}let tX=(e,t)=>{let n=(0,u.pJ)(e);if(n===t)return!0;let r=(0,x.mi)(n);if(t.startsWith(r))return!0;let i=`${n}.`;return t.startsWith(i)};function t1(e,t){let n=(0,u.Tm)((0,u.pJ)(e)),r=(0,u.Tm)(t);return null!==(0,u.LX)(n,r)}let t0=(e,t)=>{for(let n of Object.keys(e).sort((e,t)=>t.length-e.length))if(tX(n,t))return e[n];return[]};function t2(){let{sidebar:e}=tL(),{pathname:t}=(0,u.TH)(),n=decodeURIComponent(t);return(0,p.useMemo)(()=>t0(e,n),[e,n])}function t3(){let{prevPage:e,nextPage:t}=function(){let{pathname:e}=(0,u.TH)(),t=t2(),n=[],r=e=>{"items"in e?(e.link&&n.push({text:e.text,link:e.link}),e.items.forEach(e=>{"dividerType"in e||r(e)})):n.push(e)};t.forEach(e=>!("dividerType"in e)&&r(e));let i=n.findIndex(t=>(0,u.pV)((0,u.pJ)(t.link),e));return{prevPage:n[i-1]||null,nextPage:n[i+1]||null}}(),{lastUpdated:n=!1}=tL(),{siteData:r}=(0,u.Vi)(),{themeConfig:i}=r,a=i.lastUpdated||n;return(0,c.jsxs)("footer",{className:"mt-8",children:[(0,c.jsx)("div",{className:"xs:flex pb-5 px-2 justify-end items-center",children:a&&(0,c.jsx)(rk,{})}),(0,c.jsx)("div",{className:"flex flex-col",children:(0,c.jsx)(rx,{})}),(0,c.jsxs)("div",{className:"flex flex-col sm:flex-row sm:justify-around gap-4 pt-6",children:[(0,c.jsx)("div",{className:"prev_c92d1 flex flex-col",children:e?(0,c.jsx)(r9,{type:"prev",text:e.text,href:(0,u.AP)(e.link)}):null}),(0,c.jsx)("div",{className:"next_c11be flex flex-col",children:t?(0,c.jsx)(r9,{type:"next",text:t.text,href:(0,u.AP)(t.link)}):null})]})]})}let t4={hidden:"hidden_f8586",container:"container_e4235",navContainer:"navContainer_d18b1",relative:"relative_bb7f1",sticky:"sticky_ddfa7",leftNav:"leftNav_e6722",rightNav:"rightNav_a2fea",singleItem:"singleItem_c1154",activeItem:"activeItem_a28b5",navBarTitle:"navBarTitle_c5f07",menuItem:"menu-item_b8238",mobileNavMenu:"mobileNavMenu_e7045"},t5=()=>{let{siteData:e}=(0,u.Vi)(),t=tL(),{logo:n,logoText:r}=e,i=t.title??e.title,a=(0,p.useMemo)(()=>n?"string"==typeof n?(0,c.jsx)("img",{src:(0,u.i6)(n),alt:"logo",id:"logo",className:"rspress-logo"}):(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)("img",{src:(0,u.i6)(n.light),alt:"logo",id:"logo",className:"rspress-logo dark:hidden"}),(0,c.jsx)("img",{src:(0,u.i6)(n.dark),alt:"logo",id:"logo",className:"rspress-logo hidden dark:block"})]}):null,[n]);return(0,c.jsx)("div",{className:`${t4.navBarTitle}`,children:(0,c.jsxs)(nm,{href:t.langRoutePrefix,className:"flex items-center w-full h-full text-base font-semibold transition-opacity duration-300 hover:opacity-60",children:[a&&(0,c.jsx)("div",{className:"mr-1 min-w-8",children:a}),r&&(0,c.jsx)("span",{children:r}),!a&&!r&&(0,c.jsx)("span",{children:i})]})})};function t6(e){let{depth:t,dividerType:n}=e;return(0,c.jsx)("div",{className:`${"dashed"===n?"border-dashed":"border-solid"} border-t border-divider-light my-3`,style:{marginLeft:0===t?0:"18px"}})}function t7({icon:e,...t}){return e?"string"==typeof e?(0,c.jsx)("img",{src:e,alt:"",...t}):(0,c.jsx)(e,{...t}):null}let t8={navTitleMask:"navTitleMask_fb17c",sidebar:"sidebar_dd719",sidebarContent:"sidebarContent_da296",open:"open_becbd",menuLink:"menuLink_bb039",menuItem:"menuItem_ac22e",collapseContainer:"collapseContainer_d6e4e",menuItemActive:"menuItemActive_de63c"},t9=e=>"dividerType"in e,ne=e=>!("items"in e)&&"link"in e,nt=e=>"sectionHeaderText"in e,nn=e=>"link"in e&&(0,x.xf)(e.link),nr=e=>{let t=(0,u.Ww)(e);t&&t.preload()},ni=()=>{let{pathname:e}=(0,u.TH)();return(0,p.useCallback)(t=>t1(t,decodeURIComponent(e)),[e])};function na(e){let{item:t,depth:n=0,activeMatcher:r,id:i,setSidebarData:a}=e,o=(0,u.s0)(),s=(0,p.useRef)(null),l=(0,p.useRef)(),d=(0,p.useRef)(null),h=(0,p.useRef)(!0),x=(0,p.useRef)("collapsed"in t&&t.collapsed),m=t.link&&r(t.link),{collapsed:f,collapsible:g=!0}=t,v=(0,c.jsx)("div",{style:{cursor:"pointer",transition:"transform 0.2s ease-out",transform:f?"rotate(0deg)":"rotate(90deg)"},children:(0,c.jsx)(t7,{icon:W})});(0,p.useEffect)(()=>{if(h.current||!s.current||!d.current)return;l.current&&clearTimeout(l.current);let e=s.current,t=d.current,n=t.clientHeight+4;f?(e.style.maxHeight=`${n}px`,e.style.transitionDuration="0.5s",t.style.opacity="0",l.current=window.setTimeout(()=>{s.current&&(s.current.style.maxHeight="0px")},0)):(e.style.maxHeight=`${n}px`,e.style.transitionDuration="0.3s",t.style.opacity="1",l.current=window.setTimeout(()=>{s.current&&s.current.style.removeProperty("max-height")},300))},[f]),(0,p.useEffect)(()=>{h.current=!1},[]);let y=e=>{e.stopPropagation(),a(e=>{let t=[...e],n=i.split("-").map(Number),r=t[n.shift()];for(let e of n)r=r.items[e];return"items"in r&&(r.collapsed=!r.collapsed),t})};return(0,c.jsxs)("section",{className:"rspress-sidebar-section mt-0.5 block","data-context":t.context,style:{marginLeft:0===n?0:"18px"},children:[(0,c.jsxs)("div",{className:`rspress-sidebar-collapse flex justify-between items-center ${m?t8.menuItemActive:t8.menuItem}`,"data-context":t.context,onMouseEnter:()=>t.link&&nr(t.link),onClick:e=>{t.link&&o((0,u.pJ)((0,u.AP)(t.link))),g&&y(e)},style:{borderRadius:0===n?"0 var(--rp-radius) var(--rp-radius) 0":void 0,cursor:g||t.link?"pointer":"normal"},children:[(0,c.jsxs)("h2",{className:"py-2 px-3 text-sm font-medium flex",style:{...0===n?nl:{}},children:[(0,c.jsx)(im,{tag:t.tag}),(0,c.jsx)("span",{className:"flex-center",style:{fontSize:0===n?"14px":"13px"},children:tJ(t.text)})]}),g&&(0,c.jsx)("div",{className:`${t8.collapseContainer} p-2 rounded-xl`,onClick:y,children:v})]}),(0,c.jsx)("div",{ref:s,className:"transition-all duration-300 ease-in-out",style:{overflow:"hidden",maxHeight:x.current?0:void 0},children:(0,c.jsx)("div",{ref:d,className:"rspress-sidebar-group transition-opacity duration-500 ease-in-out",style:{opacity:+!x.current,marginLeft:0===n?"12px":0},children:t?.items?.map((t,r)=>t9(t)?(0,c.jsx)(t6,{depth:n+1,dividerType:t.dividerType},r):(0,c.jsx)("div",{className:"rspress-sidebar-item","data-context":t.context,children:(0,c.jsx)(no,{...e,item:t,depth:n+1,id:`${i}-${r}`})},r))})})]},i)}function no(e){let{item:t,depth:n=0,activeMatcher:r,id:i,setSidebarData:a}=e,o="link"in t&&t.link&&r(t.link),s=(0,p.useRef)(null);return((0,p.useEffect)(()=>{o&&s.current?.scrollIntoView({block:"center"})},[]),"items"in t)?(0,c.jsx)(na,{id:i,activeMatcher:r,item:t,depth:n,collapsed:t.collapsed,setSidebarData:a},`${t.text}-${i}`):(0,c.jsx)(nm,{href:(0,u.AP)(t.link),className:t8.menuLink,children:(0,c.jsxs)("div",{ref:s,className:`${o?t8.menuItemActive:t8.menuItem} mt-0.5 py-2 px-3 font-medium flex`,style:{fontSize:0===n?"14px":"13px",marginLeft:0===n?0:"18px",borderRadius:"0 var(--rp-radius) var(--rp-radius) 0",...0===n?nl:{}},children:[(0,c.jsx)(im,{tag:t.tag}),(0,c.jsx)("span",{children:tJ(t.text)})]})})}function ns({sectionHeaderText:e,tag:t}){return(0,c.jsxs)("div",{className:"rspress-sidebar-section-header",children:[(0,c.jsx)(im,{tag:t}),(0,c.jsx)("span",{children:tJ(e)})]})}let nl={fontSize:"14px",paddingLeft:"24px",fontWeight:"bold"},nc=new WeakMap;function nd(e){let{isSidebarOpen:t,beforeSidebar:n,afterSidebar:i,uiSwitch:a,navTitle:o}=e,{pathname:s}=(0,u.TH)(),l=t2(),[d,h]=(0,p.useState)(()=>l.filter(Boolean).flat()),m=decodeURIComponent(s),f=ni();return(0,p.useEffect)(()=>((0,x._f)()&&(t?(r=document.body.style.overflow,document.body.style.overflow="hidden"):document.body.style.overflow=r||""),()=>{(0,x._f)()&&(document.body.style.overflow=r||"")}),[t]),(0,p.useEffect)(()=>{if(l===d)return;nc=new WeakMap;let e=t=>nc.has(t)?nc.get(t):"link"in t&&t.link&&f(t.link)||"items"in t&&t.items.some(t=>e(t))?(nc.set(t,!0),!0):(nc.set(t,!1),!1),t=n=>{"items"in n&&(n.items.forEach(t),e(n)&&(n.collapsed=!1))},n=l.filter(Boolean).flat();n.forEach(t),h(n)},[l,m]),(0,c.jsxs)("aside",{className:`${t8.sidebar} rspress-sidebar ${t?t8.open:""}`,children:[a?.showNavbar?(0,c.jsx)("div",{className:t8.navTitleMask,children:o||(0,c.jsx)(t5,{})}):null,(0,c.jsx)("div",{className:`rspress-scrollbar ${t8.sidebarContent}`,children:(0,c.jsxs)("nav",{className:"pb-2",children:[n,(0,c.jsx)(nu,{sidebarData:d,setSidebarData:h}),i]})})]})}function nu({sidebarData:e,setSidebarData:t}){let n=ni();return(0,c.jsx)(c.Fragment,{children:e.map((e,r)=>(0,c.jsx)(nh,{item:e,index:r,setSidebarData:t,activeMatcher:n},r))})}function nh(e){let{item:t,index:n,setSidebarData:r,activeMatcher:i}=e;return t9(t)?(0,c.jsx)(t6,{depth:0,dividerType:t.dividerType},n):nt(t)?(0,c.jsx)(ns,{sectionHeaderText:t.sectionHeaderText,tag:t.tag},n):nn(t)?(0,c.jsx)("div",{className:"rspress-sidebar-item rspress-sidebar-custom-link","data-context":t.context,children:(0,c.jsx)(no,{id:String(n),item:t,depth:0,collapsed:t.collapsed??!0,setSidebarData:r,activeMatcher:i},n)},n):(0,c.jsx)(no,{id:String(n),item:t,depth:0,activeMatcher:i,collapsed:t.collapsed??!0,setSidebarData:r},n)}let np={link:"link_a7cea"},nx=(e,t)=>{let{hash:n}=window.location,r=decodeURIComponent(n),i=r.length>1&&document.getElementById(r.slice(1));r&&i&&tH(i,e,t)};function nm(e){let{href:t="/",children:n,className:r="",onNavigate:i,onClick:a}=e,o=(0,u.s0)(),{pathname:s}=(0,u.TH)(),{scrollPaddingTop:l}=tM(),d=(0,p.useMemo)(()=>(0,u.pJ)((0,u.AP)(t)),[t]),h=(0,x.xf)(t),m=t.startsWith("#");if(h)return(0,c.jsx)("a",{...e,href:t,target:"_blank",rel:"noopener noreferrer",className:`${np.link} ${r}`,children:n});if(m)return(0,c.jsx)("a",{...e,href:t,className:`${np.link} ${r}`,children:n});let f=async e=>{if(0===e.button&&(!e.currentTarget.target||"_self"===e.currentTarget.target)&&!e.metaKey&&!e.shiftKey&&!e.altKey&&!e.ctrlKey){if(e.preventDefault(),!t1(d,s)){let e=(0,u.Ww)(d);if(e){let t=setTimeout(()=>{U.start()},200);await e.preload(),clearTimeout(t),U.done()}}i?.(),o(d,{replace:!1}),setTimeout(()=>{nx(!1,l)},100)}};return(0,c.jsx)("a",{...e,href:d,className:`${np.link} ${r}`,onMouseEnter:()=>nr(d),onClick:e=>{a?.(e),f(e)},children:n})}U.configure({showSpinner:!1});let nf=({header:e,onItemClick:t})=>(0,c.jsx)("li",{children:(0,c.jsx)(nm,{href:`#${e.id}`,className:"rspress-toc-link sm:text-normal text-sm",style:{marginLeft:(e.depth-2)*12},onClick:()=>{t?.(e)},children:(0,c.jsx)("span",{className:"rspress-toc-link-text block",children:tJ(e.text)})})});function ng({onItemClick:e}){let{page:t}=(0,u.Vi)();return t.toc.length>0&&(0,c.jsx)("ul",{children:t.toc.map(t=>(0,c.jsx)(nf,{header:t,onItemClick:e},t.id))})}function nv({isSidebarOpen:e,onIsSidebarOpenChange:t,outlineTitle:n,uiSwitch:r}){let{page:i}=(0,u.Vi)(),a=(0,p.useRef)(null),o=(0,p.useRef)(null),[s,l]=(0,p.useState)(!1),{pathname:d}=(0,u.TH)();(0,p.useEffect)(()=>{t(!1)},[d]),(0,p.useEffect)(()=>(document.addEventListener("mouseup",h),document.addEventListener("touchend",h),()=>{document.addEventListener("mouseup",h),document.removeEventListener("touchend",h)}),[]);let h=(0,p.useCallback)(e=>{let{current:t}=o;if(t?.contains(e.target))return;let{current:n}=a;n&&!n.contains(e.target)&&l(!1)},[]),x=(0,p.useCallback)(()=>{l(!1)},[]),m=i.toc.length>0;return(0,c.jsx)("div",{className:`rspress-sidebar-menu-container ${m?"":"no-toc"}`,children:(0,c.jsxs)("div",{className:"rspress-sidebar-menu",children:[r?.showSidebar&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)("button",{type:"button",onClick:function(){t(!0)},className:"flex-center mr-auto",children:[(0,c.jsx)("div",{className:"text-md mr-2",children:(0,c.jsx)(t7,{icon:K})}),(0,c.jsx)("span",{className:"text-sm",children:"Menu"})]}),e&&(0,c.jsx)("div",{onClick:function(){t(!1)},className:"rspress-sidebar-back-drop",style:{background:"rgba(0, 0, 0, 0.6)"}})]}),r?.showAside&&m&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)("button",{type:"button",onClick:()=>l(e=>!e),className:"flex-center ml-auto",ref:o,children:[(0,c.jsx)("span",{className:"text-sm",children:n}),(0,c.jsx)("div",{className:"text-md mr-2",style:{transform:s?"rotate(90deg)":"rotate(0deg)",transition:"transform 0.2s ease-out",marginTop:"2px"},children:(0,c.jsx)(t7,{icon:W})})]}),(0,c.jsx)("div",{className:`rspress-local-toc-container ${s?"rspress-local-toc-container-show":""}`,children:(0,c.jsx)(ng,{onItemClick:x})})]})]})})}let ny=(0,p.createContext)({tabData:{},setTabData:()=>{}}),nb="title_fb7eb",nw=e=>{let{href:t="",className:n=""}=e,{normalizeLinkHref:r}=function(){let e=(0,u.Jr)(),t=(0,u.aw)(),n=(0,u.Vi)(),r=n.siteData.lang,i=n.siteData.multiVersion.default;return{normalizeLinkHref:n=>{let a=n;if((r||i)&&!(0,x.xf)(a)&&!a.startsWith("#")){let n=(a=(0,u.E9)(a)).split("/").filter(Boolean),o="",s="",l="";return i&&(t!==i?(o=t,n[0]===t&&n.shift()):n[0]===i&&n.shift()),r&&(e!==r?(s=e,n[0]===e&&n.shift()):n[0]===r&&n.shift()),l=n.join("/"),(0,u.AP)((0,u.pJ)([o,s,l].filter(Boolean).join("/")))}return a}}}();return(0,c.jsx)(nm,{...e,className:`${n} link_a9ef4 inline-link_f855c`,href:r(t)})},nk=e=>(0,c.jsx)("h1",{...e,className:`rspress-doc-title text-3xl mb-10 leading-10 tracking-tight ${nb}`}),nI=e=>(0,c.jsx)("h2",{...e,className:`mt-12 mb-6 pt-8 text-2xl tracking-tight border-t-[1px] border-divider-light ${nb}`}),nD=e=>(0,c.jsx)("h3",{...e,className:`mt-10 mb-2 leading-7 text-xl ${nb}`}),nE=e=>(0,c.jsx)("h4",{...e,className:`mt-8 leading-6 text-lg ${nb}`}),nF=e=>(0,c.jsx)("h5",{...e,className:nb}),nA=e=>(0,c.jsx)("h6",{...e,className:nb}),nC={asideContainer:"aside-container_bc5fa",content:"content_ff766",docLayout:"docLayout_af141"};function nj(e){let{beforeDocFooter:t,afterDocFooter:n,beforeDoc:r,afterDoc:i,beforeDocContent:a,afterDocContent:o,beforeOutline:s,afterOutline:l,beforeSidebar:x,afterSidebar:m,uiSwitch:f,navTitle:g,components:v}=e,{siteData:y,page:b}=(0,u.Vi)(),{headingTitle:w,title:k,toc:I=[],frontmatter:D}=b,[E,F]=(0,p.useState)({}),{themeConfig:A}=y,C=A.enableScrollToTop??!1,j=tL(),P=j?.outlineTitle||A?.outlineTitle||"ON THIS PAGE",S=D?.overview??!1,T={...nY(),...v},N=(0,c.jsx)(ny.Provider,{value:{tabData:E,setTabData:F},children:(0,c.jsx)(d.Zo,{components:T,children:(0,c.jsx)(u.VY,{})})}),_=(0,p.useMemo)(()=>{var e;let t=k&&("string"!=typeof(e=k)?"":(e=e.toLowerCase()).replace(h,"").replace(/ /g,"-"));return!1!==y.themeConfig.fallbackHeadingTitle&&!w&&t&&(0,c.jsxs)(nk,{id:t,children:[k,(0,c.jsx)(nw,{className:"header-anchor",href:`#${t}`,"aria-hidden":!0,children:"#"})]})},[w,k,y.themeConfig.fallbackHeadingTitle]),[B,O]=(0,p.useState)(!1);return(0,c.jsxs)("div",{className:`${nC.docLayout} pt-0`,style:{...f?.showNavbar?{}:{marginTop:0}},children:[r,f?.showSidebar&&(0,c.jsx)(nd,{isSidebarOpen:B,beforeSidebar:x,afterSidebar:m,uiSwitch:f,navTitle:g}),(0,c.jsxs)("div",{className:"flex-1 relative min-w-0",children:[(0,c.jsx)(nv,{isSidebarOpen:B,onIsSidebarOpenChange:O,outlineTitle:P,uiSwitch:f}),(0,c.jsxs)("div",{className:`${nC.content} rspress-doc-container flex`,children:[(0,c.jsx)("div",{className:`flex-1 ${S?"":"overflow-x-auto"}`,children:S?(0,c.jsxs)(c.Fragment,{children:[a,(0,c.jsx)(r0,{content:N}),o]}):(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)("div",{className:"rspress-doc",children:[a,_,N,o]}),(0,c.jsxs)("div",{className:"rspress-doc-footer",children:[t,f?.showDocFooter&&(0,c.jsx)(t3,{}),n]})]})}),C&&(0,c.jsx)(u.ri,{children:(0,c.jsx)(it,{})}),f?.showAside&&I.length>0&&(0,c.jsxs)("div",{className:nC.asideContainer,style:f?.showNavbar?void 0:{marginTop:0,paddingTop:"32px"},children:[s,(0,c.jsx)(tY,{headers:I,outlineTitle:P}),l]})]})]}),i]})}let nP=(e,t)=>t?(e=e.trim(),(t=t.trim()).startsWith("-")||t.startsWith("|"))?`${e} ${t}`:`${e} - ${t}`:e;function nS(){let{siteData:e,page:t}=(0,u.Vi)(),n=e.lang,r=e.multiVersion.default;if(n&&"undefined"!=typeof window&&location.pathname.includes(`/${n}/`)){let e=location.pathname.replace(`/${n}/`,"/");return window.location.replace(e),(0,c.jsx)(c.Fragment,{})}let i="/";return r&&t.version!==r&&(i+=`${t.version}/`),n&&t.lang!==n&&(i+=`${t.lang}/`),(0,c.jsxs)("div",{className:"m-auto mt-50 p-16 sm:p-8 sm:pt-24 sm:pb-40 text-center flex-center flex-col",children:[(0,c.jsx)("p",{className:"text-6xl font-semibold",children:"404"}),(0,c.jsx)("h1",{className:"leading-5 pt-3 text-xl font-bold",children:"PAGE NOT FOUND"}),(0,c.jsx)("div",{style:{height:"1px"},className:"mt-6 mx-auto mb-4.5 w-16 bg-gray-light-1"}),(0,c.jsx)("div",{className:"pt-5",children:(0,c.jsx)("a",{className:"py-2 px-4 rounded-2xl inline-block border-solid border-brand text-brand font-medium hover:border-brand-dark hover:text-brand-dark transition-colors duration-300",href:(0,u.pJ)(i),"aria-label":"go to home",children:"Take me home"})})]})}let nT={"code-button-group":"code-button-group_fb445",codeButtonGroup:"code-button-group_fb445","code-copy-button":"code-copy-button_c5089",codeCopyButton:"code-copy-button_c5089","icon-success":"icon-success_d5ec0",iconSuccess:"icon-success_d5ec0","code-copied":"code-copied_e2224",codeCopied:"code-copied_e2224","icon-copy":"icon-copy_ef942",iconCopy:"icon-copy_ef942","icon-wrapped":"icon-wrapped_fb89b",iconWrapped:"icon-wrapped_fb89b","wrapped-btn":"wrapped-btn_a2562",wrappedBtn:"wrapped-btn_a2562","icon-wrap":"icon-wrap_ccd3d",iconWrap:"icon-wrap_ccd3d"},nN=new Map;function n_({codeBlockRef:e}){let t=(0,p.useRef)(null);return(0,c.jsxs)("button",{className:nT.codeCopyButton,onClick:()=>(function(e,t){let n="";if(!e)return;let r=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,null),i=r.nextNode();for(;i;)i.parentElement.classList.contains("linenumber")||(n+=i.nodeValue),i=r.nextNode();if(Y(n)&&t){t.classList.add(nT.codeCopied),clearTimeout(nN.get(t));let e=setTimeout(()=>{t.classList.remove(nT.codeCopied),t.blur(),nN.delete(t)},2e3);nN.set(t,e)}})(e.current,t.current),ref:t,title:"Copy code",children:[(0,c.jsx)(t7,{icon:J,className:nT.iconCopy}),(0,c.jsx)(t7,{icon:Q,className:nT.iconSuccess})]})}let nB={doctype:{color:"var(--code-token-text)",fontStyle:"italic"},token:{color:"var(--code-token-text)"},comment:{color:"var(--code-token-comment)"},punctuation:{color:"var(--code-token-punctuation)"},property:{color:"var(--code-token-parameter)"},constant:{color:"var(--code-token-constant)"},string:{color:"var(--code-token-string)"},symbol:{color:"var(--code-token-symbol)"},variable:{color:"var(--code-token-variable)"},"attr-name":{color:"var(--code-token-symbol)"},"attr-value":{color:"var(--code-token-string-expression)"},builtin:{color:"var(--code-token-symbol)"},function:{color:"var(--code-token-function)"},keyword:{color:"var(--code-token-keyword)"},tag:{color:"var(--code-token-function)"},inserted:{color:"var(--code-token-inserted)"},deleted:{color:"var(--code-token-deleted)"},regex:{color:"var(--code-token-keyword)"},key:{color:"var(--code-token-variable)"},title:{color:"var(--code-token-keyword)"},important:{color:"#EBCB8B",fontWeight:"bold"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"},table:{display:"content"}},nO=!1;function nR(e){let{siteData:t}=(0,u.Vi)(),{meta:n,language:r,codeWrap:i}=e,{showLineNumbers:a}=t.markdown,o="",s=[];return n&&(o=/{[\d,-]*}/i.exec(n)?.[0]||"")&&(s=o.replace(/[{}]/g,"").split(",").map(e=>{let[t,n]=e.split("-");return n?Array.from({length:Number(n)-Number(t)+1},(e,n)=>n+Number(t)):Number(t)}).flat()),nO||(Object.keys(ew).forEach(e=>{ey.registerLanguage(e,ew[e])}),ey.alias(eb),nO=!0),(0,c.jsx)(ey,{language:r,style:nB,wrapLines:!0,className:"code",wrapLongLines:i,customStyle:{backgroundColor:"inherit"},showLineNumbers:a||s.length>0,lineProps:e=>({style:{...s.includes(e)?{backgroundColor:"var(--rp-code-line-highlight-color)"}:{},display:"block",padding:"0 1.25rem"}}),children:String(e.children).trim()})}function nq(e){let{siteData:t}=(0,u.Vi)(),n=e.codeHighlighter??t.markdown.codeHighlighter,{defaultWrapCode:r}=t.markdown,[i,a]=(0,p.useState)(r),o=(0,p.useRef)(null),s=(0,p.useRef)(null),{className:l}=e,d=l?.replace(/language-/,"");if(!d)return(0,c.jsx)("code",{...e});let h=e=>{i?e?.classList.remove(nT.wrappedBtn):e?.classList.add(nT.wrappedBtn),a(!i)};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)("div",{ref:s,children:"prism"===n?(0,c.jsx)(nR,{...e,language:d,codeWrap:i}):(0,c.jsx)("pre",{...e,style:{overflowX:"auto"},children:(0,c.jsx)("code",{style:{whiteSpace:i?"pre-wrap":"pre"},children:e.children})})}),(0,c.jsxs)("div",{className:nT.codeButtonGroup,children:[(0,c.jsxs)("button",{ref:o,className:nT.codeWrapButton,onClick:()=>h(o.current),title:"Toggle code wrap",children:[(0,c.jsx)(t7,{icon:Z,className:nT.iconWrapped}),(0,c.jsx)(t7,{icon:G,className:nT.iconWrap})]}),(0,c.jsx)(n_,{codeBlockRef:s})]})]})}let nL=e=>(0,c.jsx)("hr",{...e,className:"my-12 border-t border-solid border-divider-light"}),nM=e=>(0,c.jsx)("img",{...e,src:(0,u.i6)(e.src||"")}),nz=e=>(0,c.jsx)("ol",{...e,className:"list-decimal pl-5 my-4 leading-7"}),nH=e=>(0,c.jsx)("ul",{...e,className:"list-disc pl-5 my-4 leading-7"}),n$=e=>(0,c.jsx)("li",{...e,className:"[&:not(:first-child)]:mt-2"}),nW=e=>(0,c.jsx)("p",{...e,className:"my-4 leading-7"}),nK=e=>(0,c.jsx)("blockquote",{...e,className:"border-l-2 border-solid border-divider pl-4 my-6 transition-colors duration-500 blockquote_f1063"}),nU=e=>(0,c.jsx)("strong",{...e,className:"font-semibold"});function nV({children:e}){let t=e=>{let{className:t,meta:n}=e.props,r=function(e){if(!e)return"";let t=e,n=/{[\d,-]*}/i;return n.exec(e)?.[0]&&(t=e.replace(n,"").trim()),t=t.split("=")[1]??"",t?.replace(/["'`]/g,"")}(n);return(0,c.jsxs)("div",{className:t||"language-bash",children:[r&&(0,c.jsx)("div",{className:"rspress-code-title",children:r}),(0,c.jsx)("div",{className:"rspress-code-content rspress-scrollbar",children:e})]})};return Array.isArray(e)?(0,c.jsx)("div",{children:e.map(e=>t(e))}):t(e)}let nG=e=>(0,c.jsx)("table",{...e,className:"block border-collapse text-base my-5 overflow-x-auto leading-7 border-gray-light-3 dark:border-divider"}),nZ=e=>(0,c.jsx)("tr",{...e,className:"border border-solid transition-colors duration-500 even:bg-soft border-gray-light-3 dark:border-divider"}),nJ=e=>(0,c.jsx)("td",{...e,className:"border border-solid px-4 py-2 border-gray-light-3 dark:border-divider"}),nQ=e=>(0,c.jsx)("th",{...e,className:"border border-solid px-4 py-2 text-text-1 text-base font-semibold border-gray-light-3 dark:border-divider"});function nY(){return{h1:nk,h2:nI,h3:nD,h4:nE,h5:nF,h6:nA,ul:nH,ol:nz,li:n$,table:nG,td:nJ,th:nQ,tr:nZ,hr:nL,p:nW,blockquote:nK,strong:nU,a:nw,code:nq,pre:nV,img:nM}}let nX="default",n1=/[\u3131-\u314e|\u314f-\u3163|\uac00-\ud7a3]/u,n0=/[\u0400-\u04FF]/u;function n2(e){let t=e.toString().toLowerCase().normalize("NFD");if(n0.test(String(e)))return t.normalize("NFC");let n=t.replace(/[\u0300-\u036f]/g,"");return n1.test(String(e))?n.normalize("NFC"):n}function n3(e){return e.replace(/https?:\/\/[^/]+/,"")}function n4(e){return e.charCodeAt(0)>255?3:1}let n5=e=>e.map(e=>"string"==typeof e?{value:e,label:e}:e);function n6(e,t){let n=0,r=0;for(let i=0;i=t);i++)r+=n4(e.charAt(i)),n++;return n}function n7(e){let t=0;for(let n=0;n{console.error("Failed to fetch search index, please reload the page and try again."),console.error(e)};try{let e=await fetch(o);if(e.ok)return e.json();s(e)}catch(e){s(e)}return[]}async fetchSearchIndex(e){if(this.#r)return this.#r;let{currentLang:t,currentVersion:n}=e,r="remote"!==e.mode&&e.versioned;return this.#r=this.#i(t,r?n:""),this.#r}async init(e){let t=(await this.fetchSearchIndex(e)).map(e=>({...e,normalizedContent:n2(e.content),headers:e.toc.map(e=>n2(e.text)).join(" "),normalizedTitle:n2(e.title)})),n={tokenize:"full",document:{id:"id",store:!0,index:["normalizedTitle","headers","normalizedContent"]},cache:100};for(let e of(this.#e=new e3(n),this.#t=new e3({...n,tokenize:e=>re(e,n8)}),this.#n=new e3({...n,tokenize:e=>re(e,n9)}),t))this.#e.addAsync(e.id,e),this.#t.addAsync(e.id,e),this.#n.addAsync(e.id,e)}async search(e){let{keyword:t,limit:n}=e,r={enrich:!0,limit:n,index:["normalizedTitle","headers","normalizedContent"]},i=await Promise.all([this.#e?.searchAsync(t,r),this.#t?.searchAsync(t,r),this.#n?.searchAsync(t,r)]),a=[],o=new Set;return i.forEach(e=>{e&&function(e){for(let t of e)t.result.forEach(e=>{let t=e.id;o.has(t)||(o.add(t),a.push(e.doc))})}(e)}),[{index:nX,hits:a}]}}class rn{#a;async init(e){this.#a=e}async fetchSearchIndex(e){return[]}async search(e){let{apiUrl:t,searchIndexes:n}=this.#a,{keyword:r,limit:i}=e,a=Object.entries({keyword:r,limit:i.toString(),searchIndexes:n?.map(e=>"string"==typeof e?e:e.value).join(",")||"",lang:this.#a?.currentLang??""}).map(e=>e.map(encodeURIComponent).join("=")).join("&");try{return(await fetch(`${t}?${a}`)).json()}catch(e){return console.error(e),[]}}}var rr=((o={}).Default="default",o.Custom="custom",o);class ri{#a;#o=nX;#s;constructor(e){this.#a=e,this.#o=e.indexName??nX,"remote"===e.mode?this.#s=new rn:this.#s=new rt}async init(){await this.#s?.init(this.#a)}async fetchSearchIndex(){return this.#s?.fetchSearchIndex(this.#a)}async match(e,t=7){let n=await this.#s?.search({keyword:e,limit:t}),r=n2(e),i=n?.find(e=>this.#l(e.index))||{index:nX,renderType:rr.Default,hits:[]};return[{group:this.#o,renderType:rr.Default,result:this.#c(r,i)},...(n?.filter(e=>!this.#l(e.index))||[]).map(e=>({group:e.index,renderType:rr.Default,result:this.#c(r,e)}))]}#c(e,t){let n=[];return t?.hits.forEach(t=>{this.#d(t,e,n);let r=this.#u(t,e,n);this.#h(t,e,n,r)}),n}#d(e,t,n){let{title:r=""}=e,i=n2(r);return!!i.includes(t)&&(n.push({type:"title",title:r,header:r,link:`${e.domain}${(0,u.AP)(e.routePath)}`,query:t,highlightInfoList:[{start:i.indexOf(t),length:n7(t)}]}),!0)}#u(e,t,n){let r=new WeakSet,{toc:i=[],domain:a="",title:o=""}=e;for(let[s,l]of i.entries())if(n2(l.text).includes(t)){let c=(function(e,t){let n=e[t],r=t,i=[n];for(;n&&n.depth>2;){let t=!1;for(let a=r-1;a>=0;a--){let o=e[a];if(o.depth>1&&o.depth===n.depth-1){n=o,r=a,i.unshift(n),t=!0;break}}if(!t)break}return i})(i,s).map(e=>e.text).join(" > "),d=n2(c).indexOf(t),h=`${o} > `;n.push({type:"header",title:e.title,header:`${h}${c}`,highlightInfoList:[{start:d+h.length,length:n7(t)}],link:`${a}${(0,u.AP)(e.routePath)}#${l.id}`,query:t}),r.add(l)}return r}#h(e,t,n,r){let{content:i,toc:a,domain:o}=e;if(!i.length)return;let s=n2(i),l=s.indexOf(t),c=a.map(e=>e.charIndex),d=e=>a[c.findIndex((t,n)=>{if(!(n=e)return!0}return!1})],h=e=>e&&r?.has(e);if(-1===l){let r=e._matchesPosition?.content;if(!r?.length)return;let a=e._matchesPosition.content[0].start,s=d(a);if(h(s))return;let l=n6(i,a),c=n6(i,a+100),p=i.slice(l,c),x=e._matchesPosition.content.filter(e=>e.start>=a&&e.start+e.length<=a+100).map(e=>({start:n6(i,e.start)-l+3,length:e.length}));n.push({type:"content",title:e.title,header:s?.text??e.title,link:`${o}${(0,u.AP)(e.routePath)}${s?`#${s.id}`:""}`,query:t,highlightInfoList:x,statement:`...${p}...`});return}for(;-1!==l;){let a=d(l),c=i.slice(0,l).lastIndexOf("\n");c=-1===c?0:c;let p=i.indexOf("\n\n",l+t.length),x=i.slice(c,p);x.length>100&&(x=this.#p(x,t));let m=n2(x).indexOf(t),f=[{start:m,length:n7(t)}];!h(a)&&(n.push({type:"content",title:e.title,header:a?.text??e.title,statement:x,highlightInfoList:f,link:`${o}${(0,u.AP)(e.routePath)}${a?`#${a.id}`:""}`,query:t}),a&&r?.add(a)),l=s.indexOf(t,l+x.length-m)}}#p(e,t){let n=n2(e).indexOf(n2(t)),r=Math.floor((100-t.length)/2),i=e.slice(0,n);i.length>r&&(i=`...${e.slice(n-r+3,n)}`);let a=e.slice(n+t.length);return a.length>r&&(a=`${e.slice(n+t.length,n+r-3)}...`),i+t+a}#l(e){return e===this.#o||e===nX}}let ra=e=>{let t=(0,p.useRef)(e);return t.current=e,(0,p.useRef)((...e)=>t.current(...e)).current},ro=e=>{let[t,n]=(0,p.useState)(()=>"undefined"!=typeof window&&window.matchMedia(e).matches);return(0,p.useEffect)(()=>{let t=window.matchMedia(e),r=e=>n(e.matches);return t.addEventListener("change",r),()=>t.removeEventListener("change",r)},[e]),t},rs=(e,t)=>{let[n,r]=(0,p.useState)(()=>"undefined"==typeof window?t:localStorage.getItem(e)??t),i=(0,p.useCallback)(t=>{r(n=>{let r="function"==typeof t?t(n):t;return null==r?localStorage.removeItem(e):localStorage.setItem(e,r),r})},[e]);return(0,p.useEffect)(()=>{let n=n=>{n.key===e&&r(localStorage.getItem(e)??t)};return window.addEventListener("storage",n),()=>{window.removeEventListener("storage",n)}},[e,t]),[n,i]},rl=e=>["light","dark","auto"].includes(e)?e:"auto",rc=!1===ts.Z.themeConfig.darkMode,rd=()=>{let e=ro("(prefers-color-scheme: dark)"),[t,n]=rs(x.rp,"auto"),r=ra(()=>{if(rc)return"light";let n=rl(t);return"auto"===n?e?"dark":"light":n}),[i,a]=(0,p.useState)(()=>{if("undefined"==typeof window)return"light";let e=window.RSPRESS_THEME??window.MODERN_THEME;return e?"dark"===e?"dark":"light":r()}),o=(0,p.useCallback)((e,t=e)=>{rc||(a(e),n(t),l(!0))},[]);(0,p.useEffect)(()=>{document.documentElement.classList.toggle("dark","dark"===i),document.documentElement.style.colorScheme=i},[i]);let[s,l]=(0,p.useState)(!0);return(0,p.useEffect)(()=>{l(!1)},[s]),(0,p.useEffect)(()=>{s||o(r(),rl(t))},[t]),(0,p.useEffect)(()=>{s||o(e?"dark":"light","auto")},[e]),[i,o]},ru={button:"button_e8e0d",medium:"medium_fe00b",big:"big_f7033",brand:"brand_dc619",alt:"alt_b0249"};function rh(e){let{theme:t="brand",size:n="big",href:r="/",external:i=!1,className:a=""}=e,o=null;return"button"===e.type?o="button":"a"===e.type&&(o=i?"a":nm),p.createElement(o??"a",{className:`${ru.button} ${ru[t]} ${ru[n]} ${a}`,href:r},e.text)}let rp={editLink:"editLink_e1cfa"};function rx(){let e=function(){let{siteData:e,page:t}=(0,u.Vi)(),n=tL().editLink??e.themeConfig?.editLink??{};if(!n.docRepoBaseUrl||!n.text)return null;let{docRepoBaseUrl:r}=n;r.endsWith("/")||(r+="/");let i=t._relativePath.replace(/\\/g,"/"),a=`${r}${i}`;return{text:n.text,link:a}}();if(!e)return null;let{text:t,link:n}=e;return(0,c.jsx)("a",{href:n,target:"_blank",className:rp.editLink,children:t})}let rm={"grid-2":"grid-2_bce10",grid2:"grid-2_bce10","grid-4":"grid-4_bd059",grid4:"grid-4_bd059","grid-6":"grid-6_ce438",grid6:"grid-6_ce438","grid-3":"grid-3_bf296",grid3:"grid-3_bf296",featureCard:"featureCard_a17b6"},rf=e=>{let{span:t}=e;return`grid-${t||4}`};function rg({frontmatter:e,routePath:t}){let n=e?.features;return(0,c.jsx)("div",{className:"overflow-hidden m-auto flex flex-wrap max-w-6xl",children:n?.map(e=>{let{icon:n,title:r,details:i,link:a}=e,o=a;return a&&(o=(0,x.xf)(a)?a:(0,u.AP)((0,x.pJ)(a,t))),(0,c.jsx)("div",{className:`${rm[rf(e)]} rounded hover:var(--rp-c-brand)`,children:(0,c.jsx)("div",{className:"h-full p-2",children:(0,c.jsxs)("article",{className:`rspress-home-feature-card ${rm.featureCard} h-full p-8 rounded-4xl border-transparent`,style:{cursor:o?"pointer":"auto"},onClick:()=>{o&&(window.location.href=o)},children:[n?(0,c.jsx)("div",{className:"flex-center",children:(0,c.jsx)("div",{className:"rspress-home-feature-icon w-12 h-12 text-3xl text-center",children:tK(n)})}):null,(0,c.jsx)("h2",{className:"rspress-home-feature-title font-bold text-center",children:r}),(0,c.jsx)("p",{className:"rspress-home-feature-detail leading-6 pt-2 text-sm text-text-2 font-medium",children:tK(i)})]},r)})},r)})})}function rv(){let{siteData:e}=(0,u.Vi)(),{message:t}=e.themeConfig.footer||{};return t?(0,c.jsx)("footer",{className:"absolute bottom-0 mt-12 py-8 px-6 sm:p-8 w-full border-t border-solid border-divider-light",children:(0,c.jsx)("div",{className:"m-auto w-full text-center",children:(0,c.jsx)("div",{className:"font-medium text-sm text-text-2",dangerouslySetInnerHTML:{__html:t}})})}):null}let ry={name:"modern",text:"modern ssg",tagline:"modern ssg",actions:[],image:void 0};function rb({frontmatter:e,routePath:t}){let n=e?.hero||ry,r=void 0!==n.image,i=r?"sm:max-w-xl":"sm:max-w-4xl",a=n.text?n.text.toString().split(/\n/g).filter(e=>""!==e):[],o="string"==typeof n.image?.src?{light:n.image.src,dark:n.image.src}:n.image?.src||{light:"",dark:""};return(0,c.jsxs)("div",{className:"m-auto pt-0 px-6 pb-12 sm:pt-10 sm:px-16 md:pt-16 md:px-16 md:pb-16 relative",children:[(0,c.jsx)("div",{className:"mask_bbaa6",style:{left:r?"75%":"50%"}}),(0,c.jsxs)("div",{className:"m-auto flex flex-col md:flex-row max-w-6xl min-h-[50vh] mt-12 sm:mt-0",children:[(0,c.jsxs)("div",{className:"flex flex-col justify-center items-center text-center max-w-xl sm:max-w-4xl m-auto order-2 md:order-1",children:[(0,c.jsx)("h1",{className:"font-bold text-3xl pb-2 sm:text-6xl md:text-7xl m-auto sm:m-4 md:m-0 md:pb-3 lg:pb-2 leading-tight z-10",children:(0,c.jsx)("span",{className:"clip_aacad",style:{lineHeight:"1.3"},children:tK(n.name)})}),0!==a.length&&a.map(e=>(0,c.jsx)("p",{className:`rspress-home-hero-text mx-auto md:m-0 text-3xl sm:text-5xl md:text-6xl sm:pb-2 font-bold z-10 ${i}`,style:{lineHeight:"1.2"},children:tK(e)},e)),(0,c.jsx)("p",{className:`rspress-home-hero-tagline whitespace-pre-wrap pt-4 m-auto md:m-0 text-sm sm:tex-xl md:text-[1.5rem] text-text-2 font-medium z-10 ${i}`,children:tK(n.tagline)}),n.actions?.length&&(0,c.jsx)("div",{className:"grid md:flex md:flex-wrap md:justify-center gap-3 m--1.5 pt-6 sm:pt-8 z-10",children:n.actions.map(e=>{let n=(0,x.xf)(e.link)?e.link:(0,u.AP)((0,x.pJ)(e.link,t));return(0,c.jsx)("div",{className:"flex flex-shrink-0 p-1",children:(0,c.jsx)(rh,{type:"a",href:n,text:tK(e.text),theme:e.theme,className:"w-full"})},n)})})]}),r?(0,c.jsxs)("div",{className:"rspress-home-hero-image md:flex-center m-auto order-1 md:order-2 sm:flex md:none lg:flex",children:[(0,c.jsx)("img",{src:(0,u.i6)(o.light),alt:n.image?.alt,srcSet:rw(n.image?.srcset),sizes:rw(n.image?.sizes),width:375,height:375,className:"dark:hidden"}),(0,c.jsx)("img",{src:(0,u.i6)(o.dark),alt:n.image?.alt,srcSet:rw(n.image?.srcset),sizes:rw(n.image?.sizes),width:375,height:375,className:"hidden dark:block"})]}):null]})]})}function rw(e){return(Array.isArray(e)?e:[e]).filter(Boolean).join(", ")||void 0}function rk(){let{lastUpdatedText:e="Last Updated"}=tL(),{page:{lastUpdatedTime:t},siteData:n}=(0,u.Vi)(),{themeConfig:r}=n,i=r?.lastUpdatedText||e;return(0,c.jsx)("div",{className:"flex text-sm text-text-2 leading-6 sm:leading-8 font-medium",children:(0,c.jsxs)("p",{children:[i,": ",(0,c.jsx)("span",{children:t})]})})}function rI(){let{nav:e}=tL(),t=(0,u.aw)();return Array.isArray(e)?e:[...e[t.length>0?t:"default"]]}function rD(e){let{pathname:t,base:n}=e,r=new RegExp(e.activeMatch||e.link).test((0,x.tz)(t,n));return(0,c.jsx)(nm,{href:(0,u.AP)(e.link),onClick:e.onClick,children:(0,c.jsxs)("div",{className:`rspress-nav-menu-item ${t4.singleItem} ${r?t4.activeItem:""} text-sm font-medium ${e.compact?"mx-0.5":"mx-1.5"} px-3 py-2 flex items-center`,children:[(0,c.jsx)(im,{tag:e.tag}),e.text,e.rightIcon]},e.text)})}function rE(){let{siteData:e,page:t}=(0,u.Vi)(),n=(0,u.aw)(),{pathname:r,search:i}=(0,u.TH)(),a=e.lang||"",o=e.multiVersion.default||"",s=Object.values(e.locales||e.themeConfig.locales||{}),l=e.route?.cleanUrls||!1,d=s.length>1,{lang:h,pageType:p}=t,{base:m}=e;return d?{text:(0,c.jsx)(t7,{icon:tF,style:{width:"18px",height:"18px"}}),items:s.map(e=>({text:e?.label,link:(0,x.$U)(r+i,{current:h,target:e.lang,default:a},{current:n,default:o},m,l,"404"===p)})),activeValue:s.find(e=>h===e.lang)?.label}:{items:[]}}function rF(){let{siteData:e,page:t}=(0,u.Vi)(),n=(0,u.aw)(),{pathname:r}=(0,u.TH)(),i=e.route?.cleanUrls||!1,a=e.multiVersion.default||"",o=e.multiVersion.versions||[],{base:s}=e;return{items:o.map(e=>({text:e,link:(0,x.xM)(r,{current:n,target:e,default:a},s,i,"404"===t.pageType)})),text:n,activeValue:n}}let rA={socialLinksIcon:"social-links-icon_a4ad0",menuItem:"menu-item_e90a6"},rC=e=>{let{link:t,popperStyle:n={}}=e,{icon:r,mode:i="link",content:a}=t,o=(0,c.jsx)(c.Fragment,{});if(r){let e="string"==typeof r?({github:''})[r]:r.svg;o=(0,c.jsx)("div",{dangerouslySetInnerHTML:{__html:e}})}let[s,l]=(0,p.useState)(!1),d=()=>{l(!0)},u=()=>{l(!1)};return"link"===i?(0,c.jsx)("a",{href:a,target:"_blank",rel:"noopener noreferrer",className:"social-links",children:(0,c.jsx)("div",{className:`${rA.socialLinksIcon}`,children:o})},a):"text"===i?(0,c.jsxs)("div",{className:`${rA.socialLinksIcon} cursor-pointer relative mx-3`,onMouseEnter:d,onMouseLeave:u,children:[o,s?(0,c.jsx)("div",{style:{boxShadow:"var(--rp-shadow-3)",border:"1px solid var(--rp-c-divider-light)",...n},className:"z-[1] p-3 w-50 absolute right-0 bg-white dark:bg-dark",children:(0,c.jsx)("div",{className:"text-md",children:a})}):null]}):"img"===i?(0,c.jsxs)("div",{className:`${rA.socialLinksIcon} cursor-pointer relative`,onMouseEnter:d,onMouseLeave:u,children:[o,s?(0,c.jsx)("div",{className:"break-all z-[1] p-3 w-[50px] h-[50px] absolute right-0 bg-white dark:bg-dark rounded-xl",style:{boxShadow:"var(--rp-shadow-3)",...n},children:(0,c.jsx)("img",{src:a,alt:"img"})}):null]}):"dom"===i?(0,c.jsxs)("div",{className:`${rA.socialLinksIcon} cursor-pointer relative`,onMouseEnter:d,onMouseLeave:u,children:[o,s?(0,c.jsx)("div",{className:"break-all z-[1] p-3 absolute right-0 bg-white dark:bg-dark rounded-xl",style:{boxShadow:"var(--rp-shadow-3)",...n},children:(0,c.jsx)("div",{dangerouslySetInnerHTML:{__html:a}})}):null]}):(0,c.jsx)("div",{})},rj=e=>{let{links:t}=e;return(0,c.jsx)("div",{style:{boxShadow:"var(--rp-shadow-3)",marginRight:"-2px",border:"1px solid var(--rp-c-divider-light)",background:"var(--rp-c-bg)"},className:"absolute top-8 right-0 z-1 p-3 w-32 rounded-2xl flex flex-wrap gap-4",children:t.map(e=>(0,c.jsx)(rC,{link:e,popperStyle:{top:"1.25rem"}},e.content))})},rP=e=>{let{links:t,moreIconVisible:n=!1,mouseEnter:r}=e;return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)("div",{className:"flex-center h-full gap-x-4 transition-colors duration-300 md:mr-2",children:t.map((e,t)=>(0,c.jsx)(rC,{link:e,popperStyle:{top:"2.5rem"}},t))}),n?(0,c.jsx)("div",{className:"md:ml-1 p-2",onMouseEnter:r,children:(0,c.jsx)(t7,{icon:tA})}):null]})},rS=({socialLinks:e})=>{let t=e.length>5,n=e.slice(0,5),r=e.slice(5),[i,a]=(0,p.useState)(!1),o=(0,p.useCallback)(()=>{a(!1)},[a]),s=(0,p.useCallback)(()=>{a(!0)},[a]);return(0,c.jsxs)("div",{className:`social-links ${rA.menuItem} flex-center relative`,onMouseLeave:o,children:[(0,c.jsx)(rP,{links:n,moreIconVisible:t,mouseEnter:s}),i?(0,c.jsx)(rj,{links:r}):null]})},rT=()=>"function"==typeof document?.startViewTransition&&!window.matchMedia("(prefers-reduced-motion: reduce)").matches,rN=()=>{let e=document.createElement("style");return e.innerHTML=` + .rspress-doc { + view-transition-name: none !important; + } + `,document.head.appendChild(e),()=>{document.head.removeChild(e)}};function r_({onClick:e}){let{theme:t,setTheme:n=()=>{}}=(0,p.useContext)(u.Ni);return(0,c.jsx)("div",{onClick:r=>{let i=rT(),a=ts.Z?.themeConfig?.enableAppearanceAnimation,o="dark"===t?"light":"dark",s="dark"===o;if(i&&a){let t=r.clientX,i=r.clientY,a=Math.hypot(Math.max(t,innerWidth-t+200),Math.max(i,innerHeight-i+200)),l=rN(),c=document.startViewTransition(async()=>{(0,tP.flushSync)(()=>{n(o),e?.()})}),d=[`circle(0px at ${t}px ${i}px)`,`circle(${a}px at ${t}px ${i}px)`];c.ready.then(()=>{document.documentElement.animate({clipPath:s?[...d].reverse():d},{duration:400,easing:"ease-in",pseudoElement:s?"::view-transition-old(root)":"::view-transition-new(root)",id:""}).finished.then(()=>{l()})})}else n(o),e?.()},className:"md:mr-2 rspress-nav-appearance",children:(0,c.jsxs)("div",{className:"p-1 border border-solid border-gray-300 text-gray-400 cursor-pointer rounded-md hover:border-gray-600 hover:text-gray-600 dark:hover:border-gray-200 dark:hover:text-gray-200 transition-all duration-300 w-7 h-7",children:[(0,c.jsx)(t7,{className:"dark:hidden",icon:tj,width:"18",height:"18",fill:"currentColor"}),(0,c.jsx)(t7,{className:"hidden dark:block",icon:tC,width:"18",height:"18",fill:"currentColor"})]})})}let rB={navScreen:"navScreen_ec30c",active:"active_d804e",container:"container_c935d",navMenu:"navMenu_b887b",navMenuItem:"navMenuItem_e7978",navAppearance:"navAppearance_bf893",socialAndAppearance:"socialAndAppearance_eda28",navScreenMenuGroup:"navScreenMenuGroup_e771d",open:"open_aaab4",button:"button_ea41e",buttonSpan:"buttonSpan_f4b8f",items:"items_dd149",down:"down_f631a"};function rO(e){let{activeValue:t}=e,[n,r]=(0,p.useState)(!1);function i({item:e}){return(0,c.jsx)("div",{className:"p-1 text-center",children:(0,c.jsx)("span",{className:"text-brand",children:e.text})})}function a({item:e}){return(0,c.jsx)("div",{className:"py-1 font-medium",children:(0,c.jsx)(nm,{href:e.link,children:(0,c.jsx)("div",{children:(0,c.jsx)("div",{className:"flex justify-center",children:(0,c.jsx)("span",{children:e.text})})})})})}let o=e=>t===e.text?(0,c.jsx)(i,{item:e},e.link):(0,c.jsx)(a,{item:e},e.link),s=e=>(0,c.jsxs)("div",{children:["link"in e?o(e):(0,c.jsx)("p",{className:"font-bold text-gray-400 my-1 not:first:border",children:e.text}),e.items.map(o)]});return(0,c.jsxs)("div",{className:`${n?rB.open:""} ${rB.navScreenMenuGroup} relative`,children:[(0,c.jsxs)("button",{className:rB.button,onClick:()=>{r(!n)},children:[(0,c.jsx)("span",{className:rB.buttonSpan,children:e.text}),(0,c.jsx)(tS,{className:`${n?rB.open:""} ${rB.down} `})]}),(0,c.jsx)("div",{children:(0,c.jsx)("div",{className:rB.items,children:e.items.map(e=>(0,c.jsx)("div",{children:"items"in e?s(e):o(e)},e.text))})})]})}let rR=()=>{let e=rE();return(0,c.jsx)("div",{className:"flex text-sm font-bold justify-center",children:(0,c.jsx)("div",{className:"mx-1.5 my-1",children:(0,c.jsx)(rO,{...e})})})},rq=()=>{let e=rF();return(0,c.jsx)("div",{className:`${rB.navTranslations} flex text-sm font-bold justify-center`,children:(0,c.jsx)("div",{className:"mx-1.5 my-1",children:(0,c.jsx)(rO,{...e})})})},rL=()=>(0,c.jsx)("div",{className:`mt-2 ${rB.navAppearance} flex justify-center`,children:(0,c.jsx)(u.ri,{children:(0,c.jsx)(r_,{})})}),rM=({menuItems:e,pathname:t,base:n,langs:r,toggleScreen:i})=>(0,c.jsx)("div",{className:rB.navMenu,children:e.map(e=>(0,c.jsx)("div",{className:`${rB.navMenuItem} w-full`,children:"link"in e?(0,c.jsx)(rD,{pathname:t,base:n,langs:r,onClick:i,...e},e.text):(0,c.jsx)("div",{className:"mx-3 last:mr-0",children:(0,c.jsx)(rO,{...e,items:"items"in e?e.items:e})},e.text)},e.text))});function rz(e){let{isScreenOpen:t,toggleScreen:n,siteData:r,pathname:i}=e,a=(0,p.useRef)(null),o=r.themeConfig.locales||[],s=o.length>1,l=r.multiVersion.versions.length>1,d=rI(),u=!1!==r.themeConfig.darkMode,h=r?.themeConfig?.socialLinks||[],x=h.length>0,m=o.map(e=>e.lang||"zh")||[],{base:f}=r;return(0,p.useEffect)(()=>(a.current&&t&&tD(a.current,{reserveScrollBarGap:!0}),()=>{tE()}),[t]),(0,c.jsx)("div",{className:`${rB.navScreen} ${t?rB.active:""} rspress-nav-screen`,ref:a,id:"navScreen",children:(0,c.jsxs)("div",{className:rB.container,children:[(0,c.jsx)(rM,{menuItems:d,base:f,langs:m,pathname:i,toggleScreen:n}),(0,c.jsxs)("div",{className:"flex-center flex-col gap-2",children:[u&&(0,c.jsx)(rL,{}),s&&(0,c.jsx)(rR,{}),l&&(0,c.jsx)(rq,{}),x&&(0,c.jsx)(rS,{socialLinks:h})]})]})})}let rH={navHamburger:"navHamburger_ac64c",active:"active_bc9a1"};function r$(e){let{siteData:t,pathname:n}=e,{isScreenOpen:r,toggleScreen:i}=function(){let{pathname:e}=(0,u.TH)(),[t,n]=(0,p.useState)(!1);function r(){n(!0),window.addEventListener("resize",a)}function i(){n(!1),window.removeEventListener("resize",a)}function a(){window.outerWidth>=768&&i()}return(0,p.useEffect)(()=>{i()},[e]),{isScreenOpen:t,openScreen:r,closeScreen:i,toggleScreen:function(){t?i():r()}}}();return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(rz,{isScreenOpen:r,toggleScreen:i,siteData:t,pathname:n}),(0,c.jsx)("button",{onClick:i,"aria-label":"mobile hamburger",className:`${r?rH.active:""} rspress-mobile-hamburger ${rH.navHamburger} text-gray-500`,children:(0,c.jsx)(t7,{icon:tl,fill:"currentColor"})})]})}function rW({item:e}){return(0,c.jsxs)("div",{className:"rounded-2xl my-1 flex",style:{padding:"0.4rem 1.5rem 0.4rem 0.75rem"},children:[e.tag&&(0,c.jsx)(im,{tag:e.tag}),(0,c.jsx)("span",{className:"text-brand",children:e.text})]},e.link)}function rK({item:e}){return(0,c.jsx)("div",{className:"font-medium my-1",children:(0,c.jsx)(nm,{href:e.link,children:(0,c.jsx)("div",{className:"rounded-2xl hover:bg-mute",style:{padding:"0.4rem 1.5rem 0.4rem 0.75rem"},children:(0,c.jsxs)("div",{className:"flex",children:[e.tag&&(0,c.jsx)(im,{tag:e.tag}),(0,c.jsx)("span",{children:e.text})]})})})},e.link)}function rU(e){let{activeValue:t,items:n,base:r="",link:i="",pathname:a=""}=e,[o,s]=(0,p.useState)(!1),l=(0,p.useRef)(),d=()=>{l.current&&(clearTimeout(l.current),l.current=void 0)},u=e=>{let n=new RegExp(e.activeMatch||e.link).test((0,x.tz)(a,r));return t===e.text||!t&&n?(0,c.jsx)(rW,{item:e},e.link):(0,c.jsx)(rK,{item:e},e.link)},h=e=>(0,c.jsxs)("div",{children:["link"in e?u(e):(0,c.jsx)("p",{className:"font-bold text-gray-400 my-1 not:first:border",children:e.text}),e.items.map(u)]});return(0,c.jsxs)("div",{className:"relative flex-center h-14",onMouseLeave:()=>{l.current=window.setTimeout(()=>{s(!1)},150)},children:[(0,c.jsx)("button",{onMouseEnter:()=>{d(),s(!0)},className:"rspress-nav-menu-group-button flex-center items-center font-medium text-sm text-text-1 hover:text-text-2 transition-colors duration-200",children:i?(0,c.jsx)(rD,{...e,rightIcon:(0,c.jsx)(t7,{icon:tS})}):(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)("span",{className:"text-sm font-medium flex",style:{marginRight:"2px"},children:[(0,c.jsx)(im,{tag:e.tag}),e.text]}),(0,c.jsx)(t7,{icon:tS})]})}),(0,c.jsx)("div",{className:"rspress-nav-menu-group-content absolute mx-0.8 transition-opacity duration-300",style:{opacity:+!!o,visibility:o?"visible":"hidden",right:0,top:"52px"},onMouseEnter:d,children:(0,c.jsx)("div",{className:"p-3 pr-2 w-full h-full max-h-100vh whitespace-nowrap",style:{boxShadow:"var(--rp-shadow-3)",zIndex:100,border:"1px solid var(--rp-c-divider-light)",borderRadius:"var(--rp-radius-large)",background:"var(--rp-c-bg)"},children:n.map(e=>(0,c.jsx)("div",{children:"items"in e?h(e):u(e)},e.text))})})]})}function rV(){let e=rE();return(0,c.jsx)("div",{className:`translation ${t4.menuItem} flex text-sm font-bold items-center px-3 py-2`,children:(0,c.jsx)("div",{children:(0,c.jsx)(rU,{...e})})})}function rG(){let e=rF();return(0,c.jsx)("div",{className:`translation ${t4.menuItem} flex text-sm font-bold items-center px-3 py-2`,children:(0,c.jsx)("div",{children:(0,c.jsx)(rU,{...e})})})}function rZ(e){let{beforeNavTitle:t,afterNavTitle:n,beforeNav:r,afterNavMenu:i,navTitle:a}=e,{siteData:o,page:s}=(0,u.Vi)(),{base:l}=o,{pathname:d}=(0,u.TH)(),{width:h}=(0,u.iP)(),p=tq(),x=h<1280,m=Object.values(o.locales||o.themeConfig.locales||{}),f=m.length>1,g=o.multiVersion.versions.length>1,v=o.themeConfig.socialLinks||[],y=v.length>0,b=m.map(e=>e.lang||"")||[],w=({menuItems:e})=>(0,c.jsx)("div",{className:"rspress-nav-menu menu h-14",children:e.map(t=>"items"in t||Array.isArray(t)?(0,c.jsx)("div",{className:"mx-3 last:mr-0",children:(0,c.jsx)(rU,{...t,base:l,pathname:d,langs:b,items:"items"in t?t.items:t})},t.text):(0,c.jsx)(rD,{pathname:d,langs:b,base:l,compact:e.length>5,...t},t.link))}),k=rI(),I=e=>e.position??"right",D=k.filter(e=>"left"===I(e)),E=k.filter(e=>"right"===I(e)),F=o?.themeConfig?.search!==!1,A=!1!==o.themeConfig.darkMode;return(0,c.jsxs)(c.Fragment,{children:[r,(0,c.jsx)("div",{className:`${t4.navContainer} rspress-nav px-6 ${p&&!x?t4.hidden:""} ${!x||!p||"doc"!==s.pageType?t4.sticky:t4.relative}`,children:(0,c.jsxs)("div",{className:`${t4.container} flex justify-between items-center h-full`,children:[t,a||(0,c.jsx)(t5,{}),n,(0,c.jsxs)("div",{className:"flex flex-1 justify-end items-center",children:[D.length>0?(0,c.jsx)("div",{className:t4.leftNav,children:(0,c.jsx)(w,{menuItems:D})}):null,(0,c.jsxs)("div",{className:t4.rightNav,children:[F&&(0,c.jsx)("div",{className:"flex sm:flex-1 items-center sm:pl-4 sm:pr-2",children:(0,c.jsx)(ix,{})}),(0,c.jsx)(w,{menuItems:E}),(0,c.jsxs)("div",{className:"flex-center flex-row",children:[f&&(0,c.jsx)(rV,{}),g&&(0,c.jsx)(rG,{}),A&&(0,c.jsx)("div",{className:"mx-2",children:(0,c.jsx)(r_,{})}),y&&(0,c.jsx)(rS,{socialLinks:v})]})]}),i,(0,c.jsxs)("div",{className:t4.mobileNavMenu,children:[x&&F&&(0,c.jsx)(ix,{}),(0,c.jsx)(r$,{siteData:o,pathname:d})]})]})]})})]})}let rJ={"header-anchor":"header-anchor_d4f17",headerAnchor:"header-anchor_d4f17","overview-groups":"overview-groups_ced08",overviewGroups:"overview-groups_ced08","overview-group-li":"overview-group-li_e0f17",overviewGroupLi:"overview-group-li_e0f17","level-2":"level-2_e4d63",level2:"level-2_e4d63","level-3":"level-3_b489a",level3:"level-3_b489a","level-4":"level-4_a9543",level4:"level-4_a9543","overview-group":"overview-group_f8331",overviewGroup:"overview-group_f8331",header:"header_ba4f6"},rQ=e=>e.toLowerCase().replace(/-/g," "),rY=(e,t)=>rQ(e).includes(rQ(t)),rX=({query:e,setQuery:t,searchRef:n,filterNameText:r,filterPlaceholderText:i})=>(0,c.jsxs)("div",{className:"flex items-center justify-start gap-4",children:[(0,c.jsx)("label",{htmlFor:"api-filter",children:r}),(0,c.jsx)("input",{ref:n,type:"search",placeholder:i,id:"api-filter",value:e,onChange:e=>t(e.target.value),className:"border border-gray-300 dark:border-gray-700 rounded-lg px-3 py-2 transition-shadow duration-250 ease-in-out focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-opacity-50"})]}),r1=({group:e,styles:t})=>(0,c.jsxs)("div",{className:"mb-16",children:[(0,c.jsx)("h2",{children:tJ(e.name)}),(0,c.jsx)("div",{className:t.overviewGroups,children:e.items.map(e=>(0,c.jsxs)("div",{className:t.overviewGroup,children:[(0,c.jsx)("div",{className:"flex",children:(0,c.jsx)("h3",{style:{marginBottom:8},children:(0,c.jsx)(nm,{href:(0,u.AP)(e.link),children:tJ(e.text)})})}),(0,c.jsx)("ul",{className:"list-none",children:e.headers?.map(n=>(0,c.jsx)("li",{className:`${t.overviewGroupLi} ${t[`level${n.depth}`]} first:mt-2`,children:(0,c.jsx)(nm,{href:`${(0,u.AP)(e.link)}#${n.id}`,children:tJ(n.text)})},n.id))})]},e.link))})]},e.name);function r0(e){let{siteData:t,page:{routePath:n,title:r,frontmatter:i}}=(0,u.Vi)(),{content:a,groups:o,defaultGroupTitle:s="Others"}=e,[l,d]=(0,p.useState)(""),h=(0,p.useRef)(null);(0,p.useEffect)(()=>{h.current?.focus()},[]);let x=e=>(0,u.pJ)(e).startsWith(n.replace(/overview$/,""))&&!(0,u.pV)((0,u.pJ)(e),n),m=e=>"link"in e&&e.link?e.link:"items"in e?m(e.items[0]):"",{pages:f}=t,g=f.filter(e=>x(e.routePath)),v=t2(),{overview:{filterNameText:y="Filter",filterPlaceholderText:b="Enter keyword",filterNoResultText:w="No matching API found"}={}}=tL();function k(t,r,i){if(t9(t)||(0,u.pJ)(t.link)===`${n}index`&&i?.overview===!0)return!1;let a=e?.overviewHeaders??t.overviewHeaders??i?.overviewHeaders??r?.overviewHeaders??[2],o=g.find(e=>(0,u.pV)(e.routePath,(0,u.pJ)(t.link||""))),s=m(t);return{...t,link:s,headers:o?.toc?.filter(e=>a.some(t=>e.depth===t))||[]}}v[0]?.link!==n&&(v=function e(t,n){let r,i=t.findIndex(e=>(function(e){if(t9(e))return!1;let t=(0,u.pJ)(e.link),r=t.endsWith("/index")?t.slice(0,-5):t,i=n.replace(/\/$/,"");return t===n||r===n||t===i||r===i})(e));if(-1===i)return t.map(t=>"items"in t?e(t.items,n):[]).flat();let a=t[i];if("items"in a&&Array.isArray(r=a.items)&&r.length>=1)return a.items.every(e=>!("items"in e))?[a]:a.items.filter(e=>!t9(e));let o=[...t];return"items"in a||o.splice(i,1),o.filter(e=>!t9(e))}(v,n));let I=o??(0,p.useMemo)(()=>v.filter(e=>Array.isArray(e?.items)?e.items.filter(e=>x(m(e))).length>0:!!(ne(e)&&x(m(e)))).map(e=>{let t=[];return e?.items?t=e?.items?.map(t=>k(t,e,i)).filter(Boolean):ne(e)&&(t=[k({link:e.link,text:e.text||"",tag:e.tag,_fileKey:e._fileKey,overviewHeaders:e.overviewHeaders},void 0,i)]),{name:e.text||"",items:t}}),[v,n,i]),D=(0,p.useMemo)(()=>l?I.map(e=>{if(rY(e.name,l))return e;let t=e.items.map(e=>{if(rY(e.text||"",l))return e;let t=e.headers?.filter(({text:e})=>rY(e,l));return t?.length?{...e,headers:t}:null}).filter(Boolean);return t.length?{...e,items:t}:null}).filter(Boolean):I,[I,l]);return(0,c.jsxs)("div",{className:"overview-index mx-auto",children:[(0,c.jsxs)("div",{className:"flex flex-col sm:flex-row items-start sm:items-center justify-between mb-10",children:[(0,c.jsx)("h1",{className:"text-3xl leading-10 tracking-tight",children:r||"Overview"}),(0,c.jsx)(rX,{query:l,setQuery:d,searchRef:h,filterNameText:y,filterPlaceholderText:b})]}),a,D.length>0?D.map(e=>(0,c.jsx)(r1,{group:e,styles:rJ},e?.name)):(0,c.jsx)("div",{className:"text-lg text-gray-500 text-center mt-9 pt-9 border-t border-gray-200 dark:border-gray-800",children:`${w}: ${l}`})]})}function r2(e){return(0,c.jsxs)("svg",{id:"Bun",width:"1.2em",height:"1.2em",viewBox:"0 0 80 70",...e,children:[(0,c.jsx)("path",{id:"Shadow",d:"M71.09,20.74c-.16-.17-.33-.34-.5-.5s-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5A26.46,26.46,0,0,1,75.5,35.7c0,16.57-16.82,30.05-37.5,30.05-11.58,0-21.94-4.23-28.83-10.86l.5.5.5.5.5.5.5.5.5.5.5.5.5.5C19.55,65.3,30.14,69.75,42,69.75c20.68,0,37.5-13.48,37.5-30C79.5,32.69,76.46,26,71.09,20.74Z"}),(0,c.jsxs)("g",{id:"Body",children:[(0,c.jsx)("path",{id:"Background",d:"M73,35.7c0,15.21-15.67,27.54-35,27.54S3,50.91,3,35.7C3,26.27,9,17.94,18.22,13S33.18,3,38,3s8.94,4.13,19.78,10C67,17.94,73,26.27,73,35.7Z",style:{fill:"#fbf0df"}}),(0,c.jsx)("path",{id:"Bottom_Shadow","data-name":"Bottom Shadow",d:"M73,35.7a21.67,21.67,0,0,0-.8-5.78c-2.73,33.3-43.35,34.9-59.32,24.94A40,40,0,0,0,38,63.24C57.3,63.24,73,50.89,73,35.7Z",style:{fill:"#f6dece"}}),(0,c.jsx)("path",{id:"Light_Shine","data-name":"Light Shine",d:"M24.53,11.17C29,8.49,34.94,3.46,40.78,3.45A9.29,9.29,0,0,0,38,3c-2.42,0-5,1.25-8.25,3.13-1.13.66-2.3,1.39-3.54,2.15-2.33,1.44-5,3.07-8,4.7C8.69,18.13,3,26.62,3,35.7c0,.4,0,.8,0,1.19C9.06,15.48,20.07,13.85,24.53,11.17Z",style:{fill:"#fffefc"}}),(0,c.jsx)("path",{id:"Top",d:"M35.12,5.53A16.41,16.41,0,0,1,29.49,18c-.28.25-.06.73.3.59,3.37-1.31,7.92-5.23,6-13.14C35.71,5,35.12,5.12,35.12,5.53Zm2.27,0A16.24,16.24,0,0,1,39,19c-.12.35.31.65.55.36C41.74,16.56,43.65,11,37.93,5,37.64,4.74,37.19,5.14,37.39,5.49Zm2.76-.17A16.42,16.42,0,0,1,47,17.12a.33.33,0,0,0,.65.11c.92-3.49.4-9.44-7.17-12.53C40.08,4.54,39.82,5.08,40.15,5.32ZM21.69,15.76a16.94,16.94,0,0,0,10.47-9c.18-.36.75-.22.66.18-1.73,8-7.52,9.67-11.12,9.45C21.32,16.4,21.33,15.87,21.69,15.76Z",style:{fill:"#ccbea7",fillRule:"evenodd"}}),(0,c.jsx)("path",{id:"Outline",d:"M38,65.75C17.32,65.75.5,52.27.5,35.7c0-10,6.18-19.33,16.53-24.92,3-1.6,5.57-3.21,7.86-4.62,1.26-.78,2.45-1.51,3.6-2.19C32,1.89,35,.5,38,.5s5.62,1.2,8.9,3.14c1,.57,2,1.19,3.07,1.87,2.49,1.54,5.3,3.28,9,5.27C69.32,16.37,75.5,25.69,75.5,35.7,75.5,52.27,58.68,65.75,38,65.75ZM38,3c-2.42,0-5,1.25-8.25,3.13-1.13.66-2.3,1.39-3.54,2.15-2.33,1.44-5,3.07-8,4.7C8.69,18.13,3,26.62,3,35.7,3,50.89,18.7,63.25,38,63.25S73,50.89,73,35.7C73,26.62,67.31,18.13,57.78,13,54,11,51.05,9.12,48.66,7.64c-1.09-.67-2.09-1.29-3-1.84C42.63,4,40.42,3,38,3Z"})]}),(0,c.jsxs)("g",{id:"Mouth",children:[(0,c.jsx)("g",{id:"Background-2","data-name":"Background",children:(0,c.jsx)("path",{d:"M45.05,43a8.93,8.93,0,0,1-2.92,4.71,6.81,6.81,0,0,1-4,1.88A6.84,6.84,0,0,1,34,47.71,8.93,8.93,0,0,1,31.12,43a.72.72,0,0,1,.8-.81H44.26A.72.72,0,0,1,45.05,43Z",style:{fill:"#b71422"}})}),(0,c.jsxs)("g",{id:"Tongue",children:[(0,c.jsx)("path",{id:"Background-3","data-name":"Background",d:"M34,47.79a6.91,6.91,0,0,0,4.12,1.9,6.91,6.91,0,0,0,4.11-1.9,10.63,10.63,0,0,0,1-1.07,6.83,6.83,0,0,0-4.9-2.31,6.15,6.15,0,0,0-5,2.78C33.56,47.4,33.76,47.6,34,47.79Z",style:{fill:"#ff6164"}}),(0,c.jsx)("path",{id:"Outline-2","data-name":"Outline",d:"M34.16,47a5.36,5.36,0,0,1,4.19-2.08,6,6,0,0,1,4,1.69c.23-.25.45-.51.66-.77a7,7,0,0,0-4.71-1.93,6.36,6.36,0,0,0-4.89,2.36A9.53,9.53,0,0,0,34.16,47Z"})]}),(0,c.jsx)("path",{id:"Outline-3","data-name":"Outline",d:"M38.09,50.19a7.42,7.42,0,0,1-4.45-2,9.52,9.52,0,0,1-3.11-5.05,1.2,1.2,0,0,1,.26-1,1.41,1.41,0,0,1,1.13-.51H44.26a1.44,1.44,0,0,1,1.13.51,1.19,1.19,0,0,1,.25,1h0a9.52,9.52,0,0,1-3.11,5.05A7.42,7.42,0,0,1,38.09,50.19Zm-6.17-7.4c-.16,0-.2.07-.21.09a8.29,8.29,0,0,0,2.73,4.37A6.23,6.23,0,0,0,38.09,49a6.28,6.28,0,0,0,3.65-1.73,8.3,8.3,0,0,0,2.72-4.37.21.21,0,0,0-.2-.09Z"})]}),(0,c.jsxs)("g",{id:"Face",children:[(0,c.jsx)("ellipse",{id:"Right_Blush","data-name":"Right Blush",cx:"53.22",cy:"40.18",rx:"5.85",ry:"3.44",style:{fill:"#febbd0"}}),(0,c.jsx)("ellipse",{id:"Left_Bluch","data-name":"Left Bluch",cx:"22.95",cy:"40.18",rx:"5.85",ry:"3.44",style:{fill:"#febbd0"}}),(0,c.jsx)("path",{id:"Eyes",d:"M25.7,38.8a5.51,5.51,0,1,0-5.5-5.51A5.51,5.51,0,0,0,25.7,38.8Zm24.77,0A5.51,5.51,0,1,0,45,33.29,5.5,5.5,0,0,0,50.47,38.8Z",style:{fillRule:"evenodd"}}),(0,c.jsx)("path",{id:"Iris",d:"M24,33.64a2.07,2.07,0,1,0-2.06-2.07A2.07,2.07,0,0,0,24,33.64Zm24.77,0a2.07,2.07,0,1,0-2.06-2.07A2.07,2.07,0,0,0,48.75,33.64Z",style:{fill:"#fff",fillRule:"evenodd"}})]})]})}function r3(e){return(0,c.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"1em",height:"1em",viewBox:"0 0 256 256",...e,children:[(0,c.jsx)("path",{fill:"#C12127",d:"M0 256V0h256v256z"}),(0,c.jsx)("path",{fill:"#FFF",d:"M48 48h160v160h-32V80h-48v128H48z"})]})}function r4(e){return(0,c.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"1em",height:"1em",viewBox:"0 0 128 128",...e,children:[(0,c.jsx)("path",{fill:"#f8ab00",d:"M0 .004V40h39.996V.004Zm43.996 0V40h40V.004Zm44.008 0V40H128V.004Zm0 43.996v39.996H128V44Z"}),(0,c.jsx)("path",{fill:"#4c4c4c",d:"M43.996 44v39.996h40V44ZM0 87.996v40h39.996v-40Zm43.996 0v40h40v-40Zm44.008 0v40H128v-40Z"})]})}function r5(e){return(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"1em",height:"1em",viewBox:"0 0 128 128",...e,children:(0,c.jsxs)("g",{fill:"#2c8ebb",children:[(0,c.jsx)("path",{d:"M99.24 80.71C94.9 80.76 91.1 83 87.89 85c-6 3.71-9 3.47-9 3.47l-.1-.17c-.41-.67 1.92-6.68-.69-13.84c-2.82-7.83-7.3-9.72-6.94-10.32c1.53-2.59 5.36-6.7 6.89-14.36c.91-4.64.67-12.28-1.39-16.28c-.38-.74-3.78 1.24-3.78 1.24s-3.18-7.09-4.07-7.66c-2.87-1.84-6 7.61-6 7.61a14 14 0 0 0-11.71 4.5a9.64 9.64 0 0 1-3.85 2.27c-.41.14-.91.12-2.15 3.47c-1.9 5.07 3.24 10.81 3.24 10.81s-6.13 4.33-8.4 9.72a24.78 24.78 0 0 0-1.75 11.68s-4.36 3.78-4.64 7.68a12.87 12.87 0 0 0 1.77 7.83a1.94 1.94 0 0 0 2.63.91s-2.9 3.38-.19 4.81c2.47 1.29 6.63 2 8.83-.19c1.6-1.6 1.92-5.17 2.51-6.63c.14-.34.62.57 1.08 1a10 10 0 0 0 1.36 1s-3.9 1.68-2.3 5.51c.53 1.27 2.42 2.08 5.51 2.06c1.15 0 13.76-.72 17.12-1.53a4.33 4.33 0 0 0 2.61-1.46a63 63 0 0 0 15.49-7c4.74-3.09 6.68-3.93 10.51-4.84c3.16-.75 2.95-5.65-1.24-5.58z"}),(0,c.jsx)("path",{d:"M64 2a62 62 0 1 0 62 62A62 62 0 0 0 64 2zm37.3 87.83c-3.35.81-4.91 1.44-9.41 4.36a67 67 0 0 1-15.56 7.18a8.71 8.71 0 0 1-3.64 1.77c-3.81.93-16.88 1.63-17.91 1.63h-.24c-4 0-6.27-1.24-7.49-2.54c-3.4 1.7-7.8 1-11-.69a5.55 5.55 0 0 1-3-3.9a6 6 0 0 1 0-2.06a6.66 6.66 0 0 1-.79-1A16.38 16.38 0 0 1 30 84.52c.29-3.73 2.87-7.06 4.55-8.83A28.56 28.56 0 0 1 36.61 64a26.82 26.82 0 0 1 6.82-9c-1.65-2.78-3.33-7.06-1.7-11.42c1.17-3.11 2.13-4.84 4.24-5.58a6.84 6.84 0 0 0 2.51-1.34A17.65 17.65 0 0 1 60.34 31c.19-.48.41-1 .65-1.46c1.6-3.4 3.3-5.31 5.29-6a4.88 4.88 0 0 1 4.4.5c.65.43 1.48 1 3.9 6a4.69 4.69 0 0 1 2.85-.1a3.81 3.81 0 0 1 2.39 1.94c2.47 4.74 2.8 13.19 1.72 18.62a33.8 33.8 0 0 1-5.84 13.31a25.73 25.73 0 0 1 5.77 9.43a25.42 25.42 0 0 1 1.41 10.41A28.7 28.7 0 0 0 86 81.91c3.06-1.89 7.68-4.74 13.19-4.81a6.62 6.62 0 0 1 7 5.7a6.35 6.35 0 0 1-4.89 7.03z"})]})})}function r6(e){if(e.startsWith("yarn create"))return e.replace(/(yarn create [^\s]+)@latest/,"$1");if(!e?.includes("install"))return e;let t=e.split(" ").filter(e=>!e.startsWith("-")&&!e.startsWith("--")).join(" ");return"yarn install"===t||"bun install"===t?e:e.replace("install","add")}function r7({command:e,additionalTabs:t=[]}){let n,r={npm:(0,c.jsx)(r3,{}),yarn:(0,c.jsx)(r5,{}),pnpm:(0,c.jsx)(r4,{}),bun:(0,c.jsx)(r2,{})};return t.forEach(e=>{r[e.tool]=e.icon}),"string"==typeof e?(n={npm:`npm ${e}`,yarn:`yarn ${e}`,pnpm:`pnpm ${e}`,bun:`bun ${e}`},t.forEach(t=>{n[t.tool]=`${t.tool} ${e}`})):n=e,n.yarn&&(n.yarn=r6(n.yarn)),n.bun&&(n.bun=r6(n.bun)),(0,c.jsx)(ia,{groupId:"package.manager",values:Object.entries(n).map(([e])=>(0,c.jsxs)("div",{style:{display:"flex",alignItems:"center",fontSize:15},children:[r[e],(0,c.jsx)("span",{style:{marginLeft:6,marginBottom:2},children:e})]},e)),children:Object.entries(n).map(([e,t])=>(0,c.jsx)(io,{children:(0,c.jsx)(nV,{children:(0,c.jsx)(nq,{className:"language-js",codeHighlighter:"prism",children:t})})},e))})}let r8={pagerLink:"pager-link_e0d2d",title:"title_a3acb",next:"next_ad355",desc:"desc_dcc01"};function r9(e){let{type:t,text:n,href:r}=e,{prevPageText:i="Previous Page",nextPageText:a="Next Page"}=tL(),o="prev"===t?r8.pagerLink:`${r8.pagerLink} ${r8.next}`;return(0,c.jsxs)(nm,{href:r,className:o,children:[(0,c.jsx)("span",{className:r8.desc,children:"prev"===t?i:a}),(0,c.jsx)("span",{className:r8.title,children:n})]})}let ie={scrollToTop:"scroll-to-top_e22be",entered:"entered_c8faf"};function it(){let[e,t]=(0,p.useState)(!1),n=()=>{t((window.scrollY||document.documentElement.scrollTop)>0)};return(0,p.useEffect)(()=>{window.addEventListener("scroll",n)},[]),(0,c.jsx)("button",{className:`${ie.scrollToTop} ${e?ie.entered:""}`,onClick:()=>{window.scrollTo({top:0,behavior:"smooth"})},children:(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",className:"w-6 h-6",children:(0,c.jsx)("path",{fillRule:"evenodd",d:"M11.47 2.47a.75.75 0 0 1 1.06 0l7.5 7.5a.75.75 0 1 1-1.06 1.06l-6.22-6.22V21a.75.75 0 0 1-1.5 0V4.81l-6.22 6.22a.75.75 0 1 1-1.06-1.06l7.5-7.5Z",clipRule:"evenodd"})})})}let ir={container:"container_df5ed",tabList:"tab-list_ccbcc",tab:"tab_cae68",notSelected:"not-selected_dab7a",selected:"selected_f5c1e",noScrollbar:"no-scrollbar_db61f"},ii=e=>e&&"object"==typeof e&&"label"in e?e.label||e.value:e,ia=(0,p.forwardRef)((e,t)=>{let{values:n,defaultValue:r,onChange:i,children:a,groupId:o,tabPosition:s="left",tabContainerClassName:l}=e,d=p.Children.toArray(a).filter(e=>"string"!=typeof e||""!==e.trim()),u=n||[];0===u.length&&(u=p.Children.map(d,e=>(0,p.isValidElement)(e)?{label:e.props?.label,value:e.props?.value||e.props?.label}:{label:void 0,value:void 0}));let{tabData:h,setTabData:x}=(0,p.useContext)(ny),[m,f]=(0,p.useState)(()=>void 0===r?0:u.findIndex(e=>"string"==typeof e?e===r:!!e&&"object"==typeof e&&"value"in e&&e.value===r)),[g,v]=rs(`rspress.tabs.${o}`,m.toString()),y=(0,p.useMemo)(()=>o?void 0!==h[o]?h[o]:Number.parseInt(g):m,[o&&h[o]]);(0,p.useEffect)(()=>{if(o){let e=Number.parseInt(g);y!==e&&x({...h,[o]:e})}},[g]);let b=o?y:m;return(0,c.jsxs)("div",{className:ir.container,ref:t,children:[(0,c.jsx)("div",{className:l,children:u.length?(0,c.jsx)("div",{className:`${ir.tabList} ${ir.noScrollbar}`,style:{justifyContent:"center"===s?"center":"flex-start"},children:u.map((e,t)=>(0,c.jsx)("div",{className:`${ir.tab} ${b===t?ir.selected:ir.notSelected}`,onClick:()=>{i?.(t),o?(x({...h,[o]:t}),v(t.toString())):f(t)},children:ii(e)},t))}):null}),(0,c.jsx)("div",{children:p.Children.toArray(d)[b]})]})});function io({children:e,...t}){return(0,c.jsx)("div",{...t,className:"rounded px-2",children:e})}function is({query:e}){let{searchNoResultsText:t="No results for",searchSuggestedQueryText:n="Please try again with a different keyword"}=tL();return(0,c.jsxs)("div",{className:"flex flex-col items-center pt-8 pb-2",children:[(0,c.jsx)(t7,{icon:tO,className:"mb-4 opacity-80"}),(0,c.jsxs)("p",{className:"mb-2",children:[t," ",(0,c.jsxs)("b",{children:['"',e,'"']})]}),(0,c.jsx)("p",{children:n})]})}let il={mask:"mask_ac6b3",modal:"modal_e4a04",inputForm:"inputForm_d4ba2",input:"input_f8add",close:"close_bee84",searchHits:"searchHits_dc1b2",groupTitle:"groupTitle_fe27c",navSearchButton:"navSearchButton_df1fb",searchWord:"searchWord_af2c1",suggestItem:"suggestItem_b1e66",suggestItemContainer:"suggestItemContainer_f5e47",contentWrapper:"contentWrapper_efb78",mark:"mark_b6cd5",titleForContent:"titleForContent_f2995",actionIcon:"actionIcon_f4ffd",current:"current_eb655",tabClassName:"tabClassName_b3f85",mobileNavSearchButton:"mobileNavSearchButton_d85a9"},ic={title:e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M4 4a2 2 0 0 1 2-2h8a1 1 0 0 1 .707.293l5 5A1 1 0 0 1 20 8v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2zm13.586 4L14 4.414V8zM12 4H6v16h12V10h-5a1 1 0 0 1-1-1z"})}),header:e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M28 12v-2h-6V4h-2v6h-8V4h-2v6H4v2h6v8H4v2h6v6h2v-6h8v6h2v-6h6v-2h-6v-8Zm-8 8h-8v-8h8Z"})}),content:e=>(0,c.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 32 32",...e,children:[(0,c.jsx)("circle",{cx:22,cy:24,r:2,fill:"currentColor"}),(0,c.jsx)("path",{fill:"none",d:"M22 28a4 4 0 1 1 4-4 4.004 4.004 0 0 1-4 4m0-6a2 2 0 1 0 2 2 2.003 2.003 0 0 0-2-2"}),(0,c.jsx)("path",{fill:"currentColor",d:"M29.777 23.479A8.64 8.64 0 0 0 22 18a8.64 8.64 0 0 0-7.777 5.479L14 24l.223.521A8.64 8.64 0 0 0 22 30a8.64 8.64 0 0 0 7.777-5.479L30 24ZM22 28a4 4 0 1 1 4-4 4.005 4.005 0 0 1-4 4"}),(0,c.jsx)("path",{fill:"currentColor",d:"M12 28H8V4h8v6a2.006 2.006 0 0 0 2 2h6v4h2v-6a.91.91 0 0 0-.3-.7l-7-7A.9.9 0 0 0 18 2H8a2.006 2.006 0 0 0-2 2v24a2.006 2.006 0 0 0 2 2h4Zm6-23.6 5.6 5.6H18Z"})]})};function id({suggestion:e,closeSearch:t,isCurrent:n,setCurrentSuggestionIndex:r,inCurrentDocIndex:i,scrollTo:a,onMouseMove:o}){let s=ic[e.type],l=i&&!(0,u.yv)()?n3(e.link):e.link,d=(0,p.useRef)(null);n&&d.current?.offsetTop&&a(d.current?.offsetTop,d.current?.offsetHeight);let h=(e,t)=>{let n=[],r=0;for(let i of t){let{start:t,length:a}=i,o=e.slice(r,t),s=function(e,t,n){var r=e.slice(t);let i="",a=0,o=r.length;for(let e=0;e0+n);e++)a>0&&(i+=r.charAt(e));return i}(e,t,a);n.push(o),n.push((0,c.jsx)("span",{className:il.mark,children:s},t)),r=t+s.length}return r{if("header"===e.type||"title"===e.type){let{header:t,highlightInfoList:n}=e;return(0,c.jsx)("div",{className:"font-medium",children:h(t,n)})}return(0,c.jsx)("div",{className:"font-medium",children:e.header})})();break;case"content":x=(0,c.jsxs)(c.Fragment,{children:[(()=>{if("content"!==e.type)return(0,c.jsx)("div",{});let{statement:t,highlightInfoList:n}=e;return(0,c.jsx)("div",{className:"text-sm text-gray-light w-full",children:h(t,n)})})(),(0,c.jsx)("p",{className:il.titleForContent,children:e.title})]})}return(0,c.jsx)("li",{className:`rspress-search-suggest-item ${il.suggestItem} ${n?il.current:""}`,onMouseEnter:r,onMouseMove:o,ref:d,children:(0,c.jsx)("a",{href:l,onClick:e=>{t(),e.stopPropagation()},target:i?"_self":"_blank",children:(0,c.jsxs)("div",{className:il.suggestItemContainer,children:[(0,c.jsx)("div",{className:il.hitIcon,children:(0,c.jsx)(t7,{icon:s})}),(0,c.jsx)("div",{className:il.contentWrapper,children:(0,c.jsx)("span",{children:x})}),(0,c.jsx)("div",{className:il.actionIcon,children:(0,c.jsx)(t7,{icon:tR})})]})})},e.link)}let iu={ARROW_UP:"ArrowUp",ARROW_DOWN:"ArrowDown",ENTER:"Enter",SEARCH:"KeyK",ESC:"Escape"},ih=e=>{let t=(0,p.useRef)(e);return t.current=e,(0,p.useCallback)(z((...e)=>t.current(...e),150),[])};function ip({focused:e,setFocused:t}){let[n,r]=(0,p.useState)(""),[i,a]=(0,p.useState)([]),o=(0,p.useRef)(null),[s,d]=(0,p.useState)(!1),[h,m]=(0,p.useState)(0),[f,g]=(0,p.useState)(0),v=(0,p.useRef)(null),y=(0,p.useRef)(null),[b,w]=(0,p.useState)("initial"),k=(0,p.useRef)(null),I=(0,p.useRef)(null),D=(0,p.useRef)({pageX:null,pageY:null}),[E,F]=(0,p.useState)(!1),A=(e,t)=>{let n=k.current?.offsetHeight,r=k.current?.scrollTop;if(E&&void 0!==n&&void 0!==r){let a=e+t-n-(1===i.length?50:-10);a>r&&k.current?.scrollTo({top:a});let o=1===i.length?e-70:e-10;o{if(v.current)return v.current;let e={currentLang:j,currentVersion:P};return v.current=new ri({indexName:N,...T,...e}),y.current=e,v.current};async function L(){if("initial"!==b)return;let e=q();w("initing"),await e.init(),w("inited");let t=o.current?.value;t&&(a(await e.match(t)||B),d(!1))}let M=()=>{t(!1),m(0),g(0)};(0,p.useEffect)(()=>{let n=n=>{switch(n.code){case iu.SEARCH:(n.ctrlKey||n.metaKey)&&(n.preventDefault(),t(!e));break;case iu.ARROW_DOWN:if(n.isComposing)return;e&&(n.preventDefault(),O&&R===rr.Default&&(F(!0),g((f+1)%O.length)));break;case iu.ARROW_UP:if(n.isComposing)return;if(e&&(n.preventDefault(),R===rr.Default)){let e=O.length;F(!0),g((f-1+e)%e)}break;case iu.ENTER:if(n.isComposing)return;if(f>=0&&R===rr.Default){let e=[...Object.values(H(O))].flat()[f];0===h?window.location.href=(0,x.yv)()?e.link:n3(e.link):window.open(e.link),M()}break;case iu.ESC:M()}};return document.addEventListener("keydown",n),()=>{document.removeEventListener("keydown",n)}},[g,t,e,h,O,f]),(0,p.useEffect)(()=>{e?(a(B),L()):r("")},[e]),(0,p.useEffect)(()=>{"requestIdleCallback"in window&&!v.current&&window.requestIdleCallback(()=>{q().fetchSearchIndex()})},[]),(0,p.useEffect)(()=>{let{currentLang:e,currentVersion:t}=y.current??{},n=_&&P!==t;(j!==e||n)&&(w("initial"),v.current=null,q().fetchSearchIndex())},[j,P,_]);let z=ih(async e=>{let t=e;if(r(t),T&&"remote"===T.mode&&T.searchLoading&&d(!0),t){let e=[];if("beforeSearch"in l){let e=await l.beforeSearch(t);e&&(t=e)}let n=await v.current?.match(t);if(n&&e.push(...n),"onSearch"in l){let n=await l.onSearch(t,e);n&&e.push(...n.map(e=>({renderType:rr.Custom,...e})))}"afterSearch"in l&&await l.afterSearch(t,e),o.current?.value===t&&(a(e||B),d(!1))}}),H=e=>e.reduce((e,t)=>{let n=t.title;return e[n]||(e[n]=[]),e[n].push(t),e},{}),$=(e,t,n)=>{if(n)return(0,c.jsx)("div",{className:"flex flex-col items-center",children:(0,c.jsx)(t7,{icon:t_,className:"m-8 opacity-80"})});if(0===e.length&&"inited"===b)return(0,c.jsx)(is,{query:t});let r=H(e),i=-1;return(0,c.jsx)("ul",{className:il.suggestList,children:Object.keys(r).map(e=>{let t=r[e]||[];return(0,c.jsx)("li",{children:(0,c.jsx)("ul",{className:"pb-2",children:t.map(e=>{let t=++i;return(0,c.jsx)(id,{suggestion:e,isCurrent:t===f,setCurrentSuggestionIndex:e=>{(D.current.pageX!==e.pageX||D.current.pageY!==e.pageY)&&(F(!1),g(t))},onMouseMove:e=>{D.current={pageX:e.pageX,pageY:e.pageY}},closeSearch:()=>{M()},inCurrentDocIndex:0===h,scrollTo:A},`${e.title}-${t}`)})})},e)})})};return(0,c.jsx)(c.Fragment,{children:e&&(0,tP.createPortal)((0,c.jsx)("div",{className:il.mask,onClick:()=>{M()},children:(0,c.jsxs)("div",{className:`${il.modal}`,onClick:e=>{t(!0),e.stopPropagation()},children:[(0,c.jsxs)("div",{className:"flex items-center",children:[(0,c.jsxs)("div",{className:il.inputForm,children:[(0,c.jsx)("label",{children:(0,c.jsx)(t7,{icon:tT})}),(0,c.jsx)("input",{className:`rspress-search-panel-input ${il.input}`,ref:o,placeholder:S,"aria-label":"SearchPanelInput",autoComplete:"off",autoFocus:!0,onChange:e=>z(e.target.value)}),(0,c.jsx)("label",{children:(0,c.jsx)(t7,{icon:tN,className:il.close,onClick:e=>{o.current&&(e.stopPropagation(),n?(o.current.value="",r("")):M())}})})]}),(0,c.jsx)("h2",{className:"text-brand ml-2 sm:hidden cursor-pointer",onClick:e=>{e.stopPropagation(),M()},children:"Cancel"})]}),n&&"inited"===b?(0,c.jsx)("div",{className:`${il.searchHits} rspress-scrollbar`,ref:k,children:((e,t,r)=>{if(1===e.length){let t=e[0].result;return 0!==t.length||r?(0,c.jsx)("div",{ref:I,children:$(t,n,r)}):(0,c.jsx)(is,{query:n})}let i=e.map(e=>t&&"remote"===t.mode?n5(t.searchIndexes||[]).find(t=>t.value===e.group).label:e.group);return(0,c.jsx)(ia,{values:i,tabContainerClassName:il.tabClassName,onChange:e=>{m(e),g(0)},ref:I,children:e.map(e=>(0,c.jsxs)(io,{children:[e.renderType===rr.Default&&$(e.result,n,r),e.renderType===rr.Custom&&l.render(e.result)]},e.group))})})(i,T,s)}):null]})}),document.getElementById("search-container"))})}function ix(){let[e,t]=(0,p.useState)(!1),[n,r]=(0,p.useState)(null),{searchPlaceholderText:i="Search Docs"}=tL();return(0,p.useEffect)(()=>{r(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?"⌘":"Ctrl")},[]),(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)("div",{className:`rspress-nav-search-button ${il.navSearchButton}`,onClick:()=>t(!0),children:(0,c.jsxs)("button",{children:[(0,c.jsx)(t7,{icon:tT,width:"18",height:"18"}),(0,c.jsx)("p",{className:il.searchWord,children:i}),(0,c.jsxs)("div",{style:{opacity:+!!n},children:[(0,c.jsx)("span",{children:n}),(0,c.jsx)("span",{children:"K"})]})]})}),(0,c.jsx)("div",{className:il.mobileNavSearchButton,onClick:()=>t(!0),children:(0,c.jsx)(t7,{icon:tT})}),(0,c.jsx)(ip,{focused:e,setFocused:t})]})}let im=({tag:e})=>e?e.trim().startsWith("{let{top:t,bottom:n,beforeDocFooter:r,afterDocFooter:i,beforeDoc:a,afterDoc:o,beforeDocContent:s,afterDocContent:l,beforeSidebar:d,afterSidebar:h,beforeOutline:x,afterOutline:m,beforeNavTitle:f,afterNavTitle:g,navTitle:v,beforeNav:y,beforeHero:b,afterHero:w,beforeFeatures:k,afterFeatures:I,afterNavMenu:D,components:E}=e,F={beforeDocFooter:r,afterDocFooter:i,beforeDocContent:s,afterDocContent:l,beforeDoc:a,afterDoc:o,beforeSidebar:d,afterSidebar:h,beforeOutline:x,afterOutline:m,components:E},A={beforeHero:b,afterHero:w,beforeFeatures:k,afterFeatures:I},{siteData:C,page:j}=(0,u.Vi)(),{pageType:P,lang:S,title:T,frontmatter:N={}}=j,_=tL();tW();let{siteData:B,page:O}=(0,u.Vi)(),R=B.lang||"",q=Object.values(B.themeConfig.locales||{}).map(e=>e.lang)||[],L=O.lang;(0,p.useEffect)(()=>{let e,t=B.themeConfig.localeRedirect??"auto";if("never"===t||!R||/bot|spider|crawl|lighthouse/i.test(window.navigator.userAgent))return;let{pathname:n,search:r}=window.location,i=(0,u.E9)(n),a="rspress-visited";if(localStorage.getItem(a))return;localStorage.setItem(a,"1");let o=window.navigator.language.split("-")[0];q.includes(o)&&o!==L&&(o===R?e=n.replace(`/${L}`,""):L===R?e=(0,u.pJ)(`/${o}${i}`):"auto"===t&&(e=n.replace(`/${L}`,`/${o}`)),e&&window.location.replace(e+r))},[]);let M=N.title??T,z=C.title||_.title||"";M=M&&"doc"===P?nP(M,N.titleSuffix||z):"home"===P?nP(z,N.titleSuffix):"404"===P?nP("404",z):z;let H=N?.description||C.description||_.description,$={...tM(),...e.uiSwitch};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)(V.ql,{htmlAttributes:{lang:S||"en"},children:[M?(0,c.jsx)("title",{children:M}):null,H?(0,c.jsx)("meta",{name:"description",content:H}):null]}),t,"blank"!==P&&$.showNavbar&&(0,c.jsx)(rZ,{beforeNavTitle:f,afterNavTitle:g,navTitle:v,beforeNav:y,afterNavMenu:D}),(0,c.jsx)("section",{children:(()=>{switch(P){case"home":return(0,c.jsx)(ig.HomeLayout,{...A});case"doc":return(0,c.jsx)(nj,{...F,uiSwitch:$,navTitle:v});case"404":return(0,c.jsx)(ig.NotFoundLayout,{});case"custom":case"blank":return(0,c.jsx)(u.VY,{});default:return(0,c.jsx)(nj,{...F})}})()}),n]})},NotFoundLayout:nS,HomeLayout:function(e){let{beforeHero:t,afterHero:n,beforeFeatures:r,afterFeatures:i}=e,{page:{frontmatter:a,routePath:o}}=(0,u.Vi)();return(0,c.jsxs)("div",{className:"relative",style:{minHeight:"calc(100vh - var(--rp-nav-height))",paddingBottom:"80px"},children:[(0,c.jsxs)("div",{className:"pb-12",children:[t,(0,c.jsx)(rb,{frontmatter:a,routePath:o}),n,r,(0,c.jsx)(rg,{frontmatter:a,routePath:o}),i]}),(0,c.jsx)(rv,{})]})},useBindingAsideScroll:t$,useSetup:tW}},7854:function(e){"use strict";e.exports=JSON.parse('{"AElig":"\xc6","AMP":"&","Aacute":"\xc1","Acirc":"\xc2","Agrave":"\xc0","Aring":"\xc5","Atilde":"\xc3","Auml":"\xc4","COPY":"\xa9","Ccedil":"\xc7","ETH":"\xd0","Eacute":"\xc9","Ecirc":"\xca","Egrave":"\xc8","Euml":"\xcb","GT":">","Iacute":"\xcd","Icirc":"\xce","Igrave":"\xcc","Iuml":"\xcf","LT":"<","Ntilde":"\xd1","Oacute":"\xd3","Ocirc":"\xd4","Ograve":"\xd2","Oslash":"\xd8","Otilde":"\xd5","Ouml":"\xd6","QUOT":"\\"","REG":"\xae","THORN":"\xde","Uacute":"\xda","Ucirc":"\xdb","Ugrave":"\xd9","Uuml":"\xdc","Yacute":"\xdd","aacute":"\xe1","acirc":"\xe2","acute":"\xb4","aelig":"\xe6","agrave":"\xe0","amp":"&","aring":"\xe5","atilde":"\xe3","auml":"\xe4","brvbar":"\xa6","ccedil":"\xe7","cedil":"\xb8","cent":"\xa2","copy":"\xa9","curren":"\xa4","deg":"\xb0","divide":"\xf7","eacute":"\xe9","ecirc":"\xea","egrave":"\xe8","eth":"\xf0","euml":"\xeb","frac12":"\xbd","frac14":"\xbc","frac34":"\xbe","gt":">","iacute":"\xed","icirc":"\xee","iexcl":"\xa1","igrave":"\xec","iquest":"\xbf","iuml":"\xef","laquo":"\xab","lt":"<","macr":"\xaf","micro":"\xb5","middot":"\xb7","nbsp":"\xa0","not":"\xac","ntilde":"\xf1","oacute":"\xf3","ocirc":"\xf4","ograve":"\xf2","ordf":"\xaa","ordm":"\xba","oslash":"\xf8","otilde":"\xf5","ouml":"\xf6","para":"\xb6","plusmn":"\xb1","pound":"\xa3","quot":"\\"","raquo":"\xbb","reg":"\xae","sect":"\xa7","shy":"\xad","sup1":"\xb9","sup2":"\xb2","sup3":"\xb3","szlig":"\xdf","thorn":"\xfe","times":"\xd7","uacute":"\xfa","ucirc":"\xfb","ugrave":"\xf9","uml":"\xa8","uuml":"\xfc","yacute":"\xfd","yen":"\xa5","yuml":"\xff"}')},1636:function(e){"use strict";e.exports=JSON.parse('{"0":"οΏ½","128":"€","130":"β€š","131":"Ζ’","132":"β€ž","133":"…","134":"†","135":"‑","136":"Λ†","137":"‰","138":"Ε ","139":"β€Ή","140":"Ε’","142":"Ε½","145":"β€˜","146":"’","147":"β€œ","148":"”","149":"β€’","150":"–","151":"β€”","152":"˜","153":"β„’","154":"Ε‘","155":"β€Ί","156":"Ε“","158":"ΕΎ","159":"ΕΈ"}')}}]); \ No newline at end of file diff --git a/static/js/2179.d9a2a7b5.js.LICENSE.txt b/static/js/2179.4246b248.js.LICENSE.txt similarity index 100% rename from static/js/2179.d9a2a7b5.js.LICENSE.txt rename to static/js/2179.4246b248.js.LICENSE.txt diff --git a/static/js/2179.d9a2a7b5.js b/static/js/2179.d9a2a7b5.js deleted file mode 100644 index 5e3ae856..00000000 --- a/static/js/2179.d9a2a7b5.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! For license information please see 2179.d9a2a7b5.js.LICENSE.txt */ -(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["2179"],{436:function(e,t,n){"use strict";n.d(t,{ri:()=>th,LX:()=>tg,E9:()=>tw,R0:()=>tu,Vi:()=>tE,i6:()=>tv,TH:()=>tI,AP:()=>tf,s0:()=>tD,pV:()=>tx,yv:()=>tm,pJ:()=>tC,VK:()=>tc,aw:()=>tF,Ni:()=>tp,Jr:()=>tk,Tm:()=>ty,iP:()=>tA,VY:()=>td,Ww:()=>tb});var r=n(7294),i=n(3935);let a=(0,r.createContext)({}),o=(0,r.createContext)({});var s=n(5893),l=n(9250),c=n(5378),d=n(3040);let u=(0,d.lazyWithPreload)(()=>n.e("5123").then(n.bind(n,6080))),h=(0,d.lazyWithPreload)(()=>n.e("7654").then(n.bind(n,403))),p=(0,d.lazyWithPreload)(()=>n.e("7824").then(n.bind(n,3986))),x=(0,d.lazyWithPreload)(()=>n.e("6703").then(n.bind(n,6528))),m=(0,d.lazyWithPreload)(()=>n.e("7221").then(n.bind(n,377))),g=(0,d.lazyWithPreload)(()=>n.e("6112").then(n.bind(n,2875))),f=(0,d.lazyWithPreload)(()=>n.e("9538").then(n.bind(n,5845))),v=(0,d.lazyWithPreload)(()=>n.e("2276").then(n.bind(n,1544))),y=(0,d.lazyWithPreload)(()=>n.e("8274").then(n.bind(n,1644))),b=(0,d.lazyWithPreload)(()=>n.e("5190").then(n.bind(n,2029))),w=(0,d.lazyWithPreload)(()=>n.e("7956").then(n.bind(n,6227))),k=(0,d.lazyWithPreload)(()=>n.e("1995").then(n.bind(n,8216))),I=(0,d.lazyWithPreload)(()=>n.e("3875").then(n.bind(n,5098))),D=(0,d.lazyWithPreload)(()=>n.e("1912").then(n.bind(n,4721))),E=(0,d.lazyWithPreload)(()=>n.e("9422").then(n.bind(n,817))),F=(0,d.lazyWithPreload)(()=>n.e("2540").then(n.bind(n,7683))),A=(0,d.lazyWithPreload)(()=>n.e("1732").then(n.bind(n,9802))),C=(0,d.lazyWithPreload)(()=>n.e("7458").then(n.bind(n,1698))),j=(0,d.lazyWithPreload)(()=>n.e("6307").then(n.bind(n,7623))),P=(0,d.lazyWithPreload)(()=>n.e("3551").then(n.bind(n,6842))),S=(0,d.lazyWithPreload)(()=>n.e("8318").then(n.bind(n,7798))),T=(0,d.lazyWithPreload)(()=>n.e("1399").then(n.bind(n,9424))),N=(0,d.lazyWithPreload)(()=>n.e("238").then(n.bind(n,6601))),_=(0,d.lazyWithPreload)(()=>n.e("2829").then(n.bind(n,3834))),B=(0,d.lazyWithPreload)(()=>n.e("820").then(n.bind(n,301))),O=(0,d.lazyWithPreload)(()=>n.e("8841").then(n.bind(n,4310))),R=(0,d.lazyWithPreload)(()=>n.e("9806").then(n.bind(n,7787))),q=(0,d.lazyWithPreload)(()=>n.e("9862").then(n.bind(n,8108))),L=(0,d.lazyWithPreload)(()=>n.e("9322").then(n.bind(n,3513))),M=(0,d.lazyWithPreload)(()=>n.e("2299").then(n.bind(n,1801))),z=(0,d.lazyWithPreload)(()=>n.e("2640").then(n.bind(n,3873))),H=(0,d.lazyWithPreload)(()=>n.e("9716").then(n.bind(n,2154))),$=(0,d.lazyWithPreload)(()=>n.e("9437").then(n.bind(n,751))),W=(0,d.lazyWithPreload)(()=>n.e("4877").then(n.bind(n,4718))),K=(0,d.lazyWithPreload)(()=>n.e("5363").then(n.bind(n,8924))),U=(0,d.lazyWithPreload)(()=>n.e("4607").then(n.bind(n,3871))),V=(0,d.lazyWithPreload)(()=>n.e("1034").then(n.bind(n,8365))),G=(0,d.lazyWithPreload)(()=>n.e("4979").then(n.bind(n,8335))),Z=(0,d.lazyWithPreload)(()=>n.e("6791").then(n.bind(n,1997))),J=(0,d.lazyWithPreload)(()=>n.e("2721").then(n.bind(n,1564))),Q=(0,d.lazyWithPreload)(()=>n.e("7401").then(n.bind(n,4785))),Y=(0,d.lazyWithPreload)(()=>n.e("521").then(n.bind(n,6083))),X=(0,d.lazyWithPreload)(()=>n.e("5010").then(n.bind(n,7300))),ee=(0,d.lazyWithPreload)(()=>n.e("8186").then(n.bind(n,277))),et=(0,d.lazyWithPreload)(()=>n.e("1584").then(n.bind(n,1718))),en=(0,d.lazyWithPreload)(()=>n.e("7201").then(n.bind(n,2771))),er=(0,d.lazyWithPreload)(()=>n.e("1974").then(n.bind(n,651))),ei=(0,d.lazyWithPreload)(()=>n.e("1396").then(n.bind(n,7828))),ea=(0,d.lazyWithPreload)(()=>n.e("9453").then(n.bind(n,7284))),eo=(0,d.lazyWithPreload)(()=>n.e("3895").then(n.bind(n,2077))),es=(0,d.lazyWithPreload)(()=>n.e("1644").then(n.bind(n,3447))),el=(0,d.lazyWithPreload)(()=>n.e("3942").then(n.bind(n,7265))),ec=(0,d.lazyWithPreload)(()=>n.e("4645").then(n.bind(n,8013))),ed=(0,d.lazyWithPreload)(()=>n.e("8566").then(n.bind(n,4089))),eu=(0,d.lazyWithPreload)(()=>n.e("3218").then(n.bind(n,9729))),eh=(0,d.lazyWithPreload)(()=>n.e("2068").then(n.bind(n,7772))),ep=(0,d.lazyWithPreload)(()=>n.e("5481").then(n.bind(n,5240))),ex=(0,d.lazyWithPreload)(()=>n.e("4108").then(n.bind(n,6132))),em=(0,d.lazyWithPreload)(()=>n.e("2951").then(n.bind(n,6755))),eg=(0,d.lazyWithPreload)(()=>n.e("4025").then(n.bind(n,4575))),ef=(0,d.lazyWithPreload)(()=>n.e("2033").then(n.bind(n,9353))),ev=(0,d.lazyWithPreload)(()=>n.e("635").then(n.bind(n,937))),ey=(0,d.lazyWithPreload)(()=>n.e("6324").then(n.bind(n,8586))),eb=(0,d.lazyWithPreload)(()=>n.e("7365").then(n.bind(n,86))),ew=(0,d.lazyWithPreload)(()=>n.e("2184").then(n.bind(n,6427))),ek=(0,d.lazyWithPreload)(()=>n.e("2787").then(n.bind(n,686))),eI=(0,d.lazyWithPreload)(()=>n.e("3552").then(n.bind(n,8035))),eD=(0,d.lazyWithPreload)(()=>n.e("1290").then(n.bind(n,6147))),eE=(0,d.lazyWithPreload)(()=>n.e("3828").then(n.bind(n,9236))),eF=(0,d.lazyWithPreload)(()=>n.e("5263").then(n.bind(n,8502))),eA=(0,d.lazyWithPreload)(()=>n.e("2595").then(n.bind(n,6977))),eC=(0,d.lazyWithPreload)(()=>n.e("5658").then(n.bind(n,6413))),ej=(0,d.lazyWithPreload)(()=>n.e("7308").then(n.bind(n,8333))),eP=(0,d.lazyWithPreload)(()=>n.e("7368").then(n.bind(n,2828))),eS=(0,d.lazyWithPreload)(()=>n.e("435").then(n.bind(n,6942))),eT=(0,d.lazyWithPreload)(()=>n.e("1441").then(n.bind(n,2991))),eN=(0,d.lazyWithPreload)(()=>n.e("3012").then(n.bind(n,2931))),e_=(0,d.lazyWithPreload)(()=>n.e("1020").then(n.bind(n,5637))),eB=(0,d.lazyWithPreload)(()=>n.e("6096").then(n.bind(n,6665))),eO=(0,d.lazyWithPreload)(()=>n.e("2473").then(n.bind(n,7321))),eR=(0,d.lazyWithPreload)(()=>n.e("3858").then(n.bind(n,68))),eq=(0,d.lazyWithPreload)(()=>n.e("7804").then(n.bind(n,7870))),eL=(0,d.lazyWithPreload)(()=>n.e("5469").then(n.bind(n,6495))),eM=(0,d.lazyWithPreload)(()=>n.e("8425").then(n.bind(n,6620))),ez=(0,d.lazyWithPreload)(()=>n.e("7839").then(n.bind(n,4955))),eH=(0,d.lazyWithPreload)(()=>n.e("3014").then(n.bind(n,6415))),e$=(0,d.lazyWithPreload)(()=>n.e("4880").then(n.bind(n,1310))),eW=(0,d.lazyWithPreload)(()=>n.e("9148").then(n.bind(n,3753))),eK=(0,d.lazyWithPreload)(()=>n.e("1121").then(n.bind(n,4723))),eU=(0,d.lazyWithPreload)(()=>n.e("8369").then(n.bind(n,4916))),eV=(0,d.lazyWithPreload)(()=>n.e("9498").then(n.bind(n,1650))),eG=(0,d.lazyWithPreload)(()=>n.e("7635").then(n.bind(n,6636))),eZ=(0,d.lazyWithPreload)(()=>n.e("7487").then(n.bind(n,49))),eJ=(0,d.lazyWithPreload)(()=>n.e("8756").then(n.bind(n,2688))),eQ=(0,d.lazyWithPreload)(()=>n.e("3748").then(n.bind(n,8523))),eY=(0,d.lazyWithPreload)(()=>n.e("6409").then(n.bind(n,3242))),eX=(0,d.lazyWithPreload)(()=>n.e("1954").then(n.bind(n,3391))),e1=(0,d.lazyWithPreload)(()=>n.e("5828").then(n.bind(n,268))),e0=(0,d.lazyWithPreload)(()=>n.e("8708").then(n.bind(n,8591))),e2=(0,d.lazyWithPreload)(()=>n.e("3241").then(n.bind(n,9546))),e3=(0,d.lazyWithPreload)(()=>n.e("6600").then(n.bind(n,6906))),e4=(0,d.lazyWithPreload)(()=>n.e("5820").then(n.bind(n,9136))),e5=(0,d.lazyWithPreload)(()=>n.e("4913").then(n.bind(n,983))),e6=(0,d.lazyWithPreload)(()=>n.e("2321").then(n.bind(n,7869))),e7=[{path:"/react-native-testing-library/12.x/cookbook/advanced/network-requests",element:r.createElement(u),filePath:"12.x/cookbook/advanced/network-requests.md",preload:async()=>(await u.preload(),n.e("5123").then(n.bind(n,6080))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/cookbook/basics/async-tests",element:r.createElement(h),filePath:"12.x/cookbook/basics/async-tests.md",preload:async()=>(await h.preload(),n.e("7654").then(n.bind(n,403))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/cookbook/basics/custom-render",element:r.createElement(p),filePath:"12.x/cookbook/basics/custom-render.md",preload:async()=>(await p.preload(),n.e("7824").then(n.bind(n,3986))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/cookbook/",element:r.createElement(x),filePath:"12.x/cookbook/index.md",preload:async()=>(await x.preload(),n.e("6703").then(n.bind(n,6528))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/cookbook/state-management/jotai",element:r.createElement(m),filePath:"12.x/cookbook/state-management/jotai.md",preload:async()=>(await m.preload(),n.e("7221").then(n.bind(n,377))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/advanced/testing-env",element:r.createElement(g),filePath:"12.x/docs/advanced/testing-env.mdx",preload:async()=>(await g.preload(),n.e("6112").then(n.bind(n,2875))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/advanced/understanding-act",element:r.createElement(f),filePath:"12.x/docs/advanced/understanding-act.mdx",preload:async()=>(await f.preload(),n.e("9538").then(n.bind(n,5845))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api",element:r.createElement(v),filePath:"12.x/docs/api.md",preload:async()=>(await v.preload(),n.e("2276").then(n.bind(n,1544))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/events/fire-event",element:r.createElement(y),filePath:"12.x/docs/api/events/fire-event.mdx",preload:async()=>(await y.preload(),n.e("8274").then(n.bind(n,1644))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/events/user-event",element:r.createElement(b),filePath:"12.x/docs/api/events/user-event.mdx",preload:async()=>(await b.preload(),n.e("5190").then(n.bind(n,2029))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/jest-matchers",element:r.createElement(w),filePath:"12.x/docs/api/jest-matchers.mdx",preload:async()=>(await w.preload(),n.e("7956").then(n.bind(n,6227))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/misc/accessibility",element:r.createElement(k),filePath:"12.x/docs/api/misc/accessibility.mdx",preload:async()=>(await k.preload(),n.e("1995").then(n.bind(n,8216))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/misc/async",element:r.createElement(I),filePath:"12.x/docs/api/misc/async.mdx",preload:async()=>(await I.preload(),n.e("3875").then(n.bind(n,5098))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/misc/config",element:r.createElement(D),filePath:"12.x/docs/api/misc/config.mdx",preload:async()=>(await D.preload(),n.e("1912").then(n.bind(n,4721))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/misc/other",element:r.createElement(E),filePath:"12.x/docs/api/misc/other.mdx",preload:async()=>(await E.preload(),n.e("9422").then(n.bind(n,817))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/misc/render-hook",element:r.createElement(F),filePath:"12.x/docs/api/misc/render-hook.mdx",preload:async()=>(await F.preload(),n.e("2540").then(n.bind(n,7683))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/queries",element:r.createElement(A),filePath:"12.x/docs/api/queries.mdx",preload:async()=>(await A.preload(),n.e("1732").then(n.bind(n,9802))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/render",element:r.createElement(C),filePath:"12.x/docs/api/render.mdx",preload:async()=>(await C.preload(),n.e("7458").then(n.bind(n,1698))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/api/screen",element:r.createElement(j),filePath:"12.x/docs/api/screen.mdx",preload:async()=>(await j.preload(),n.e("6307").then(n.bind(n,7623))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/guides/community-resources",element:r.createElement(P),filePath:"12.x/docs/guides/community-resources.mdx",preload:async()=>(await P.preload(),n.e("3551").then(n.bind(n,6842))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/guides/faq",element:r.createElement(S),filePath:"12.x/docs/guides/faq.mdx",preload:async()=>(await S.preload(),n.e("8318").then(n.bind(n,7798))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/guides/how-to-query",element:r.createElement(T),filePath:"12.x/docs/guides/how-to-query.mdx",preload:async()=>(await T.preload(),n.e("1399").then(n.bind(n,9424))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/guides/troubleshooting",element:r.createElement(N),filePath:"12.x/docs/guides/troubleshooting.mdx",preload:async()=>(await N.preload(),n.e("238").then(n.bind(n,6601))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/migration/jest-matchers",element:r.createElement(_),filePath:"12.x/docs/migration/jest-matchers.mdx",preload:async()=>(await _.preload(),n.e("2829").then(n.bind(n,3834))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/migration/previous/v11",element:r.createElement(B),filePath:"12.x/docs/migration/previous/v11.mdx",preload:async()=>(await B.preload(),n.e("820").then(n.bind(n,301))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/migration/previous/v2",element:r.createElement(O),filePath:"12.x/docs/migration/previous/v2.mdx",preload:async()=>(await O.preload(),n.e("8841").then(n.bind(n,4310))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/migration/previous/v7",element:r.createElement(R),filePath:"12.x/docs/migration/previous/v7.mdx",preload:async()=>(await R.preload(),n.e("9806").then(n.bind(n,7787))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/migration/previous/v9",element:r.createElement(q),filePath:"12.x/docs/migration/previous/v9.mdx",preload:async()=>(await q.preload(),n.e("9862").then(n.bind(n,8108))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/migration/v12",element:r.createElement(L),filePath:"12.x/docs/migration/v12.mdx",preload:async()=>(await L.preload(),n.e("9322").then(n.bind(n,3513))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/start/intro",element:r.createElement(M),filePath:"12.x/docs/start/intro.md",preload:async()=>(await M.preload(),n.e("2299").then(n.bind(n,1801))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/docs/start/quick-start",element:r.createElement(z),filePath:"12.x/docs/start/quick-start.mdx",preload:async()=>(await z.preload(),n.e("2640").then(n.bind(n,3873))),lang:"",version:"12.x"},{path:"/react-native-testing-library/12.x/",element:r.createElement(H),filePath:"12.x/index.md",preload:async()=>(await H.preload(),n.e("9716").then(n.bind(n,2154))),lang:"",version:"12.x"},{path:"/react-native-testing-library/cookbook/advanced/network-requests",element:r.createElement($),filePath:"13.x/cookbook/advanced/network-requests.md",preload:async()=>(await $.preload(),n.e("9437").then(n.bind(n,751))),lang:"",version:"13.x"},{path:"/react-native-testing-library/cookbook/basics/async-tests",element:r.createElement(W),filePath:"13.x/cookbook/basics/async-tests.md",preload:async()=>(await W.preload(),n.e("4877").then(n.bind(n,4718))),lang:"",version:"13.x"},{path:"/react-native-testing-library/cookbook/basics/custom-render",element:r.createElement(K),filePath:"13.x/cookbook/basics/custom-render.md",preload:async()=>(await K.preload(),n.e("5363").then(n.bind(n,8924))),lang:"",version:"13.x"},{path:"/react-native-testing-library/cookbook/",element:r.createElement(U),filePath:"13.x/cookbook/index.md",preload:async()=>(await U.preload(),n.e("4607").then(n.bind(n,3871))),lang:"",version:"13.x"},{path:"/react-native-testing-library/cookbook/state-management/jotai",element:r.createElement(V),filePath:"13.x/cookbook/state-management/jotai.md",preload:async()=>(await V.preload(),n.e("1034").then(n.bind(n,8365))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/advanced/testing-env",element:r.createElement(G),filePath:"13.x/docs/advanced/testing-env.mdx",preload:async()=>(await G.preload(),n.e("4979").then(n.bind(n,8335))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/advanced/third-party-integration",element:r.createElement(Z),filePath:"13.x/docs/advanced/third-party-integration.mdx",preload:async()=>(await Z.preload(),n.e("6791").then(n.bind(n,1997))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/advanced/understanding-act",element:r.createElement(J),filePath:"13.x/docs/advanced/understanding-act.mdx",preload:async()=>(await J.preload(),n.e("2721").then(n.bind(n,1564))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api",element:r.createElement(Q),filePath:"13.x/docs/api.md",preload:async()=>(await Q.preload(),n.e("7401").then(n.bind(n,4785))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/events/fire-event",element:r.createElement(Y),filePath:"13.x/docs/api/events/fire-event.mdx",preload:async()=>(await Y.preload(),n.e("521").then(n.bind(n,6083))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/events/user-event",element:r.createElement(X),filePath:"13.x/docs/api/events/user-event.mdx",preload:async()=>(await X.preload(),n.e("5010").then(n.bind(n,7300))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/jest-matchers",element:r.createElement(ee),filePath:"13.x/docs/api/jest-matchers.mdx",preload:async()=>(await ee.preload(),n.e("8186").then(n.bind(n,277))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/misc/accessibility",element:r.createElement(et),filePath:"13.x/docs/api/misc/accessibility.mdx",preload:async()=>(await et.preload(),n.e("1584").then(n.bind(n,1718))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/misc/async",element:r.createElement(en),filePath:"13.x/docs/api/misc/async.mdx",preload:async()=>(await en.preload(),n.e("7201").then(n.bind(n,2771))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/misc/config",element:r.createElement(er),filePath:"13.x/docs/api/misc/config.mdx",preload:async()=>(await er.preload(),n.e("1974").then(n.bind(n,651))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/misc/other",element:r.createElement(ei),filePath:"13.x/docs/api/misc/other.mdx",preload:async()=>(await ei.preload(),n.e("1396").then(n.bind(n,7828))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/misc/render-hook",element:r.createElement(ea),filePath:"13.x/docs/api/misc/render-hook.mdx",preload:async()=>(await ea.preload(),n.e("9453").then(n.bind(n,7284))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/queries",element:r.createElement(eo),filePath:"13.x/docs/api/queries.mdx",preload:async()=>(await eo.preload(),n.e("3895").then(n.bind(n,2077))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/render",element:r.createElement(es),filePath:"13.x/docs/api/render.mdx",preload:async()=>(await es.preload(),n.e("1644").then(n.bind(n,3447))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/api/screen",element:r.createElement(el),filePath:"13.x/docs/api/screen.mdx",preload:async()=>(await el.preload(),n.e("3942").then(n.bind(n,7265))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/guides/community-resources",element:r.createElement(ec),filePath:"13.x/docs/guides/community-resources.mdx",preload:async()=>(await ec.preload(),n.e("4645").then(n.bind(n,8013))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/guides/faq",element:r.createElement(ed),filePath:"13.x/docs/guides/faq.mdx",preload:async()=>(await ed.preload(),n.e("8566").then(n.bind(n,4089))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/guides/how-to-query",element:r.createElement(eu),filePath:"13.x/docs/guides/how-to-query.mdx",preload:async()=>(await eu.preload(),n.e("3218").then(n.bind(n,9729))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/guides/react-19",element:r.createElement(eh),filePath:"13.x/docs/guides/react-19.mdx",preload:async()=>(await eh.preload(),n.e("2068").then(n.bind(n,7772))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/guides/troubleshooting",element:r.createElement(ep),filePath:"13.x/docs/guides/troubleshooting.mdx",preload:async()=>(await ep.preload(),n.e("5481").then(n.bind(n,5240))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/migration/jest-matchers",element:r.createElement(ex),filePath:"13.x/docs/migration/jest-matchers.mdx",preload:async()=>(await ex.preload(),n.e("4108").then(n.bind(n,6132))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/migration/previous/v11",element:r.createElement(em),filePath:"13.x/docs/migration/previous/v11.mdx",preload:async()=>(await em.preload(),n.e("2951").then(n.bind(n,6755))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/migration/previous/v12",element:r.createElement(eg),filePath:"13.x/docs/migration/previous/v12.mdx",preload:async()=>(await eg.preload(),n.e("4025").then(n.bind(n,4575))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/migration/previous/v2",element:r.createElement(ef),filePath:"13.x/docs/migration/previous/v2.mdx",preload:async()=>(await ef.preload(),n.e("2033").then(n.bind(n,9353))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/migration/previous/v7",element:r.createElement(ev),filePath:"13.x/docs/migration/previous/v7.mdx",preload:async()=>(await ev.preload(),n.e("635").then(n.bind(n,937))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/migration/previous/v9",element:r.createElement(ey),filePath:"13.x/docs/migration/previous/v9.mdx",preload:async()=>(await ey.preload(),n.e("6324").then(n.bind(n,8586))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/migration/v13",element:r.createElement(eb),filePath:"13.x/docs/migration/v13.mdx",preload:async()=>(await eb.preload(),n.e("7365").then(n.bind(n,86))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/start/intro",element:r.createElement(ew),filePath:"13.x/docs/start/intro.md",preload:async()=>(await ew.preload(),n.e("2184").then(n.bind(n,6427))),lang:"",version:"13.x"},{path:"/react-native-testing-library/docs/start/quick-start",element:r.createElement(ek),filePath:"13.x/docs/start/quick-start.mdx",preload:async()=>(await ek.preload(),n.e("2787").then(n.bind(n,686))),lang:"",version:"13.x"},{path:"/react-native-testing-library/",element:r.createElement(eI),filePath:"13.x/index.md",preload:async()=>(await eI.preload(),n.e("3552").then(n.bind(n,8035))),lang:"",version:"13.x"},{path:"/react-native-testing-library/14.x/cookbook/advanced/network-requests",element:r.createElement(eD),filePath:"14.x/cookbook/advanced/network-requests.md",preload:async()=>(await eD.preload(),n.e("1290").then(n.bind(n,6147))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/cookbook/basics/async-tests",element:r.createElement(eE),filePath:"14.x/cookbook/basics/async-tests.md",preload:async()=>(await eE.preload(),n.e("3828").then(n.bind(n,9236))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/cookbook/basics/custom-render",element:r.createElement(eF),filePath:"14.x/cookbook/basics/custom-render.md",preload:async()=>(await eF.preload(),n.e("5263").then(n.bind(n,8502))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/cookbook/",element:r.createElement(eA),filePath:"14.x/cookbook/index.md",preload:async()=>(await eA.preload(),n.e("2595").then(n.bind(n,6977))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/cookbook/state-management/jotai",element:r.createElement(eC),filePath:"14.x/cookbook/state-management/jotai.md",preload:async()=>(await eC.preload(),n.e("5658").then(n.bind(n,6413))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/advanced/testing-env",element:r.createElement(ej),filePath:"14.x/docs/advanced/testing-env.mdx",preload:async()=>(await ej.preload(),n.e("7308").then(n.bind(n,8333))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/advanced/third-party-integration",element:r.createElement(eP),filePath:"14.x/docs/advanced/third-party-integration.mdx",preload:async()=>(await eP.preload(),n.e("7368").then(n.bind(n,2828))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/advanced/understanding-act",element:r.createElement(eS),filePath:"14.x/docs/advanced/understanding-act.mdx",preload:async()=>(await eS.preload(),n.e("435").then(n.bind(n,6942))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api",element:r.createElement(eT),filePath:"14.x/docs/api.md",preload:async()=>(await eT.preload(),n.e("1441").then(n.bind(n,2991))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/events/fire-event",element:r.createElement(eN),filePath:"14.x/docs/api/events/fire-event.mdx",preload:async()=>(await eN.preload(),n.e("3012").then(n.bind(n,2931))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/events/user-event",element:r.createElement(e_),filePath:"14.x/docs/api/events/user-event.mdx",preload:async()=>(await e_.preload(),n.e("1020").then(n.bind(n,5637))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/jest-matchers",element:r.createElement(eB),filePath:"14.x/docs/api/jest-matchers.mdx",preload:async()=>(await eB.preload(),n.e("6096").then(n.bind(n,6665))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/misc/accessibility",element:r.createElement(eO),filePath:"14.x/docs/api/misc/accessibility.mdx",preload:async()=>(await eO.preload(),n.e("2473").then(n.bind(n,7321))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/misc/async",element:r.createElement(eR),filePath:"14.x/docs/api/misc/async.mdx",preload:async()=>(await eR.preload(),n.e("3858").then(n.bind(n,68))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/misc/config",element:r.createElement(eq),filePath:"14.x/docs/api/misc/config.mdx",preload:async()=>(await eq.preload(),n.e("7804").then(n.bind(n,7870))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/misc/other",element:r.createElement(eL),filePath:"14.x/docs/api/misc/other.mdx",preload:async()=>(await eL.preload(),n.e("5469").then(n.bind(n,6495))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/misc/render-hook",element:r.createElement(eM),filePath:"14.x/docs/api/misc/render-hook.mdx",preload:async()=>(await eM.preload(),n.e("8425").then(n.bind(n,6620))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/queries",element:r.createElement(ez),filePath:"14.x/docs/api/queries.mdx",preload:async()=>(await ez.preload(),n.e("7839").then(n.bind(n,4955))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/render",element:r.createElement(eH),filePath:"14.x/docs/api/render.mdx",preload:async()=>(await eH.preload(),n.e("3014").then(n.bind(n,6415))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/api/screen",element:r.createElement(e$),filePath:"14.x/docs/api/screen.mdx",preload:async()=>(await e$.preload(),n.e("4880").then(n.bind(n,1310))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/guides/community-resources",element:r.createElement(eW),filePath:"14.x/docs/guides/community-resources.mdx",preload:async()=>(await eW.preload(),n.e("9148").then(n.bind(n,3753))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/guides/faq",element:r.createElement(eK),filePath:"14.x/docs/guides/faq.mdx",preload:async()=>(await eK.preload(),n.e("1121").then(n.bind(n,4723))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/guides/how-to-query",element:r.createElement(eU),filePath:"14.x/docs/guides/how-to-query.mdx",preload:async()=>(await eU.preload(),n.e("8369").then(n.bind(n,4916))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/guides/react-19",element:r.createElement(eV),filePath:"14.x/docs/guides/react-19.mdx",preload:async()=>(await eV.preload(),n.e("9498").then(n.bind(n,1650))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/guides/troubleshooting",element:r.createElement(eG),filePath:"14.x/docs/guides/troubleshooting.mdx",preload:async()=>(await eG.preload(),n.e("7635").then(n.bind(n,6636))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/jest-matchers",element:r.createElement(eZ),filePath:"14.x/docs/migration/jest-matchers.mdx",preload:async()=>(await eZ.preload(),n.e("7487").then(n.bind(n,49))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/previous/v11",element:r.createElement(eJ),filePath:"14.x/docs/migration/previous/v11.mdx",preload:async()=>(await eJ.preload(),n.e("8756").then(n.bind(n,2688))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/previous/v12",element:r.createElement(eQ),filePath:"14.x/docs/migration/previous/v12.mdx",preload:async()=>(await eQ.preload(),n.e("3748").then(n.bind(n,8523))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/previous/v2",element:r.createElement(eY),filePath:"14.x/docs/migration/previous/v2.mdx",preload:async()=>(await eY.preload(),n.e("6409").then(n.bind(n,3242))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/previous/v7",element:r.createElement(eX),filePath:"14.x/docs/migration/previous/v7.mdx",preload:async()=>(await eX.preload(),n.e("1954").then(n.bind(n,3391))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/previous/v9",element:r.createElement(e1),filePath:"14.x/docs/migration/previous/v9.mdx",preload:async()=>(await e1.preload(),n.e("5828").then(n.bind(n,268))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/v13",element:r.createElement(e0),filePath:"14.x/docs/migration/v13.mdx",preload:async()=>(await e0.preload(),n.e("8708").then(n.bind(n,8591))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/migration/v14",element:r.createElement(e2),filePath:"14.x/docs/migration/v14.mdx",preload:async()=>(await e2.preload(),n.e("3241").then(n.bind(n,9546))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/start/intro",element:r.createElement(e3),filePath:"14.x/docs/start/intro.md",preload:async()=>(await e3.preload(),n.e("6600").then(n.bind(n,6906))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/docs/start/quick-start",element:r.createElement(e4),filePath:"14.x/docs/start/quick-start.mdx",preload:async()=>(await e4.preload(),n.e("5820").then(n.bind(n,9136))),lang:"",version:"14.x"},{path:"/react-native-testing-library/14.x/",element:r.createElement(e5),filePath:"14.x/index.md",preload:async()=>(await e5.preload(),n.e("4913").then(n.bind(n,983))),lang:"",version:"14.x"},{path:"/react-native-testing-library/404",element:r.createElement(e6),filePath:"404.mdx",preload:async()=>(await e6.preload(),n.e("2321").then(n.bind(n,7869))),lang:"",version:"13.x"}];var e8=n(2599);function e9(e){return decodeURIComponent(e).replace(/\.html$/,"").replace(/\/index$/,"/")}let te=new Map;function tt(e){var t;let n=te.get(e);if(n)return n;let r=(0,e8.fp)(e7,e9(e)),i=null==r||null==(t=r[0])?void 0:t.route;return i&&te.set(e,i),i}let tn=(0,r.memo)(function(e){var t;let n=e.el;return(null===c.Z||void 0===c.Z||null==(t=c.Z.themeConfig)?void 0:t.enableContentAnimation)&&(n=function(e){let[t,n]=(0,r.useState)(e);return(0,r.useLayoutEffect)(()=>{document.startViewTransition&&t!==e?document.startViewTransition(()=>{(0,i.flushSync)(()=>{n(e)}),window.dispatchEvent(new Event("RspressReloadContent"))}):((0,i.flushSync)(()=>{n(e)}),window.dispatchEvent(new Event("RspressReloadContent")))},[e]),t}(e.el)),n},(e,t)=>e.el===t.el);var tr=n(8995);function ti(e="/"){return(0,tr.pJ)(e,c.Z.base)}function ta(e){var t;let n=!!(null===c.Z||void 0===c.Z||null==(t=c.Z.route)?void 0:t.cleanUrls);return(0,tr.yc)(e,n)}tr.nY;var to=tr.yv;tr.Kw,tr.Qj;var ts=n(9655),tl=n(405),tc=ts.VK,td=({fallback:e=(0,s.jsx)(s.Fragment,{})})=>{let{pathname:t}=(0,l.TH)(),n=tt(t);if(!n)return(0,s.jsx)("div",{});let i=n.element;return(0,s.jsx)(r.Suspense,{fallback:e,children:(0,s.jsx)(tn,{el:i})})},tu=a;tl.ql;var th=function(e){let{children:t}=e,[n,i]=(0,r.useState)(!1);return((0,r.useEffect)(()=>{i(!0)},[]),n)?(0,s.jsx)(s.Fragment,{children:t}):null},tp=o,tx=function(e,t){return ti(ta((0,tr.lm)(e)))===ti(ta((0,tr.lm)(t)))},tm=to,tg=e8.LX;e8.fp;var tf=ta,tv=function(e){var t;return!(0,tr.yv)()||(t=e,(0,tr.xf)(t)||(0,tr.pZ)(t)||t.startsWith("//"))||!e.startsWith("/")?e:ti(e)},ty=e9,tb=tt,tw=function(e){return(0,tr.E9)(e,c.Z.base)},tk=function(){return(0,r.useContext)(a).data.page.lang||""},tI=l.TH,tD=l.s0,tE=function(){return(0,r.useContext)(a).data};ts.lr;var tF=function(){return(0,r.useContext)(a).data.page.version||""},tA=function(e,t){let[n,i]=(0,r.useState)({width:e??("undefined"==typeof window?Number.POSITIVE_INFINITY:window.innerWidth),height:t??("undefined"==typeof window?Number.POSITIVE_INFINITY:window.innerHeight)});return(0,r.useLayoutEffect)(()=>{let e=()=>{i({width:window.innerWidth,height:window.innerHeight})};return window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}},[]),n},tC=ti},640:function(e,t,n){"use strict";var r=n(1742),i={"text/plain":"Text","text/html":"Url",default:"Text"};e.exports=function(e,t){var n,a,o,s,l,c,d,u,h=!1;t||(t={}),o=t.debug||!1;try{if(l=r(),c=document.createRange(),d=document.getSelection(),(u=document.createElement("span")).textContent=e,u.ariaHidden="true",u.style.all="unset",u.style.position="fixed",u.style.top=0,u.style.clip="rect(0, 0, 0, 0)",u.style.whiteSpace="pre",u.style.webkitUserSelect="text",u.style.MozUserSelect="text",u.style.msUserSelect="text",u.style.userSelect="text",u.addEventListener("copy",function(n){if(n.stopPropagation(),t.format)if(n.preventDefault(),void 0===n.clipboardData){o&&console.warn("unable to use e.clipboardData"),o&&console.warn("trying IE specific stuff"),window.clipboardData.clearData();var r=i[t.format]||i.default;window.clipboardData.setData(r,e)}else n.clipboardData.clearData(),n.clipboardData.setData(t.format,e);t.onCopy&&(n.preventDefault(),t.onCopy(n.clipboardData))}),document.body.appendChild(u),c.selectNodeContents(u),d.addRange(c),!document.execCommand("copy"))throw Error("copy command was unsuccessful");h=!0}catch(r){o&&console.error("unable to copy using execCommand: ",r),o&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(t.format||"text",e),t.onCopy&&t.onCopy(window.clipboardData),h=!0}catch(r){o&&console.error("unable to copy using clipboardData: ",r),o&&console.error("falling back to prompt"),n="message"in t?t.message:"Copy to clipboard: #{key}, Enter",a=(/mac os x/i.test(navigator.userAgent)?"⌘":"Ctrl")+"+C",s=n.replace(/#{\s*key\s*}/g,a),window.prompt(s,e)}}finally{d&&("function"==typeof d.removeRange?d.removeRange(c):d.removeAllRanges()),u&&document.body.removeChild(u),l()}return h}},8892:function(e){"use strict";e.exports=function(e,n){for(var r,i,a,o=e||"",s=n||"div",l={},c=0;c4&&x.slice(0,4)===o&&s.test(t)&&("-"===t.charAt(4)?m=o+(n=t.slice(5).replace(l,u)).charAt(0).toUpperCase()+n.slice(1):(p=(h=t).slice(4),t=l.test(p)?h:("-"!==(p=p.replace(c,d)).charAt(0)&&(p="-"+p),o+p)),g=i),new g(m,t))};var s=/^data[-\w.:]+$/i,l=/-[a-z]/g,c=/[A-Z]/g;function d(e){return"-"+e.toLowerCase()}function u(e){return e.charAt(1).toUpperCase()}},8055:function(e,t,n){"use strict";var r=n(6230),i=n(3970);e.exports=r([n(629),i,n(647),n(1305),n(2537)])},1305:function(e,t,n){"use strict";var r=n(1422),i=n(7589),a=r.booleanish,o=r.number,s=r.spaceSeparated;e.exports=i({transform:function(e,t){return"role"===t?t:"aria-"+t.slice(4).toLowerCase()},properties:{ariaActiveDescendant:null,ariaAtomic:a,ariaAutoComplete:null,ariaBusy:a,ariaChecked:a,ariaColCount:o,ariaColIndex:o,ariaColSpan:o,ariaControls:s,ariaCurrent:null,ariaDescribedBy:s,ariaDetails:null,ariaDisabled:a,ariaDropEffect:s,ariaErrorMessage:null,ariaExpanded:a,ariaFlowTo:s,ariaGrabbed:a,ariaHasPopup:null,ariaHidden:a,ariaInvalid:null,ariaKeyShortcuts:null,ariaLabel:null,ariaLabelledBy:s,ariaLevel:o,ariaLive:null,ariaModal:a,ariaMultiLine:a,ariaMultiSelectable:a,ariaOrientation:null,ariaOwns:s,ariaPlaceholder:null,ariaPosInSet:o,ariaPressed:a,ariaReadOnly:a,ariaRelevant:null,ariaRequired:a,ariaRoleDescription:s,ariaRowCount:o,ariaRowIndex:o,ariaRowSpan:o,ariaSelected:a,ariaSetSize:o,ariaSort:null,ariaValueMax:o,ariaValueMin:o,ariaValueNow:o,ariaValueText:null,role:null}})},2537:function(e,t,n){"use strict";var r=n(1422),i=n(7589),a=n(9348),o=r.boolean,s=r.overloadedBoolean,l=r.booleanish,c=r.number,d=r.spaceSeparated,u=r.commaSeparated;e.exports=i({space:"html",attributes:{acceptcharset:"accept-charset",classname:"class",htmlfor:"for",httpequiv:"http-equiv"},transform:a,mustUseProperty:["checked","multiple","muted","selected"],properties:{abbr:null,accept:u,acceptCharset:d,accessKey:d,action:null,allow:null,allowFullScreen:o,allowPaymentRequest:o,allowUserMedia:o,alt:null,as:null,async:o,autoCapitalize:null,autoComplete:d,autoFocus:o,autoPlay:o,capture:o,charSet:null,checked:o,cite:null,className:d,cols:c,colSpan:null,content:null,contentEditable:l,controls:o,controlsList:d,coords:c|u,crossOrigin:null,data:null,dateTime:null,decoding:null,default:o,defer:o,dir:null,dirName:null,disabled:o,download:s,draggable:l,encType:null,enterKeyHint:null,form:null,formAction:null,formEncType:null,formMethod:null,formNoValidate:o,formTarget:null,headers:d,height:c,hidden:o,high:c,href:null,hrefLang:null,htmlFor:d,httpEquiv:d,id:null,imageSizes:null,imageSrcSet:u,inputMode:null,integrity:null,is:null,isMap:o,itemId:null,itemProp:d,itemRef:d,itemScope:o,itemType:d,kind:null,label:null,lang:null,language:null,list:null,loading:null,loop:o,low:c,manifest:null,max:null,maxLength:c,media:null,method:null,min:null,minLength:c,multiple:o,muted:o,name:null,nonce:null,noModule:o,noValidate:o,onAbort:null,onAfterPrint:null,onAuxClick:null,onBeforePrint:null,onBeforeUnload:null,onBlur:null,onCancel:null,onCanPlay:null,onCanPlayThrough:null,onChange:null,onClick:null,onClose:null,onContextMenu:null,onCopy:null,onCueChange:null,onCut:null,onDblClick:null,onDrag:null,onDragEnd:null,onDragEnter:null,onDragExit:null,onDragLeave:null,onDragOver:null,onDragStart:null,onDrop:null,onDurationChange:null,onEmptied:null,onEnded:null,onError:null,onFocus:null,onFormData:null,onHashChange:null,onInput:null,onInvalid:null,onKeyDown:null,onKeyPress:null,onKeyUp:null,onLanguageChange:null,onLoad:null,onLoadedData:null,onLoadedMetadata:null,onLoadEnd:null,onLoadStart:null,onMessage:null,onMessageError:null,onMouseDown:null,onMouseEnter:null,onMouseLeave:null,onMouseMove:null,onMouseOut:null,onMouseOver:null,onMouseUp:null,onOffline:null,onOnline:null,onPageHide:null,onPageShow:null,onPaste:null,onPause:null,onPlay:null,onPlaying:null,onPopState:null,onProgress:null,onRateChange:null,onRejectionHandled:null,onReset:null,onResize:null,onScroll:null,onSecurityPolicyViolation:null,onSeeked:null,onSeeking:null,onSelect:null,onSlotChange:null,onStalled:null,onStorage:null,onSubmit:null,onSuspend:null,onTimeUpdate:null,onToggle:null,onUnhandledRejection:null,onUnload:null,onVolumeChange:null,onWaiting:null,onWheel:null,open:o,optimum:c,pattern:null,ping:d,placeholder:null,playsInline:o,poster:null,preload:null,readOnly:o,referrerPolicy:null,rel:d,required:o,reversed:o,rows:c,rowSpan:c,sandbox:d,scope:null,scoped:o,seamless:o,selected:o,shape:null,size:c,sizes:null,slot:null,span:c,spellCheck:l,src:null,srcDoc:null,srcLang:null,srcSet:u,start:c,step:null,style:null,tabIndex:c,target:null,title:null,translate:null,type:null,typeMustMatch:o,useMap:null,value:l,width:c,wrap:null,align:null,aLink:null,archive:d,axis:null,background:null,bgColor:null,border:c,borderColor:null,bottomMargin:c,cellPadding:null,cellSpacing:null,char:null,charOff:null,classId:null,clear:null,code:null,codeBase:null,codeType:null,color:null,compact:o,declare:o,event:null,face:null,frame:null,frameBorder:null,hSpace:c,leftMargin:c,link:null,longDesc:null,lowSrc:null,marginHeight:c,marginWidth:c,noResize:o,noHref:o,noShade:o,noWrap:o,object:null,profile:null,prompt:null,rev:null,rightMargin:c,rules:null,scheme:null,scrolling:l,standby:null,summary:null,text:null,topMargin:c,valueType:null,version:null,vAlign:null,vLink:null,vSpace:c,allowTransparency:null,autoCorrect:null,autoSave:null,disablePictureInPicture:o,disableRemotePlayback:o,prefix:null,property:null,results:c,security:null,unselectable:null}})},9348:function(e,t,n){"use strict";var r=n(1098);e.exports=function(e,t){return r(e,t.toLowerCase())}},1098:function(e){"use strict";e.exports=function(e,t){return t in e?e[t]:t}},7589:function(e,t,n){"use strict";var r=n(4977),i=n(6038),a=n(8444);e.exports=function(e){var t,n,o=e.space,s=e.mustUseProperty||[],l=e.attributes||{},c=e.properties,d=e.transform,u={},h={};for(t in c)n=new a(t,d(l,t),c[t],o),-1!==s.indexOf(t)&&(n.mustUseProperty=!0),u[t]=n,h[r(t)]=t,h[r(n.attribute)]=t;return new i(u,h,o)}},8444:function(e,t,n){"use strict";var r=n(313),i=n(1422);e.exports=s,s.prototype=new r,s.prototype.defined=!0;var a=["boolean","booleanish","overloadedBoolean","number","commaSeparated","spaceSeparated","commaOrSpaceSeparated"],o=a.length;function s(e,t,n,s){var l,c,d,u,h,p,x=-1;for(l=this,(c=s)&&(l.space=c),r.call(this,e,t);++x-1}var o=["itemScope"];function s(t,n,r,i){void 0===i&&(i=null);var a=r[t],o=r._;return a?e.createElement(a,n,i):o?o(t,n,i):e.createElement(t,n,i)}return function(e,r){if(void 0===r&&(r={}),"string"!=typeof e)throw TypeError("Expected HTML string");var a=document.createElement("div");a.innerHTML=e.trim();var o=Array.from(a.childNodes).map(function(e,a){return function e(r,a,o){var l,c=o.transform||{},d=o.preserveAttributes||[],u=o.dangerouslySetChildren||["style"],h=c._;if(8===r.nodeType)return null;if(3===r.nodeType){var p=r.textContent;return h?h(p):p}for(var x={},m=r.attributes,g=0;g1){var i,a=(i=r[0].trim(),/^-ms-/.test(i)&&(i=i.substr(1)),i.startsWith("--")?i:t(i)),s=(n=r.slice(1).join(":").trim(),/^\d+$/.test(n)?Number(n):n.replace(/'/g,'"'));o[a]=s}}),o);else{var c=l[n],u=""===c||String(c).toLowerCase()===r.toLowerCase();e[s.name]=s.isBoolean?u:c}return e},{})),y=Array.from(r.childNodes).map(function(t,r){return n.indexOf(f)>-1&&3===t.nodeType&&(t.textContent=t.textContent.trim(),""===t.textContent)?null:e(t,a+"."+r,o)}).filter(Boolean);if(u.indexOf(f)>-1){var b=r.innerHTML;return b&&("style"!==f&&"script"!==f&&(b=b.replace(/"/g,""")),v.dangerouslySetInnerHTML={__html:b.trim()}),s(f,v,c)}return s(f,v,c,0===y.length?null:y)}(e,String(a),r)}).filter(Boolean);return 1===o.length?o[0]:o}}(n(7294))},1143:function(e){"use strict";e.exports=function(e,t,n,r,i,a,o,s){if(!e){var l;if(void 0===t)l=Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,i,a,o,s],d=0;(l=Error(t.replace(/%s/g,function(){return c[d++]}))).name="Invariant Violation"}throw l.framesToPop=1,l}}},4865:function(e){var t;t=function(){var e,t,n,r={};r.version="0.2.0";var i=r.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
    '};function a(e,t,n){return en?n:e}r.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(i[t]=n);return this},r.status=null,r.set=function(e){var t=r.isStarted();r.status=1===(e=a(e,i.minimum,1))?null:e;var n=r.render(!t),l=n.querySelector(i.barSelector),c=i.speed,d=i.easing;return n.offsetWidth,o(function(t){var a,o,u,h;""===i.positionUsing&&(i.positionUsing=r.getPositioningCSS()),s(l,(a=e,o=c,u=d,(h="translate3d"===i.positionUsing?{transform:"translate3d("+(-1+a)*100+"%,0,0)"}:"translate"===i.positionUsing?{transform:"translate("+(-1+a)*100+"%,0)"}:{"margin-left":(-1+a)*100+"%"}).transition="all "+o+"ms "+u,h)),1===e?(s(n,{transition:"none",opacity:1}),n.offsetWidth,setTimeout(function(){s(n,{transition:"all "+c+"ms linear",opacity:0}),setTimeout(function(){r.remove(),t()},c)},c)):setTimeout(t,c)}),this},r.isStarted=function(){return"number"==typeof r.status},r.start=function(){r.status||r.set(0);var e=function(){setTimeout(function(){r.status&&(r.trickle(),e())},i.trickleSpeed)};return i.trickle&&e(),this},r.done=function(e){return e||r.status?r.inc(.3+.5*Math.random()).set(1):this},r.inc=function(e){var t=r.status;return t?("number"!=typeof e&&(e=(1-t)*a(Math.random()*t,.1,.95)),t=a(t+e,0,.994),r.set(t)):r.start()},r.trickle=function(){return r.inc(Math.random()*i.trickleRate)},e=0,t=0,r.promise=function(n){return n&&"resolved"!==n.state()&&(0===t&&r.start(),e++,t++,n.always(function(){0==--t?(e=0,r.done()):r.set((e-t)/e)})),this},r.render=function(e){if(r.isRendered())return document.getElementById("nprogress");c(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=i.template;var n,a=t.querySelector(i.barSelector),o=e?"-100":(-1+(r.status||0))*100,l=document.querySelector(i.parent);return s(a,{transition:"all 0 linear",transform:"translate3d("+o+"%,0,0)"}),!i.showSpinner&&(n=t.querySelector(i.spinnerSelector))&&h(n),l!=document.body&&c(l,"nprogress-custom-parent"),l.appendChild(t),t},r.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(i.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&h(e)},r.isRendered=function(){return!!document.getElementById("nprogress")},r.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var o=(n=[],function(e){n.push(e),1==n.length&&function e(){var t=n.shift();t&&t(e)}()}),s=function(){var e=["Webkit","O","Moz","ms"],t={};function n(n,r,i){var a;r=t[a=(a=r).replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(e,t){return t.toUpperCase()})]||(t[a]=function(t){var n=document.body.style;if(t in n)return t;for(var r,i=e.length,a=t.charAt(0).toUpperCase()+t.slice(1);i--;)if((r=e[i]+a)in n)return r;return t}(a)),n.style[r]=i}return function(e,t){var r,i,a=arguments;if(2==a.length)for(r in t)void 0!==(i=t[r])&&t.hasOwnProperty(r)&&n(e,r,i);else n(e,a[1],a[2])}}();function l(e,t){return("string"==typeof e?e:u(e)).indexOf(" "+t+" ")>=0}function c(e,t){var n=u(e),r=n+t;l(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=u(e);l(e,t)&&(e.className=(n=r.replace(" "+t+" "," ")).substring(1,n.length-1))}function u(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function h(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return r},"function"==typeof define&&define.amd?define(t):e.exports=t()},2703:function(e,t,n){"use strict";var r=n(414);function i(){}function a(){}a.resetWarningCache=i,e.exports=function(){function e(e,t,n,i,a,o){if(o!==r){var s=Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:a,resetWarningCache:i};return n.PropTypes=n,n}},5697:function(e,t,n){e.exports=n(2703)()},414:function(e){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},9590:function(e){var t="undefined"!=typeof Element,n="function"==typeof Map,r="function"==typeof Set,i="function"==typeof ArrayBuffer&&!!ArrayBuffer.isView;e.exports=function(e,a){try{return function e(a,o){if(a===o)return!0;if(a&&o&&"object"==typeof a&&"object"==typeof o){var s,l,c,d;if(a.constructor!==o.constructor)return!1;if(Array.isArray(a)){if((s=a.length)!=o.length)return!1;for(l=s;0!=l--;)if(!e(a[l],o[l]))return!1;return!0}if(n&&a instanceof Map&&o instanceof Map){if(a.size!==o.size)return!1;for(d=a.entries();!(l=d.next()).done;)if(!o.has(l.value[0]))return!1;for(d=a.entries();!(l=d.next()).done;)if(!e(l.value[1],o.get(l.value[0])))return!1;return!0}if(r&&a instanceof Set&&o instanceof Set){if(a.size!==o.size)return!1;for(d=a.entries();!(l=d.next()).done;)if(!o.has(l.value[0]))return!1;return!0}if(i&&ArrayBuffer.isView(a)&&ArrayBuffer.isView(o)){if((s=a.length)!=o.length)return!1;for(l=s;0!=l--;)if(a[l]!==o[l])return!1;return!0}if(a.constructor===RegExp)return a.source===o.source&&a.flags===o.flags;if(a.valueOf!==Object.prototype.valueOf&&"function"==typeof a.valueOf&&"function"==typeof o.valueOf)return a.valueOf()===o.valueOf();if(a.toString!==Object.prototype.toString&&"function"==typeof a.toString&&"function"==typeof o.toString)return a.toString()===o.toString();if((s=(c=Object.keys(a)).length)!==Object.keys(o).length)return!1;for(l=s;0!=l--;)if(!Object.prototype.hasOwnProperty.call(o,c[l]))return!1;if(t&&a instanceof Element)return!1;for(l=s;0!=l--;)if(("_owner"!==c[l]&&"__v"!==c[l]&&"__o"!==c[l]||!a.$$typeof)&&!e(a[c[l]],o[c[l]]))return!1;return!0}return a!=a&&o!=o}(e,a)}catch(e){if((e.message||"").match(/stack|recursion/i))return console.warn("react-fast-compare cannot handle circular refs"),!1;throw e}}},405:function(e,t,n){"use strict";n.d(t,{B6:()=>$,ql:()=>Q});var r=n(7294),i=n(5697),a=n.n(i),o=n(9590),s=n.n(o),l=n(1143),c=n.n(l),d=n(6774),u=n.n(d);function h(){return(h=Object.assign||function(e){for(var t=1;t=0||(i[n]=e[n]);return i}var g={BASE:"base",BODY:"body",HEAD:"head",HTML:"html",LINK:"link",META:"meta",NOSCRIPT:"noscript",SCRIPT:"script",STYLE:"style",TITLE:"title",FRAGMENT:"Symbol(react.fragment)"},f={rel:["amphtml","canonical","alternate"]},v={type:["application/ld+json"]},y={charset:"",name:["robots","description"],property:["og:type","og:title","og:url","og:image","og:image:alt","og:description","twitter:url","twitter:title","twitter:description","twitter:image","twitter:image:alt","twitter:card","twitter:site"]},b=Object.keys(g).map(function(e){return g[e]}),w={accesskey:"accessKey",charset:"charSet",class:"className",contenteditable:"contentEditable",contextmenu:"contextMenu","http-equiv":"httpEquiv",itemprop:"itemProp",tabindex:"tabIndex"},k=Object.keys(w).reduce(function(e,t){return e[w[t]]=t,e},{}),I=function(e,t){for(var n=e.length-1;n>=0;n-=1){var r=e[n];if(Object.prototype.hasOwnProperty.call(r,t))return r[t]}return null},D=function(e){var t=I(e,g.TITLE),n=I(e,"titleTemplate");if(Array.isArray(t)&&(t=t.join("")),n&&t)return n.replace(/%s/g,function(){return t});var r=I(e,"defaultTitle");return t||r||void 0},E=function(e,t){return t.filter(function(t){return void 0!==t[e]}).map(function(t){return t[e]}).reduce(function(e,t){return h({},e,t)},{})},F=function(e,t,n){var r={};return n.filter(function(t){return!!Array.isArray(t[e])||(void 0!==t[e]&&console&&"function"==typeof console.warn&&console.warn("Helmet: "+e+' should be of type "Array". Instead found type "'+typeof t[e]+'"'),!1)}).map(function(t){return t[e]}).reverse().reduce(function(e,n){var i={};n.filter(function(e){for(var n,a=Object.keys(e),o=0;o/g,">").replace(/"/g,""").replace(/'/g,"'")},N=function(e){return Object.keys(e).reduce(function(t,n){var r=void 0!==e[n]?n+'="'+e[n]+'"':""+n;return t?t+" "+r:r},"")},_=function(e,t){return void 0===t&&(t={}),Object.keys(e).reduce(function(t,n){return t[w[n]||n]=e[n],t},t)},B=function(e,t){return t.map(function(t,n){var i,a=((i={key:n})["data-rh"]=!0,i);return Object.keys(t).forEach(function(e){var n=w[e]||e;"innerHTML"===n||"cssText"===n?a.dangerouslySetInnerHTML={__html:t.innerHTML||t.cssText}:a[n]=t[e]}),r.createElement(e,a)})},O=function(e,t,n){switch(e){case g.TITLE:return{toComponent:function(){var e,n,i,a;return n=t.titleAttributes,(i={key:e=t.title})["data-rh"]=!0,a=_(n,i),[r.createElement(g.TITLE,a,e)]},toString:function(){var r,i,a,o;return r=t.title,i=t.titleAttributes,a=N(i),o=C(r),a?"<"+e+' data-rh="true" '+a+">"+T(o,n)+"":"<"+e+' data-rh="true">'+T(o,n)+""}};case"bodyAttributes":case"htmlAttributes":return{toComponent:function(){return _(t)},toString:function(){return N(t)}};default:return{toComponent:function(){return B(e,t)},toString:function(){return t.reduce(function(t,r){var i=Object.keys(r).filter(function(e){return"innerHTML"!==e&&"cssText"!==e}).reduce(function(e,t){var i=void 0===r[t]?t:t+'="'+T(r[t],n)+'"';return e?e+" "+i:i},""),a=r.innerHTML||r.cssText||"",o=-1===S.indexOf(e);return t+"<"+e+' data-rh="true" '+i+(o?"/>":">"+a+"")},"")}}}},R=function(e){var t=e.baseTag,n=e.bodyAttributes,r=e.encode,i=e.htmlAttributes,a=e.noscriptTags,o=e.styleTags,s=e.title,l=e.titleAttributes,c=e.linkTags,d=e.metaTags,u=e.scriptTags,h={toComponent:function(){},toString:function(){return""}};if(e.prioritizeSeoTags){var p,x,m,b,w,k,I=(p=e.linkTags,x=e.scriptTags,m=e.encode,b=j(e.metaTags,y),w=j(p,f),k=j(x,v),{priorityMethods:{toComponent:function(){return[].concat(B(g.META,b.priority),B(g.LINK,w.priority),B(g.SCRIPT,k.priority))},toString:function(){return O(g.META,b.priority,m)+" "+O(g.LINK,w.priority,m)+" "+O(g.SCRIPT,k.priority,m)}},metaTags:b.default,linkTags:w.default,scriptTags:k.default});h=I.priorityMethods,c=I.linkTags,d=I.metaTags,u=I.scriptTags}return{priority:h,base:O(g.BASE,t,r),bodyAttributes:O("bodyAttributes",n,r),htmlAttributes:O("htmlAttributes",i,r),link:O(g.LINK,c,r),meta:O(g.META,d,r),noscript:O(g.NOSCRIPT,a,r),script:O(g.SCRIPT,u,r),style:O(g.STYLE,o,r),title:O(g.TITLE,{title:void 0===s?"":s,titleAttributes:l},r)}},q=[],L=function(e,t){var n=this;void 0===t&&(t="undefined"!=typeof document),this.instances=[],this.value={setHelmet:function(e){n.context.helmet=e},helmetInstances:{get:function(){return n.canUseDOM?q:n.instances},add:function(e){(n.canUseDOM?q:n.instances).push(e)},remove:function(e){var t=(n.canUseDOM?q:n.instances).indexOf(e);(n.canUseDOM?q:n.instances).splice(t,1)}}},this.context=e,this.canUseDOM=t,t||(e.helmet=R({baseTag:[],bodyAttributes:{},encodeSpecialCharacters:!0,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],scriptTags:[],styleTags:[],title:"",titleAttributes:{}}))},M=r.createContext({}),z=a().shape({setHelmet:a().func,helmetInstances:a().shape({get:a().func,add:a().func,remove:a().func})}),H="undefined"!=typeof document,$=function(e){function t(n){var r;return(r=e.call(this,n)||this).helmetData=new L(r.props.context,t.canUseDOM),r}return p(t,e),t.prototype.render=function(){return r.createElement(M.Provider,{value:this.helmetData.value},this.props.children)},t}(r.Component);$.canUseDOM=H,$.propTypes={context:a().shape({helmet:a().shape()}),children:a().node.isRequired},$.defaultProps={context:{}},$.displayName="HelmetProvider";var W=function(e,t){var n,r=document.head||document.querySelector(g.HEAD),i=r.querySelectorAll(e+"[data-rh]"),a=[].slice.call(i),o=[];return t&&t.length&&t.forEach(function(t){var r=document.createElement(e);for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&("innerHTML"===i?r.innerHTML=t.innerHTML:"cssText"===i?r.styleSheet?r.styleSheet.cssText=t.cssText:r.appendChild(document.createTextNode(t.cssText)):r.setAttribute(i,void 0===t[i]?"":t[i]));r.setAttribute("data-rh","true"),a.some(function(e,t){return n=t,r.isEqualNode(e)})?a.splice(n,1):o.push(r)}),a.forEach(function(e){return e.parentNode.removeChild(e)}),o.forEach(function(e){return r.appendChild(e)}),{oldTags:a,newTags:o}},K=function(e,t){var n=document.getElementsByTagName(e)[0];if(n){for(var r=n.getAttribute("data-rh"),i=r?r.split(","):[],a=[].concat(i),o=Object.keys(t),s=0;s=0;u-=1)n.removeAttribute(a[u]);i.length===a.length?n.removeAttribute("data-rh"):n.getAttribute("data-rh")!==o.join(",")&&n.setAttribute("data-rh",o.join(","))}},U=function(e,t){var n=e.baseTag,r=e.htmlAttributes,i=e.linkTags,a=e.metaTags,o=e.noscriptTags,s=e.onChangeClientState,l=e.scriptTags,c=e.styleTags,d=e.title,u=e.titleAttributes;K(g.BODY,e.bodyAttributes),K(g.HTML,r),void 0!==d&&document.title!==d&&(document.title=C(d)),K(g.TITLE,u);var h={baseTag:W(g.BASE,n),linkTags:W(g.LINK,i),metaTags:W(g.META,a),noscriptTags:W(g.NOSCRIPT,o),scriptTags:W(g.SCRIPT,l),styleTags:W(g.STYLE,c)},p={},x={};Object.keys(h).forEach(function(e){var t=h[e],n=t.newTags,r=t.oldTags;n.length&&(p[e]=n),r.length&&(x[e]=h[e].oldTags)}),t&&t(),s(e,p,x)},V=null,G=function(e){function t(){for(var t,n=arguments.length,r=Array(n),i=0;i elements are self-closing and can not contain children. Refer to our API for more information.")}},n.flattenArrayTypeChildren=function(e){var t,n=e.child,r=e.arrayTypeChildren;return h({},r,((t={})[n.type]=[].concat(r[n.type]||[],[h({},e.newChildProps,this.mapNestedChildrenToProps(n,e.nestedChildren))]),t))},n.mapObjectTypeChildren=function(e){var t,n,r=e.child,i=e.newProps,a=e.newChildProps,o=e.nestedChildren;switch(r.type){case g.TITLE:return h({},i,((t={})[r.type]=o,t.titleAttributes=h({},a),t));case g.BODY:return h({},i,{bodyAttributes:h({},a)});case g.HTML:return h({},i,{htmlAttributes:h({},a)});default:return h({},i,((n={})[r.type]=h({},a),n))}},n.mapArrayTypeChildrenToProps=function(e,t){var n=h({},t);return Object.keys(e).forEach(function(t){var r;n=h({},n,((r={})[t]=e[t],r))}),n},n.warnOnInvalidChildren=function(e,t){return c()(b.some(function(t){return e.type===t}),"function"==typeof e.type?"You may be attempting to nest components within each other, which is not allowed. Refer to our API for more information.":"Only elements types "+b.join(", ")+" are allowed. Helmet does not support rendering <"+e.type+"> elements. Refer to our API for more information."),c()(!t||"string"==typeof t||Array.isArray(t)&&!t.some(function(e){return"string"!=typeof e}),"Helmet expects a string as a child of <"+e.type+">. Did you forget to wrap your children in braces? ( <"+e.type+">{``} ) Refer to our API for more information."),!0},n.mapChildrenToProps=function(e,t){var n=this,i={};return r.Children.forEach(e,function(e){if(e&&e.props){var r=e.props,a=r.children,o=m(r,Z),s=Object.keys(o).reduce(function(e,t){return e[k[t]||t]=o[t],e},{}),l=e.type;switch("symbol"==typeof l?l=l.toString():n.warnOnInvalidChildren(e,a),l){case g.FRAGMENT:t=n.mapChildrenToProps(a,t);break;case g.LINK:case g.META:case g.NOSCRIPT:case g.SCRIPT:case g.STYLE:i=n.flattenArrayTypeChildren({child:e,arrayTypeChildren:i,newChildProps:s,nestedChildren:a});break;default:t=n.mapObjectTypeChildren({child:e,newProps:t,newChildProps:s,nestedChildren:a})}}}),this.mapArrayTypeChildrenToProps(i,t)},n.render=function(){var e=this.props,t=e.children,n=m(e,J),i=h({},n),a=n.helmetData;return t&&(i=this.mapChildrenToProps(t,i)),!a||a instanceof L||(a=new L(a.context,a.instances)),a?r.createElement(G,h({},i,{context:a.value,helmetData:void 0})):r.createElement(M.Consumer,null,function(e){return r.createElement(G,h({},i,{context:e}))})},t}(r.Component);Q.propTypes={base:a().object,bodyAttributes:a().object,children:a().oneOfType([a().arrayOf(a().node),a().node]),defaultTitle:a().string,defer:a().bool,encodeSpecialCharacters:a().bool,htmlAttributes:a().object,link:a().arrayOf(a().object),meta:a().arrayOf(a().object),noscript:a().arrayOf(a().object),onChangeClientState:a().func,script:a().arrayOf(a().object),style:a().arrayOf(a().object),title:a().string,titleAttributes:a().object,titleTemplate:a().string,prioritizeSeoTags:a().bool,helmetData:a().object},Q.defaultProps={defer:!0,encodeSpecialCharacters:!0,prioritizeSeoTags:!1},Q.displayName="Helmet"},3040:function(e,t,n){"use strict";t.lazyWithPreload=void 0;var r=n(7294);t.lazyWithPreload=function(e){var t,n,i=(0,r.lazy)(e),a=(0,r.forwardRef)(function(e,n){var a=(0,r.useRef)(null!=t?t:i);return(0,r.createElement)(a.current,Object.assign(n?{ref:n}:{},e))});return a.preload=function(){return n||(n=e().then(function(e){return t=e.default})),n},a}},1318:function(e,t,n){"use strict";var r=n(5751);t.default=void 0,t.default=r(n(6979)).default},9031:function(e,t,n){"use strict";var r=n(5751);t.default=void 0,t.default=r(n(3336)).default},2041:function(e,t,n){"use strict";var r=n(5751);t.default=void 0,t.default=r(n(6155)).default},7852:function(e,t,n){"use strict";var r=n(5751);t.default=void 0,t.default=r(n(5950)).default},7893:function(e,t,n){"use strict";var r=n(5751);t.default=void 0,t.default=r(n(7041)).default},2521:function(e,t,n){"use strict";var r=n(5751);t.default=void 0,t.default=r(n(4979)).default},1215:function(e,t,n){"use strict";var r,i,a="object"==typeof globalThis?globalThis:"object"==typeof self?self:"object"==typeof window?window:"object"==typeof n.g?n.g:{},o=(i=(r="Prism"in a)?a.Prism:void 0,function(){r?a.Prism=i:delete a.Prism,r=void 0,i=void 0});a.Prism={manual:!0,disableWorkerMessageHandler:!0};var s=n(4862),l=n(2921),c=n(9216),d=n(2717),u=n(2049),h=n(9726),p=n(6155);o();var x={}.hasOwnProperty;function m(){}m.prototype=c;var g=new m;function f(e){if("function"!=typeof e||!e.displayName)throw Error("Expected `function` for `grammar`, got `"+e+"`");void 0===g.languages[e.displayName]&&e(g)}e.exports=g,g.highlight=function(e,t){var n,r=c.highlight;if("string"!=typeof e)throw Error("Expected `string` for `value`, got `"+e+"`");if("Object"===g.util.type(t))n=t,t=null;else{if("string"!=typeof t)throw Error("Expected `string` for `name`, got `"+t+"`");if(x.call(g.languages,t))n=g.languages[t];else throw Error("Unknown language: `"+t+"` is not registered")}return r.call(this,e,n,t)},g.register=f,g.alias=function(e,t){var n,r,i,a,o=g.languages,s=e;for(n in t&&((s={})[e]=t),s)for(i=(r="string"==typeof(r=s[n])?[r]:r).length,a=-1;++a>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:r},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:r},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:r.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:r.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var i=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],a=r.variable[1].inside,o=0;o]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}}e.exports=t,t.displayName="clike",t.aliases=[]},2049:function(e){"use strict";function t(e){var t,n;t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/,e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css,(n=e.languages.markup)&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}e.exports=t,t.displayName="css",t.aliases=[]},3336:function(e){"use strict";function t(e){var t;e.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]},Object.keys(t={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"}).forEach(function(n){var r=t[n],i=[];/^\w+$/.test(n)||i.push(/\w+/.exec(n)[0]),"diff"===n&&i.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+r+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:i,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(n)[0]}}}}),Object.defineProperty(e.languages.diff,"PREFIXES",{value:t})}e.exports=t,t.displayName="diff",t.aliases=[]},6155:function(e){"use strict";function t(e){e.languages.javascript=e.languages.extend("clike",{"class-name":[e.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+(/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source)+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),e.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,e.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:e.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:e.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:e.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:e.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:e.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),e.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:e.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),e.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),e.languages.markup&&(e.languages.markup.tag.addInlined("script","javascript"),e.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),e.languages.js=e.languages.javascript}e.exports=t,t.displayName="javascript",t.aliases=["js"]},5950:function(e){"use strict";function t(e){e.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},e.languages.webmanifest=e.languages.json}e.exports=t,t.displayName="json",t.aliases=["webmanifest"]},6412:function(e){"use strict";function t(e){!function(e){var t=e.util.clone(e.languages.javascript),n=/(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source,r=/(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source,i=/(?:\{*\.{3}(?:[^{}]|)*\})/.source;function a(e,t){return RegExp(e=e.replace(//g,function(){return n}).replace(//g,function(){return r}).replace(//g,function(){return i}),t)}i=a(i).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=a(/<\/?(?:[\w.:-]+(?:+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|))?|))**\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:a(//.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:a(/=/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var o=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(o).join(""):""},s=function(t){for(var n=[],r=0;r0&&n[n.length-1].tagName===o(i.content[0].content[1])&&n.pop():"/>"===i.content[i.content.length-1].content||n.push({tagName:o(i.content[0].content[1]),openedBraces:0}):n.length>0&&"punctuation"===i.type&&"{"===i.content?n[n.length-1].openedBraces++:n.length>0&&n[n.length-1].openedBraces>0&&"punctuation"===i.type&&"}"===i.content?n[n.length-1].openedBraces--:a=!0),(a||"string"==typeof i)&&n.length>0&&0===n[n.length-1].openedBraces){var l=o(i);r0&&("string"==typeof t[r-1]||"plain-text"===t[r-1].type)&&(l=o(t[r-1])+l,t.splice(r-1,1),r--),t[r]=new e.Token("plain-text",l,null,l)}i.content&&"string"!=typeof i.content&&s(i.content)}};e.hooks.add("after-tokenize",function(e){("jsx"===e.language||"tsx"===e.language)&&s(e.tokens)})}(e)}e.exports=t,t.displayName="jsx",t.aliases=[]},2717:function(e){"use strict";function t(e){e.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},e.languages.markup.tag.inside["attr-value"].inside.entity=e.languages.markup.entity,e.languages.markup.doctype.inside["internal-subset"].inside=e.languages.markup,e.hooks.add("wrap",function(e){"entity"===e.type&&(e.attributes.title=e.content.value.replace(/&/,"&"))}),Object.defineProperty(e.languages.markup.tag,"addInlined",{value:function(t,n){var r={};r["language-"+n]={pattern:/(^$)/i,lookbehind:!0,inside:e.languages[n]},r.cdata=/^$/i;var i={"included-cdata":{pattern://i,inside:r}};i["language-"+n]={pattern:/[\s\S]+/,inside:e.languages[n]};var a={};a[t]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,function(){return t}),"i"),lookbehind:!0,greedy:!0,inside:i},e.languages.insertBefore("markup","cdata",a)}}),Object.defineProperty(e.languages.markup.tag,"addAttribute",{value:function(t,n){e.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+t+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[n,"language-"+n],inside:e.languages[n]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),e.languages.html=e.languages.markup,e.languages.mathml=e.languages.markup,e.languages.svg=e.languages.markup,e.languages.xml=e.languages.extend("markup",{}),e.languages.ssml=e.languages.xml,e.languages.atom=e.languages.xml,e.languages.rss=e.languages.xml}e.exports=t,t.displayName="markup",t.aliases=["html","mathml","svg","xml","ssml","atom","rss"]},7041:function(e,t,n){"use strict";var r=n(6412),i=n(4979);function a(e){var t,n;e.register(r),e.register(i),t=e.util.clone(e.languages.typescript),e.languages.tsx=e.languages.extend("jsx",t),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"],(n=e.languages.tsx.tag).pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+n.pattern.source+")",n.pattern.flags),n.lookbehind=!0}e.exports=a,a.displayName="tsx",a.aliases=[]},4979:function(e){"use strict";function t(e){var t;e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"],t=e.languages.extend("typescript",{}),delete t["class-name"],e.languages.typescript["class-name"].inside=t,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t}}}}),e.languages.ts=e.languages.typescript}e.exports=t,t.displayName="typescript",t.aliases=["ts"]},166:function(e){"use strict";e.exports=function(e){var t="string"==typeof e?e.charCodeAt(0):e;return t>=97&&t<=122||t>=65&&t<=90}},2783:function(e,t,n){"use strict";var r=n(166),i=n(1250);e.exports=function(e){return r(e)||i(e)}},1250:function(e){"use strict";e.exports=function(e){var t="string"==typeof e?e.charCodeAt(0):e;return t>=48&&t<=57}},9956:function(e){"use strict";e.exports=function(e){var t="string"==typeof e?e.charCodeAt(0):e;return t>=97&&t<=102||t>=65&&t<=70||t>=48&&t<=57}},1e3:function(e){"use strict";var t;e.exports=function(e){var n,r="&"+e+";";return(t=t||document.createElement("i")).innerHTML=r,(59!==(n=t.textContent).charCodeAt(n.length-1)||"semi"===e)&&n!==r&&n}},2921:function(e,t,n){"use strict";var r=n(7854),i=n(1636),a=n(1250),o=n(9956),s=n(2783),l=n(1e3);e.exports=function(e,t){var n,a,o={};for(a in t||(t={}),h)n=t[a],o[a]=null==n?h[a]:n;return(o.position.indent||o.position.start)&&(o.indent=o.position.indent||[],o.position=o.position.start),function(e,t){var n,a,o,h,y,b,w,k,I,D,E,F,A,C,j,P,S,T,N,_,B,O=t.additional,R=t.nonTerminated,q=t.text,L=t.reference,M=t.warning,z=t.textContext,H=t.referenceContext,$=t.warningContext,W=t.position,K=t.indent||[],U=e.length,V=0,G=-1,Z=W.column||1,J=W.line||1,Q="",Y=[];for("string"==typeof O&&(O=O.charCodeAt(0)),T=X(),D=M?function(e,t){var n=X();n.column+=t,n.offset+=t,M.call($,v[e],n,e)}:u,V--,U++;++V=55296&&n<=57343||n>1114111?(D(7,_),k=d(65533)):k in i?(D(6,_),k=i[k]):(F="",((a=k)>=1&&a<=8||11===a||a>=13&&a<=31||a>=127&&a<=159||a>=64976&&a<=65007||(65535&a)==65535||(65535&a)==65534)&&D(6,_),k>65535&&(k-=65536,F+=d(k>>>10|55296),k=56320|1023&k),k=F+d(k))):P!==p&&D(4,_)}k?(ee(),T=X(),V=B-1,Z+=B-j+1,Y.push(k),N=X(),N.offset++,L&&L.call(H,k,{start:T,end:N},e.slice(j-1,B)),T=N):(b=e.slice(j-1,B),Q+=b,Z+=b.length,V=B-1)}else 10===w&&(J++,G++,Z=0),w==w?(Q+=d(w),Z++):ee();return Y.join("");function X(){return{line:J,column:Z,offset:V+(W.offset||0)}}function ee(){Q&&(Y.push(Q),q&&q.call(z,Q,{start:T,end:X()}),Q="")}}(e,o)};var c={}.hasOwnProperty,d=String.fromCharCode,u=Function.prototype,h={warning:null,reference:null,text:null,warningContext:null,referenceContext:null,textContext:null,position:{},additional:null,attribute:!1,nonTerminated:!0},p="named",x="hexadecimal",m="decimal",g={};g[x]=16,g[m]=10;var f={};f[p]=s,f[m]=a,f[x]=o;var v={};v[1]="Named character references must be terminated by a semicolon",v[2]="Numeric character references must be terminated by a semicolon",v[3]="Named character references cannot be empty",v[4]="Numeric character references cannot be empty",v[5]="Named character references must be known",v[6]="Numeric character references cannot be disallowed",v[7]="Numeric character references cannot be outside the permissible Unicode range"},9216:function(e,t,n){var r=function(e){var t=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,n=0,r={},i={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(t){return t instanceof a?new a(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/=d.reach));k+=w.value.length,w=w.next){var I,D=w.value;if(n.length>t.length)return;if(!(D instanceof a)){var E=1;if(f){if(!(I=o(b,k,t,g))||I.index>=t.length)break;var F=I.index,A=I.index+I[0].length,C=k;for(C+=w.value.length;F>=C;)C+=(w=w.next).value.length;if(C-=w.value.length,k=C,w.value instanceof a)continue;for(var j=w;j!==n.tail&&(Cd.reach&&(d.reach=N);var _=w.prev;if(S&&(_=l(n,_,S),k+=S.length),function(e,t,n){for(var r=t.next,i=0;i1){var B={cause:u+","+p,reach:N};e(t,n,r,w.prev,k,B),d&&B.reach>d.reach&&(d.reach=B.reach)}}}}}}(e,c,t,c.head,0),function(e){for(var t=[],n=e.head.next;n!==e.tail;)t.push(n.value),n=n.next;return t}(c)},hooks:{all:{},add:function(e,t){var n=i.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=i.hooks.all[e];if(n&&n.length)for(var r,a=0;r=n[a++];)r(t)}},Token:a};function a(e,t,n,r){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length}function o(e,t,n,r){e.lastIndex=t;var i=e.exec(n);if(i&&r&&i[1]){var a=i[1].length;i.index+=a,i[0]=i[0].slice(a)}return i}function s(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function l(e,t,n){var r=t.next,i={value:n,prev:t,next:r};return t.next=i,r.prev=i,e.length++,i}if(e.Prism=i,a.stringify=function e(t,n){if("string"==typeof t)return t;if(Array.isArray(t)){var r="";return t.forEach(function(t){r+=e(t,n)}),r}var a={type:t.type,content:e(t.content,n),tag:"span",classes:["token",t.type],attributes:{},language:n},o=t.alias;o&&(Array.isArray(o)?Array.prototype.push.apply(a.classes,o):a.classes.push(o)),i.hooks.run("wrap",a);var s="";for(var l in a.attributes)s+=" "+l+'="'+(a.attributes[l]||"").replace(/"/g,""")+'"';return"<"+a.tag+' class="'+a.classes.join(" ")+'"'+s+">"+a.content+""},!e.document)return e.addEventListener&&(i.disableWorkerMessageHandler||e.addEventListener("message",function(t){var n=JSON.parse(t.data),r=n.language,a=n.code,o=n.immediateClose;e.postMessage(i.highlight(a,i.languages[r],r)),o&&e.close()},!1)),i;var c=i.util.currentScript();function d(){i.manual||i.highlightAll()}if(c&&(i.filename=c.src,c.hasAttribute("data-manual")&&(i.manual=!0)),!i.manual){var u=document.readyState;"loading"===u||"interactive"===u&&c&&c.defer?document.addEventListener("DOMContentLoaded",d):window.requestAnimationFrame?window.requestAnimationFrame(d):window.setTimeout(d,16)}return i}("undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{});e.exports&&(e.exports=r),void 0!==n.g&&(n.g.Prism=r)},6774:function(e){e.exports=function(e,t,n,r){var i=n?n.call(r,e,t):void 0;if(void 0!==i)return!!i;if(e===t)return!0;if("object"!=typeof e||!e||"object"!=typeof t||!t)return!1;var a=Object.keys(e),o=Object.keys(t);if(a.length!==o.length)return!1;for(var s=Object.prototype.hasOwnProperty.bind(t),l=0;lr});let r={title:"React Native Testing Library",description:"Helps you to write better tests with less effort.",icon:"/img/owl.png",route:{cleanUrls:!0},themeConfig:{enableContentAnimation:!0,enableScrollToTop:!0,outlineTitle:"Contents",footer:{message:"Copyright \xa9 2026 Callstack Open Source"},socialLinks:[{icon:"github",mode:"link",content:"https://github.com/callstack/react-native-testing-library"}],locales:[],nav:{"12.x":[{text:"Docs",link:"/12.x/docs/start/intro",activeMatch:"^/docs/"},{text:"Cookbook",link:"/12.x/cookbook/",activeMatch:"^/cookbook/"},{text:"Examples",link:"https://github.com/callstack/react-native-testing-library/tree/main/examples"}],"13.x":[{text:"Docs",link:"/docs/start/intro",activeMatch:"^/docs/"},{text:"Cookbook",link:"/cookbook/",activeMatch:"^/cookbook/"},{text:"Examples",link:"https://github.com/callstack/react-native-testing-library/tree/main/examples"}],"14.x":[{text:"Docs",link:"/14.x/docs/start/intro",activeMatch:"^/docs/"},{text:"Cookbook",link:"/14.x/cookbook/",activeMatch:"^/cookbook/"},{text:"Examples",link:"https://github.com/callstack/react-native-testing-library/tree/main/examples"}]},sidebar:{"/12.x/cookbook":[{text:"Introduction",link:"/12.x/cookbook/index",_fileKey:"12.x/cookbook/index"},{text:"Basic Recipes",collapsible:!0,collapsed:!1,items:[{text:"Async tests",link:"/12.x/cookbook/basics/async-tests",_fileKey:"12.x/cookbook/basics/async-tests"},{text:"Custom `render` function",link:"/12.x/cookbook/basics/custom-render",_fileKey:"12.x/cookbook/basics/custom-render"}],link:"",_fileKey:""},{text:"Advanced Recipes",collapsible:!0,collapsed:!1,items:[{text:"Network Requests",link:"/12.x/cookbook/advanced/network-requests",_fileKey:"12.x/cookbook/advanced/network-requests"}],link:"",_fileKey:""},{text:"State Management Recipes",collapsible:!0,collapsed:!1,items:[{text:"Jotai",link:"/12.x/cookbook/state-management/jotai",_fileKey:"12.x/cookbook/state-management/jotai"}],link:"",_fileKey:""}],"/12.x/docs":[{text:"Getting started",collapsible:!0,collapsed:!1,items:[{text:"Introduction",link:"/12.x/docs/start/intro",_fileKey:"12.x/docs/start/intro"},{text:"Quick Start",link:"/12.x/docs/start/quick-start",_fileKey:"12.x/docs/start/quick-start"}],link:"",_fileKey:""},{text:"API reference",collapsible:!0,collapsed:!1,items:[{text:"Render function",link:"/12.x/docs/api/render",_fileKey:"12.x/docs/api/render"},{text:"Screen object",link:"/12.x/docs/api/screen",_fileKey:"12.x/docs/api/screen"},{text:"Queries",link:"/12.x/docs/api/queries",_fileKey:"12.x/docs/api/queries"},{text:"Jest matchers",link:"/12.x/docs/api/jest-matchers",_fileKey:"12.x/docs/api/jest-matchers"},{text:"Triggering events",collapsible:!0,collapsed:!1,items:[{text:"User Event",link:"/12.x/docs/api/events/user-event",_fileKey:"12.x/docs/api/events/user-event"},{text:"Fire Event",link:"/12.x/docs/api/events/fire-event",_fileKey:"12.x/docs/api/events/fire-event"}],link:"",_fileKey:""},{text:"Miscellaneous",collapsible:!0,collapsed:!1,items:[{text:"Render Hook function",link:"/12.x/docs/api/misc/render-hook",_fileKey:"12.x/docs/api/misc/render-hook"},{text:"Async utilities",link:"/12.x/docs/api/misc/async",_fileKey:"12.x/docs/api/misc/async"},{text:"Configuration",link:"/12.x/docs/api/misc/config",_fileKey:"12.x/docs/api/misc/config"},{text:"Accessibility",link:"/12.x/docs/api/misc/accessibility",_fileKey:"12.x/docs/api/misc/accessibility"},{text:"Other helpers",link:"/12.x/docs/api/misc/other",_fileKey:"12.x/docs/api/misc/other"}],link:"",_fileKey:""}],link:"/12.x/docs/api",_fileKey:"12.x/docs/api"},{text:"Guides",collapsible:!0,collapsed:!1,items:[{text:"How should I query?",link:"/12.x/docs/guides/how-to-query",_fileKey:"12.x/docs/guides/how-to-query"},{text:"Troubleshooting",link:"/12.x/docs/guides/troubleshooting",_fileKey:"12.x/docs/guides/troubleshooting"},{text:"FAQ",link:"/12.x/docs/guides/faq",_fileKey:"12.x/docs/guides/faq"},{text:"Community resources",link:"/12.x/docs/guides/community-resources",_fileKey:"12.x/docs/guides/community-resources"}],link:"",_fileKey:""},{text:"Advanced Guides",collapsible:!0,collapsed:!1,items:[{text:"Testing environment",link:"/12.x/docs/advanced/testing-env",_fileKey:"12.x/docs/advanced/testing-env"},{text:"Understanding `act` function",link:"/12.x/docs/advanced/understanding-act",_fileKey:"12.x/docs/advanced/understanding-act"}],link:"",_fileKey:""},{text:"Migration Guides",collapsible:!0,collapsed:!0,items:[{text:"Migration to 12.x",link:"/12.x/docs/migration/v12",_fileKey:"12.x/docs/migration/v12"},{text:"Migration to built-in Jest matchers",link:"/12.x/docs/migration/jest-matchers",_fileKey:"12.x/docs/migration/jest-matchers"},{text:"Previous versions",collapsible:!0,collapsed:!0,items:[{text:"Migration to 11.x",link:"/12.x/docs/migration/previous/v11",_fileKey:"12.x/docs/migration/previous/v11"},{text:"Migration to 9.x",link:"/12.x/docs/migration/previous/v9",_fileKey:"12.x/docs/migration/previous/v9"},{text:"Migration to 7.x",link:"/12.x/docs/migration/previous/v7",_fileKey:"12.x/docs/migration/previous/v7"},{text:"Migration to 2.x",link:"/12.x/docs/migration/previous/v2",_fileKey:"12.x/docs/migration/previous/v2"}],link:"",_fileKey:""}],link:"",_fileKey:""}],"/cookbook":[{text:"Introduction",link:"/cookbook/index",_fileKey:"13.x/cookbook/index"},{text:"Basic Recipes",collapsible:!0,collapsed:!1,items:[{text:"Async tests",link:"/cookbook/basics/async-tests",_fileKey:"13.x/cookbook/basics/async-tests"},{text:"Custom `render` function",link:"/cookbook/basics/custom-render",_fileKey:"13.x/cookbook/basics/custom-render"}],link:"",_fileKey:""},{text:"Advanced Recipes",collapsible:!0,collapsed:!1,items:[{text:"Network Requests",link:"/cookbook/advanced/network-requests",_fileKey:"13.x/cookbook/advanced/network-requests"}],link:"",_fileKey:""},{text:"State Management Recipes",collapsible:!0,collapsed:!1,items:[{text:"Jotai",link:"/cookbook/state-management/jotai",_fileKey:"13.x/cookbook/state-management/jotai"}],link:"",_fileKey:""}],"/docs":[{text:"Getting started",collapsible:!0,collapsed:!1,items:[{text:"Introduction",link:"/docs/start/intro",_fileKey:"13.x/docs/start/intro"},{text:"Quick Start",link:"/docs/start/quick-start",_fileKey:"13.x/docs/start/quick-start"}],link:"",_fileKey:""},{text:"API reference",collapsible:!0,collapsed:!1,items:[{text:"Render function",link:"/docs/api/render",_fileKey:"13.x/docs/api/render"},{text:"Screen object",link:"/docs/api/screen",_fileKey:"13.x/docs/api/screen"},{text:"Queries",link:"/docs/api/queries",_fileKey:"13.x/docs/api/queries"},{text:"Jest matchers",link:"/docs/api/jest-matchers",_fileKey:"13.x/docs/api/jest-matchers"},{text:"Triggering events",collapsible:!0,collapsed:!1,items:[{text:"User Event",link:"/docs/api/events/user-event",_fileKey:"13.x/docs/api/events/user-event"},{text:"Fire Event",link:"/docs/api/events/fire-event",_fileKey:"13.x/docs/api/events/fire-event"}],link:"",_fileKey:""},{text:"Miscellaneous",collapsible:!0,collapsed:!1,items:[{text:"Render Hook function",link:"/docs/api/misc/render-hook",_fileKey:"13.x/docs/api/misc/render-hook"},{text:"Async utilities",link:"/docs/api/misc/async",_fileKey:"13.x/docs/api/misc/async"},{text:"Configuration",link:"/docs/api/misc/config",_fileKey:"13.x/docs/api/misc/config"},{text:"Accessibility",link:"/docs/api/misc/accessibility",_fileKey:"13.x/docs/api/misc/accessibility"},{text:"Other helpers",link:"/docs/api/misc/other",_fileKey:"13.x/docs/api/misc/other"}],link:"",_fileKey:""}],link:"/docs/api",_fileKey:"13.x/docs/api"},{text:"Guides",collapsible:!0,collapsed:!1,items:[{text:"How should I query?",link:"/docs/guides/how-to-query",_fileKey:"13.x/docs/guides/how-to-query"},{text:"React 19 & Suspense Support",link:"/docs/guides/react-19",_fileKey:"13.x/docs/guides/react-19"},{text:"Troubleshooting",link:"/docs/guides/troubleshooting",_fileKey:"13.x/docs/guides/troubleshooting"},{text:"FAQ",link:"/docs/guides/faq",_fileKey:"13.x/docs/guides/faq"},{text:"Community resources",link:"/docs/guides/community-resources",_fileKey:"13.x/docs/guides/community-resources"}],link:"",_fileKey:""},{text:"Advanced Guides",collapsible:!0,collapsed:!1,items:[{text:"Testing environment",link:"/docs/advanced/testing-env",_fileKey:"13.x/docs/advanced/testing-env"},{text:"Understanding `act` function",link:"/docs/advanced/understanding-act",_fileKey:"13.x/docs/advanced/understanding-act"},{text:"Third-Party Library Integration",link:"/docs/advanced/third-party-integration",_fileKey:"13.x/docs/advanced/third-party-integration"}],link:"",_fileKey:""},{text:"Migration Guides",collapsible:!0,collapsed:!0,items:[{text:"Migration to 13.x",link:"/docs/migration/v13",_fileKey:"13.x/docs/migration/v13"},{text:"Migration to built-in Jest matchers",link:"/docs/migration/jest-matchers",_fileKey:"13.x/docs/migration/jest-matchers"},{text:"Previous versions",collapsible:!0,collapsed:!0,items:[{text:"Migration to 12.x",link:"/docs/migration/previous/v12",_fileKey:"13.x/docs/migration/previous/v12"},{text:"Migration to 11.x",link:"/docs/migration/previous/v11",_fileKey:"13.x/docs/migration/previous/v11"},{text:"Migration to 9.x",link:"/docs/migration/previous/v9",_fileKey:"13.x/docs/migration/previous/v9"},{text:"Migration to 7.x",link:"/docs/migration/previous/v7",_fileKey:"13.x/docs/migration/previous/v7"},{text:"Migration to 2.x",link:"/docs/migration/previous/v2",_fileKey:"13.x/docs/migration/previous/v2"}],link:"",_fileKey:""}],link:"",_fileKey:""}],"/14.x/cookbook":[{text:"Introduction",link:"/14.x/cookbook/index",_fileKey:"14.x/cookbook/index"},{text:"Basic Recipes",collapsible:!0,collapsed:!1,items:[{text:"Async tests",link:"/14.x/cookbook/basics/async-tests",_fileKey:"14.x/cookbook/basics/async-tests"},{text:"Custom `render` function",link:"/14.x/cookbook/basics/custom-render",_fileKey:"14.x/cookbook/basics/custom-render"}],link:"",_fileKey:""},{text:"Advanced Recipes",collapsible:!0,collapsed:!1,items:[{text:"Network Requests",link:"/14.x/cookbook/advanced/network-requests",_fileKey:"14.x/cookbook/advanced/network-requests"}],link:"",_fileKey:""},{text:"State Management Recipes",collapsible:!0,collapsed:!1,items:[{text:"Jotai",link:"/14.x/cookbook/state-management/jotai",_fileKey:"14.x/cookbook/state-management/jotai"}],link:"",_fileKey:""}],"/14.x/docs":[{text:"Getting started",collapsible:!0,collapsed:!1,items:[{text:"Introduction",link:"/14.x/docs/start/intro",_fileKey:"14.x/docs/start/intro"},{text:"Quick Start",link:"/14.x/docs/start/quick-start",_fileKey:"14.x/docs/start/quick-start"}],link:"",_fileKey:""},{text:"API reference",collapsible:!0,collapsed:!1,items:[{text:"Render function",link:"/14.x/docs/api/render",_fileKey:"14.x/docs/api/render"},{text:"Screen object",link:"/14.x/docs/api/screen",_fileKey:"14.x/docs/api/screen"},{text:"Queries",link:"/14.x/docs/api/queries",_fileKey:"14.x/docs/api/queries"},{text:"Jest matchers",link:"/14.x/docs/api/jest-matchers",_fileKey:"14.x/docs/api/jest-matchers"},{text:"Triggering events",collapsible:!0,collapsed:!1,items:[{text:"User Event",link:"/14.x/docs/api/events/user-event",_fileKey:"14.x/docs/api/events/user-event"},{text:"Fire Event",link:"/14.x/docs/api/events/fire-event",_fileKey:"14.x/docs/api/events/fire-event"}],link:"",_fileKey:""},{text:"Miscellaneous",collapsible:!0,collapsed:!1,items:[{text:"Render Hook function",link:"/14.x/docs/api/misc/render-hook",_fileKey:"14.x/docs/api/misc/render-hook"},{text:"Async utilities",link:"/14.x/docs/api/misc/async",_fileKey:"14.x/docs/api/misc/async"},{text:"Configuration",link:"/14.x/docs/api/misc/config",_fileKey:"14.x/docs/api/misc/config"},{text:"Accessibility",link:"/14.x/docs/api/misc/accessibility",_fileKey:"14.x/docs/api/misc/accessibility"},{text:"Other helpers",link:"/14.x/docs/api/misc/other",_fileKey:"14.x/docs/api/misc/other"}],link:"",_fileKey:""}],link:"/14.x/docs/api",_fileKey:"14.x/docs/api"},{text:"Guides",collapsible:!0,collapsed:!1,items:[{text:"How should I query?",link:"/14.x/docs/guides/how-to-query",_fileKey:"14.x/docs/guides/how-to-query"},{text:"React 19 & Suspense Support",link:"/14.x/docs/guides/react-19",_fileKey:"14.x/docs/guides/react-19"},{text:"Troubleshooting",link:"/14.x/docs/guides/troubleshooting",_fileKey:"14.x/docs/guides/troubleshooting"},{text:"FAQ",link:"/14.x/docs/guides/faq",_fileKey:"14.x/docs/guides/faq"},{text:"Community resources",link:"/14.x/docs/guides/community-resources",_fileKey:"14.x/docs/guides/community-resources"}],link:"",_fileKey:""},{text:"Advanced Guides",collapsible:!0,collapsed:!1,items:[{text:"Testing environment",link:"/14.x/docs/advanced/testing-env",_fileKey:"14.x/docs/advanced/testing-env"},{text:"Understanding `act` function",link:"/14.x/docs/advanced/understanding-act",_fileKey:"14.x/docs/advanced/understanding-act"},{text:"Third-Party Library Integration",link:"/14.x/docs/advanced/third-party-integration",_fileKey:"14.x/docs/advanced/third-party-integration"}],link:"",_fileKey:""},{text:"Migration Guides",collapsible:!0,collapsed:!0,items:[{text:"Migration to 14.x",link:"/14.x/docs/migration/v14",_fileKey:"14.x/docs/migration/v14"},{text:"Migration to 13.x",link:"/14.x/docs/migration/v13",_fileKey:"14.x/docs/migration/v13"},{text:"Migration to built-in Jest matchers",link:"/14.x/docs/migration/jest-matchers",_fileKey:"14.x/docs/migration/jest-matchers"},{text:"Previous versions",collapsible:!0,collapsed:!0,items:[{text:"Migration to 12.x",link:"/14.x/docs/migration/previous/v12",_fileKey:"14.x/docs/migration/previous/v12"},{text:"Migration to 11.x",link:"/14.x/docs/migration/previous/v11",_fileKey:"14.x/docs/migration/previous/v11"},{text:"Migration to 9.x",link:"/14.x/docs/migration/previous/v9",_fileKey:"14.x/docs/migration/previous/v9"},{text:"Migration to 7.x",link:"/14.x/docs/migration/previous/v7",_fileKey:"14.x/docs/migration/previous/v7"},{text:"Migration to 2.x",link:"/14.x/docs/migration/previous/v2",_fileKey:"14.x/docs/migration/previous/v2"}],link:"",_fileKey:""}],link:"",_fileKey:""}]}},base:"/react-native-testing-library/",lang:"",locales:[],logo:"/img/owl.png",logoText:"React Native Testing Library",ssg:!0,multiVersion:{default:"13.x",versions:["12.x","13.x","14.x"]},search:{versioned:!0},pages:[{title:"Network Requests",routePath:"/react-native-testing-library/12.x/cookbook/advanced/network-requests",lang:"",toc:[{text:"Introduction",id:"introduction",depth:2,charIndex:3},{text:"Phonebook Example",id:"phonebook-example",depth:2,charIndex:568},{text:"Start testing with a simple test",id:"start-testing-with-a-simple-test",depth:2,charIndex:1294},{text:"Testing error handling",id:"testing-error-handling",depth:2,charIndex:2353},{text:"Global guarding against unwanted API requests",id:"global-guarding-against-unwanted-api-requests",depth:2,charIndex:2920},{text:"Conclusion",id:"conclusion",depth:2,charIndex:3508},{text:"Further Reading and Alternatives",id:"further-reading-and-alternatives",depth:2,charIndex:4130}],frontmatter:{},version:"12.x",_relativePath:"12.x/cookbook/advanced/network-requests.md"},{title:"Async tests",routePath:"/react-native-testing-library/12.x/cookbook/basics/async-tests",lang:"",toc:[{text:"Summary",id:"summary",depth:2,charIndex:3},{text:"Example",id:"example",depth:3,charIndex:911},{text:"Async utilities",id:"async-utilities",depth:2,charIndex:1008},{text:"`findBy*` queries",id:"findby-queries",depth:3,charIndex:-1},{text:"Example",id:"example-1",depth:4,charIndex:1622},{text:"`waitFor` function",id:"waitfor-function",depth:3,charIndex:-1},{text:"Example",id:"example-2",depth:4,charIndex:2128},{text:"`waitForElementToBeRemoved` function",id:"waitforelementtoberemoved-function",depth:3,charIndex:-1},{text:"Example",id:"example-3",depth:4,charIndex:2743},{text:"Fake Timers",id:"fake-timers",depth:2,charIndex:2756}],frontmatter:{},version:"12.x",_relativePath:"12.x/cookbook/basics/async-tests.md"},{title:"Custom `render` function",routePath:"/react-native-testing-library/12.x/cookbook/basics/custom-render",lang:"",toc:[{text:"Summary",id:"summary",depth:3,charIndex:25},{text:"Example",id:"example",depth:3,charIndex:318},{text:"More info",id:"more-info",depth:3,charIndex:360},{text:"Additional params",id:"additional-params",depth:4,charIndex:372},{text:"Multiple functions",id:"multiple-functions",depth:4,charIndex:571},{text:"Async function",id:"async-function",depth:4,charIndex:787}],frontmatter:{},version:"12.x",_relativePath:"12.x/cookbook/basics/custom-render.md"},{title:"Introduction",routePath:"/react-native-testing-library/12.x/cookbook/",lang:"",toc:[{text:"What's Inside the Cookbook?",id:"whats-inside-the-cookbook",depth:2,charIndex:434},{text:"What's Next?",id:"whats-next",depth:2,charIndex:1045}],frontmatter:{},version:"12.x",_relativePath:"12.x/cookbook/index.md"},{title:"Jotai",routePath:"/react-native-testing-library/12.x/cookbook/state-management/jotai",lang:"",toc:[{text:"Introduction",id:"introduction",depth:2,charIndex:3},{text:"Task List Example",id:"task-list-example",depth:2,charIndex:337},{text:"Starting with a Simple Test",id:"starting-with-a-simple-test",depth:2,charIndex:566},{text:"Custom Render Function to populate Jotai Atoms with Initial Values",id:"custom-render-function-to-populate-jotai-atoms-with-initial-values",depth:2,charIndex:860},{text:"Testing the `TaskList` Component with initial tasks",id:"testing-the-tasklist-component-with-initial-tasks",depth:2,charIndex:-1},{text:"Modifying atom outside of React components",id:"modifying-atom-outside-of-react-components",depth:2,charIndex:1773},{text:"Testing atom outside of React components",id:"testing-atom-outside-of-react-components",depth:2,charIndex:2022},{text:"Conclusion",id:"conclusion",depth:2,charIndex:2358}],frontmatter:{},version:"12.x",_relativePath:"12.x/cookbook/state-management/jotai.md"},{title:"Testing environment",routePath:"/react-native-testing-library/12.x/docs/advanced/testing-env",lang:"",toc:[{text:"React renderers",id:"react-renderers",depth:2,charIndex:659},{text:"React Test Renderer",id:"react-test-renderer",depth:2,charIndex:1382},{text:"Element tree",id:"element-tree",depth:2,charIndex:2783},{text:"Host and composite components",id:"host-and-composite-components",depth:2,charIndex:3389},{text:"Differentiating between host and composite elements",id:"differentiating-between-host-and-composite-elements",depth:3,charIndex:5113},{text:"Tree nodes",id:"tree-nodes",depth:2,charIndex:5538},{text:"Asserting props",id:"asserting-props",depth:3,charIndex:5854},{text:"Tree navigation",id:"tree-navigation",depth:2,charIndex:6557},{text:"Queries",id:"queries",depth:2,charIndex:7290}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/advanced/testing-env.mdx"},{title:"Understanding `act` function",routePath:"/react-native-testing-library/12.x/docs/advanced/understanding-act",lang:"",toc:[{text:"`act` warnings",id:"act-warnings",depth:2,charIndex:-1},{text:"Synchronous `act`",id:"synchronous-act",depth:2,charIndex:-1},{text:"Responsibility",id:"responsibility",depth:3,charIndex:575},{text:"When to use act",id:"when-to-use-act",depth:3,charIndex:1673},{text:"Implementation",id:"implementation",depth:3,charIndex:2765},{text:"Asynchronous `act`",id:"asynchronous-act",depth:2,charIndex:-1},{text:"Asynchronous code",id:"asynchronous-code",depth:3,charIndex:3756},{text:"Solution with fake timers",id:"solution-with-fake-timers",depth:3,charIndex:4462},{text:"Solution with real timers",id:"solution-with-real-timers",depth:3,charIndex:4772},{text:"Async act warning",id:"async-act-warning",depth:3,charIndex:5594},{text:"References",id:"references",depth:2,charIndex:6029}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/advanced/understanding-act.mdx"},{title:"API Overview",routePath:"/react-native-testing-library/12.x/docs/api",lang:"",toc:[],frontmatter:{uri:"/api"},version:"12.x",_relativePath:"12.x/docs/api.md"},{title:"Fire Event API",routePath:"/react-native-testing-library/12.x/docs/api/events/fire-event",lang:"",toc:[{text:"`fireEvent.press`",id:"fireeventpress",depth:3,charIndex:-1},{text:"`fireEvent.changeText`",id:"fireeventchangetext",depth:3,charIndex:-1},{text:"`fireEvent.scroll`",id:"fireeventscroll",depth:3,charIndex:-1},{text:"On a `ScrollView`",id:"on-a-scrollview",depth:4,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/events/fire-event.mdx"},{title:"User Event interactions",routePath:"/react-native-testing-library/12.x/docs/api/events/user-event",lang:"",toc:[{text:"Comparison with Fire Event API",id:"comparison-with-fire-event-api",depth:2,charIndex:81},{text:"`setup()`",id:"setup",depth:2,charIndex:-1},{text:"Options",id:"options",depth:3,charIndex:-1},{text:"`press()`",id:"press",depth:2,charIndex:-1},{text:"`longPress()`",id:"longpress",depth:2,charIndex:-1},{text:"Options",id:"options-1",depth:3,charIndex:-1},{text:"`type()`",id:"type",depth:2,charIndex:-1},{text:"Options",id:"options-2",depth:3,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events",depth:3,charIndex:-1},{text:"`clear()`",id:"clear",depth:2,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-1",depth:3,charIndex:-1},{text:"`paste()`",id:"paste",depth:2,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-2",depth:3,charIndex:-1},{text:"`scrollTo()`",id:"scroll-to",depth:2,charIndex:-1},{text:"Options",id:"options-3",depth:3,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-3",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/events/user-event.mdx"},{title:"Jest matchers",routePath:"/react-native-testing-library/12.x/docs/api/jest-matchers",lang:"",toc:[{text:"Setup",id:"setup",depth:2,charIndex:250},{text:"Migration from legacy Jest Native matchers.",id:"migration-from-legacy-jest-native-matchers",depth:2,charIndex:563},{text:"Checking element existence",id:"checking-element-existence",depth:2,charIndex:727},{text:"`toBeOnTheScreen()`",id:"tobeonthescreen",depth:3,charIndex:-1},{text:"Element Content",id:"element-content",depth:2,charIndex:981},{text:"`toHaveTextContent()`",id:"tohavetextcontent",depth:3,charIndex:-1},{text:"`toContainElement()`",id:"tocontainelement",depth:3,charIndex:-1},{text:"`toBeEmptyElement()`",id:"tobeemptyelement",depth:3,charIndex:-1},{text:"Checking element state",id:"checking-element-state",depth:2,charIndex:1467},{text:"`toHaveDisplayValue()`",id:"tohavedisplayvalue",depth:3,charIndex:-1},{text:"`toHaveAccessibilityValue()`",id:"tohaveaccessibilityvalue",depth:3,charIndex:-1},{text:"`toBeEnabled()` / `toBeDisabled`",id:"tobeenabled--tobedisabled",depth:3,charIndex:-1},{text:"`toBeSelected()`",id:"tobeselected",depth:3,charIndex:-1},{text:"`toBeChecked()` / `toBePartiallyChecked()`",id:"tobechecked--tobepartiallychecked",depth:3,charIndex:-1},{text:"`toBeExpanded()` / `toBeCollapsed()`",id:"tobeexpanded--tobecollapsed",depth:3,charIndex:-1},{text:"`toBeBusy()`",id:"tobebusy",depth:3,charIndex:-1},{text:"Checking element style",id:"checking-element-style",depth:2,charIndex:4079},{text:"`toBeVisible()`",id:"tobevisible",depth:3,charIndex:-1},{text:"`toHaveStyle()`",id:"tohavestyle",depth:3,charIndex:-1},{text:"Other matchers",id:"other-matchers",depth:2,charIndex:4468},{text:"`toHaveAccessibleName()`",id:"tohaveaccessiblename",depth:3,charIndex:-1},{text:"`toHaveProp()`",id:"tohaveprop",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/jest-matchers.mdx"},{title:"Accessibility",routePath:"/react-native-testing-library/12.x/docs/api/misc/accessibility",lang:"",toc:[{text:"`isHiddenFromAccessibility`",id:"ishiddenfromaccessibility",depth:2,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/misc/accessibility.mdx"},{title:"Async utilities",routePath:"/react-native-testing-library/12.x/docs/api/misc/async",lang:"",toc:[{text:"`findBy*` queries",id:"findby-queries",depth:2,charIndex:-1},{text:"`waitFor`",id:"waitfor",depth:2,charIndex:-1},{text:"Using a React Native version < 0.71 with Jest fake timers",id:"using-a-react-native-version--071-with-jest-fake-timers",depth:3,charIndex:1885},{text:"`waitForElementToBeRemoved`",id:"waitforelementtoberemoved",depth:2,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/misc/async.mdx"},{title:"Configuration",routePath:"/react-native-testing-library/12.x/docs/api/misc/config",lang:"",toc:[{text:"`configure`",id:"configure",depth:2,charIndex:-1},{text:"`asyncUtilTimeout` option",id:"asyncutiltimeout-option",depth:3,charIndex:-1},{text:"`defaultIncludeHiddenElements` option",id:"defaultincludehiddenelements-option",depth:3,charIndex:-1},{text:"`defaultDebugOptions` option",id:"defaultdebugoptions-option",depth:3,charIndex:-1},{text:"`concurrentRoot` option",id:"concurrentroot-option",depth:3,charIndex:-1},{text:"`resetToDefaults()`",id:"resettodefaults",depth:2,charIndex:-1},{text:"Environment variables",id:"environment-variables",depth:2,charIndex:945},{text:"`RNTL_SKIP_AUTO_CLEANUP`",id:"rntl_skip_auto_cleanup",depth:3,charIndex:-1},{text:"`RNTL_SKIP_AUTO_DETECT_FAKE_TIMERS`",id:"rntl_skip_auto_detect_fake_timers",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/misc/config.mdx"},{title:"Other helpers",routePath:"/react-native-testing-library/12.x/docs/api/misc/other",lang:"",toc:[{text:"`within`, `getQueriesForElement`",id:"within-getqueriesforelement",depth:2,charIndex:-1},{text:"`act`",id:"act",depth:2,charIndex:-1},{text:"`cleanup`",id:"cleanup",depth:2,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/misc/other.mdx"},{title:"`renderHook` function",routePath:"/react-native-testing-library/12.x/docs/api/misc/render-hook",lang:"",toc:[{text:"`options`",id:"options",depth:2,charIndex:-1},{text:"`initialProps`",id:"initialprops",depth:3,charIndex:-1},{text:"`wrapper`",id:"wrapper",depth:3,charIndex:-1},{text:"`RenderHookResult`",id:"renderhookresult",depth:2,charIndex:-1},{text:"`result`",id:"result",depth:3,charIndex:-1},{text:"`rerender`",id:"rerender",depth:3,charIndex:-1},{text:"`unmount`",id:"unmount",depth:3,charIndex:-1},{text:"Examples",id:"examples",depth:2,charIndex:1786},{text:"With `initialProps`",id:"with-initialprops",depth:3,charIndex:-1},{text:"With `wrapper`",id:"with-wrapper",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/misc/render-hook.mdx"},{title:"Queries",routePath:"/react-native-testing-library/12.x/docs/api/queries",lang:"",toc:[{text:"Accessing queries",id:"accessing-queries",depth:2,charIndex:226},{text:"Using `screen` object",id:"using-screen-object",depth:3,charIndex:-1},{text:"Using `render` result",id:"using-render-result",depth:3,charIndex:-1},{text:"Query parts",id:"query-parts",depth:2,charIndex:848},{text:"Query variant",id:"query-variant",depth:2,charIndex:1095},{text:"`getBy*` queries",id:"getby-queries",depth:3,charIndex:-1},{text:"`getAllBy*` queries",id:"getallby-queries",depth:3,charIndex:-1},{text:"`queryBy*` queries",id:"queryby-queries",depth:3,charIndex:-1},{text:"`queryAllBy*` queries",id:"queryallby-queries",depth:3,charIndex:-1},{text:"`findBy*` queries",id:"findby-queries",depth:3,charIndex:-1},{text:"`findAllBy*` queries",id:"findallby-queries",depth:3,charIndex:-1},{text:"Query predicates",id:"query-predicates",depth:2,charIndex:3631},{text:"`*ByRole`",id:"byrole",depth:3,charIndex:-1},{text:"Options",id:"options",depth:4,charIndex:-1},{text:"`*ByLabelText`",id:"bylabeltext",depth:3,charIndex:-1},{text:"`*ByPlaceholderText`",id:"byplaceholdertext",depth:3,charIndex:-1},{text:"`*ByDisplayValue`",id:"bydisplayvalue",depth:3,charIndex:-1},{text:"`*ByText`",id:"bytext",depth:3,charIndex:-1},{text:"`*ByHintText`",id:"byhinttext",depth:3,charIndex:-1},{text:"`*ByTestId`",id:"bytestid",depth:3,charIndex:-1},{text:"Common options",id:"common-options",depth:3,charIndex:9754},{text:"`includeHiddenElements` option",id:"includehiddenelements-option",depth:4,charIndex:-1},{text:"TextMatch type",id:"textmatch-type",depth:2,charIndex:10468},{text:"Examples",id:"examples",depth:3,charIndex:10603},{text:"Options",id:"options-1",depth:3,charIndex:-1},{text:"Precision",id:"precision",depth:4,charIndex:10704},{text:"Normalization",id:"normalization",depth:4,charIndex:11487},{text:"Legacy unit testing helpers",id:"legacy-unit-testing-helpers",depth:2,charIndex:12753},{text:"`UNSAFE_ByType`",id:"unsafe_bytype",depth:3,charIndex:-1},{text:"`UNSAFE_ByProps`",id:"unsafe_byprops",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/queries.mdx"},{title:"`render` function",routePath:"/react-native-testing-library/12.x/docs/api/render",lang:"",toc:[{text:"Options",id:"options",depth:3,charIndex:-1},{text:"`wrapper` option",id:"wrapper-option",depth:4,charIndex:-1},{text:"`concurrentRoot` option",id:"concurrentroot-option",depth:4,charIndex:-1},{text:"`createNodeMock` option",id:"createnodemock-option",depth:4,charIndex:-1},{text:"`unstable_validateStringsRenderedWithinText` option",id:"unstable_validatestringsrenderedwithintext-option",depth:4,charIndex:-1},{text:"Result",id:"result",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/render.mdx"},{title:"`screen` object",routePath:"/react-native-testing-library/12.x/docs/api/screen",lang:"",toc:[{text:"`...queries`",id:"queries",depth:3,charIndex:-1},{text:"Example",id:"example",depth:4,charIndex:549},{text:"`rerender`",id:"rerender",depth:3,charIndex:-1},{text:"`unmount`",id:"unmount",depth:3,charIndex:-1},{text:"`debug`",id:"debug",depth:3,charIndex:-1},{text:"`message` option",id:"message-option",depth:4,charIndex:-1},{text:"`mapProps` option",id:"mapprops-option",depth:4,charIndex:-1},{text:"`toJSON`",id:"tojson",depth:3,charIndex:-1},{text:"`root`",id:"root",depth:3,charIndex:-1},{text:"`UNSAFE_root`",id:"unsafe_root",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/api/screen.mdx"},{title:"Community resources",routePath:"/react-native-testing-library/12.x/docs/guides/community-resources",lang:"",toc:[{text:"Recommended content",id:"recommended-content",depth:2,charIndex:3},{text:"Older, potentially outdated content",id:"older-potentially-outdated-content",depth:2,charIndex:601}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/guides/community-resources.mdx"},{title:"FAQ",routePath:"/react-native-testing-library/12.x/docs/guides/faq",lang:"",toc:[{text:"Can I test the native features of React Native apps?",id:"can-i-test-the-native-features-of-react-native-apps",depth:2,charIndex:3},{text:"Should I use/migrate to `screen` queries?",id:"should-i-usemigrate-to-screen-queries",depth:2,charIndex:-1},{text:"Should I use/migrate to User Event interactions?",id:"should-i-usemigrate-to-user-event-interactions",depth:2,charIndex:1595}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/guides/faq.mdx"},{title:"How should I query?",routePath:"/react-native-testing-library/12.x/docs/guides/how-to-query",lang:"",toc:[{text:"Query parts",id:"query-parts",depth:2,charIndex:273},{text:"Query variant",id:"query-variant",depth:2,charIndex:521},{text:"Idiomatic query variants",id:"idiomatic-query-variants",depth:3,charIndex:1386},{text:"Query predicate",id:"query-predicate",depth:2,charIndex:2339},{text:"Idiomatic query predicates",id:"idiomatic-query-predicates",depth:3,charIndex:3113},{text:"1. By Role query",id:"1-by-role-query",depth:3,charIndex:-1},{text:"Name option",id:"name-option",depth:4,charIndex:-1},{text:"2. Text input queries",id:"2-text-input-queries",depth:3,charIndex:-1},{text:"3. Other accessible queries",id:"3-other-accessible-queries",depth:3,charIndex:-1},{text:"4. Test ID query",id:"4-test-id-query",depth:3,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/guides/how-to-query.mdx"},{title:"Troubleshooting",routePath:"/react-native-testing-library/12.x/docs/guides/troubleshooting",lang:"",toc:[{text:"Matching React Native, React & React Test Renderer versions",id:"matching-react-native-react--react-test-renderer-versions",depth:2,charIndex:116},{text:"Example repository",id:"example-repository",depth:2,charIndex:1005},{text:"Undefined component error",id:"undefined-component-error",depth:2,charIndex:1254},{text:"Mocking React Native",id:"mocking-react-native",depth:3,charIndex:2110},{text:"Act warnings",id:"act-warnings",depth:2,charIndex:2372}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/guides/troubleshooting.mdx"},{title:"Migration to built-in Jest matchers",routePath:"/react-native-testing-library/12.x/docs/migration/jest-matchers",lang:"",toc:[{text:"General notes",id:"general-notes",depth:2,charIndex:119},{text:"Usage",id:"usage",depth:2,charIndex:533},{text:"Gradual migration",id:"gradual-migration",depth:3,charIndex:674},{text:"Migration details",id:"migration-details",depth:2,charIndex:905},{text:"Matchers not requiring changes",id:"matchers-not-requiring-changes",depth:3,charIndex:926},{text:"Replaced matchers",id:"replaced-matchers",depth:3,charIndex:1233},{text:"Added matchers",id:"added-matchers",depth:3,charIndex:1626},{text:"Noteworthy details",id:"noteworthy-details",depth:3,charIndex:1688}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/migration/jest-matchers.mdx"},{title:"Migration to 11.x",routePath:"/react-native-testing-library/12.x/docs/migration/previous/v11",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:153},{text:"Update to Jest 28 if you use fake timers",id:"update-to-jest-28-if-you-use-fake-timers",depth:3,charIndex:173},{text:"Refactor legacy `waitForOptions` position",id:"refactor-legacy-waitforoptions-position",depth:3,charIndex:-1},{text:'Triggering non-touch events on targets with `pointerEvents="box-none"` prop',id:"triggering-non-touch-events-on-targets-with-pointereventsbox-none-prop",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:1263}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/migration/previous/v11.mdx"},{title:"Migration to 2.x",routePath:"/react-native-testing-library/12.x/docs/migration/previous/v2",lang:"",toc:[{text:"Dropping Node 8",id:"dropping-node-8",depth:2,charIndex:100},{text:"Auto Cleanup",id:"auto-cleanup",depth:2,charIndex:325},{text:"WaitFor API changes",id:"waitfor-api-changes",depth:2,charIndex:1248},{text:"Removed global `debug` function",id:"removed-global-debug-function",depth:2,charIndex:-1},{text:"Removed global `shallow` function",id:"removed-global-shallow-function",depth:2,charIndex:-1},{text:"Removed functions",id:"removed-functions",depth:2,charIndex:2145},{text:"Some `ByTestId` queries behavior changes",id:"some-bytestid-queries-behavior-changes",depth:2,charIndex:-1},{text:"Deprecated `flushMicrotasksQueue`",id:"deprecated-flushmicrotasksqueue",depth:2,charIndex:-1}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/migration/previous/v2.mdx"},{title:"Migration to 7.x",routePath:"/react-native-testing-library/12.x/docs/migration/previous/v7",lang:"",toc:[{text:"Guide for `react-native-testing-library` users",id:"guide-for-react-native-testing-library-users",depth:2,charIndex:-1},{text:"Renaming the library",id:"renaming-the-library",depth:3,charIndex:452},{text:"New aliases",id:"new-aliases",depth:3,charIndex:1352},{text:"Renaming `ByPlaceholder` queries",id:"renaming-byplaceholder-queries",depth:3,charIndex:-1},{text:"`fireEvent` support for disabled components",id:"fireevent-support-for-disabled-components",depth:3,charIndex:-1},{text:"Guide for `@testing-library/react-native` users",id:"guide-for-testing-libraryreact-native-users",depth:2,charIndex:-1},{text:'Renaming "wait" helpers',id:"renaming-wait-helpers",depth:3,charIndex:2874},{text:"Changes to `ByTestId` queries",id:"changes-to-bytestid-queries",depth:3,charIndex:-1},{text:"No `ByTitle` queries",id:"no-bytitle-queries",depth:3,charIndex:-1},{text:"No custom Jest configuration",id:"no-custom-jest-configuration",depth:3,charIndex:3628},{text:"Cleanup is included by default",id:"cleanup-is-included-by-default",depth:3,charIndex:3917},{text:"No NativeTestInstance abstraction",id:"no-nativetestinstance-abstraction",depth:3,charIndex:4313},{text:"No `container` nor `baseElement` returned from `render`",id:"no-container-nor-baseelement-returned-from-render",depth:3,charIndex:-1},{text:"Firing events changes",id:"firing-events-changes",depth:3,charIndex:4823}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/migration/previous/v7.mdx"},{title:"Migration to 9.x",routePath:"/react-native-testing-library/12.x/docs/migration/previous/v9",lang:"",toc:[{text:"Support for text match options a.k.a string precision API",id:"support-for-text-match-options-aka-string-precision-api",depth:2,charIndex:284},{text:"Reverted matching text across several nodes",id:"reverted-matching-text-across-several-nodes",depth:2,charIndex:924},{text:"Future plans",id:"future-plans",depth:2,charIndex:1437}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/migration/previous/v9.mdx"},{title:"Migration to 12.x",routePath:"/react-native-testing-library/12.x/docs/migration/v12",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:484},{text:"1. All queries exclude elements hidden from accessibility by default",id:"1-all-queries-exclude-elements-hidden-from-accessibility-by-default",depth:3,charIndex:504},{text:"2. `*ByRole` queries now return only accessibility elements",id:"2-byrole-queries-now-return-only-accessibility-elements",depth:3,charIndex:-1},{text:"Examples",id:"examples",depth:4,charIndex:1510},{text:"3. `*ByText`, `*ByDisplayValue`, `*ByPlaceholderText` queries now return host elements",id:"3-bytext-bydisplayvalue-byplaceholdertext-queries-now-return-host-elements",depth:3,charIndex:-1},{text:"4. `container` API has been renamed to `UNSAFE_root`.",id:"4-container-api-has-been-renamed-to-unsafe_root",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:2923}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/migration/v12.mdx"},{title:"Introduction",routePath:"/react-native-testing-library/12.x/docs/start/intro",lang:"",toc:[{text:"The problem",id:"the-problem",depth:2,charIndex:3},{text:"This solution",id:"this-solution",depth:2,charIndex:479},{text:"Example",id:"example",depth:2,charIndex:988}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/start/intro.md"},{title:"Quick Start",routePath:"/react-native-testing-library/12.x/docs/start/quick-start",lang:"",toc:[{text:"Installation",id:"installation",depth:2,charIndex:3},{text:"Jest matchers",id:"jest-matchers",depth:3,charIndex:223},{text:"ESLint plugin",id:"eslint-plugin",depth:3,charIndex:379}],frontmatter:{},version:"12.x",_relativePath:"12.x/docs/start/quick-start.mdx"},{title:"",routePath:"/react-native-testing-library/12.x/",lang:"",toc:[],frontmatter:{pageType:"home",hero:{name:"React Native",text:"Testing Library",image:{src:"/img/owl.png"},tagline:"Helps you to write better tests with less effort.",actions:[{theme:"brand",text:"Quick Start",link:"/docs/start/quick-start"},{theme:"alt",text:"Explore API",link:"/docs/api"}]},features:[{title:"Maintainable",details:"Write maintainable tests for your React Native apps.",icon:"✨"},{title:"Reliable",details:"Promotes testing public APIs and avoiding implementation details.",icon:"βœ…"},{title:"Community Driven",details:"Supported by React Native community and its core contributors.",icon:"❀️"}]},version:"12.x",_relativePath:"12.x/index.md"},{title:"Network Requests",routePath:"/react-native-testing-library/cookbook/advanced/network-requests",lang:"",toc:[{text:"Introduction",id:"introduction",depth:2,charIndex:3},{text:"Phonebook Example",id:"phonebook-example",depth:2,charIndex:568},{text:"Start testing with a simple test",id:"start-testing-with-a-simple-test",depth:2,charIndex:1294},{text:"Testing error handling",id:"testing-error-handling",depth:2,charIndex:2353},{text:"Global guarding against unwanted API requests",id:"global-guarding-against-unwanted-api-requests",depth:2,charIndex:2920},{text:"Conclusion",id:"conclusion",depth:2,charIndex:3508},{text:"Further Reading and Alternatives",id:"further-reading-and-alternatives",depth:2,charIndex:4130}],frontmatter:{},version:"13.x",_relativePath:"13.x/cookbook/advanced/network-requests.md"},{title:"Async tests",routePath:"/react-native-testing-library/cookbook/basics/async-tests",lang:"",toc:[{text:"Summary",id:"summary",depth:2,charIndex:3},{text:"Example",id:"example",depth:3,charIndex:911},{text:"Async utilities",id:"async-utilities",depth:2,charIndex:1008},{text:"`findBy*` queries",id:"findby-queries",depth:3,charIndex:-1},{text:"Example",id:"example-1",depth:4,charIndex:1622},{text:"`waitFor` function",id:"waitfor-function",depth:3,charIndex:-1},{text:"Example",id:"example-2",depth:4,charIndex:2128},{text:"`waitForElementToBeRemoved` function",id:"waitforelementtoberemoved-function",depth:3,charIndex:-1},{text:"Example",id:"example-3",depth:4,charIndex:2743},{text:"Fake Timers",id:"fake-timers",depth:2,charIndex:2756}],frontmatter:{},version:"13.x",_relativePath:"13.x/cookbook/basics/async-tests.md"},{title:"Custom `render` function",routePath:"/react-native-testing-library/cookbook/basics/custom-render",lang:"",toc:[{text:"Summary",id:"summary",depth:3,charIndex:25},{text:"Example",id:"example",depth:3,charIndex:318},{text:"More info",id:"more-info",depth:3,charIndex:360},{text:"Additional params",id:"additional-params",depth:4,charIndex:372},{text:"Multiple functions",id:"multiple-functions",depth:4,charIndex:571},{text:"Async function",id:"async-function",depth:4,charIndex:787}],frontmatter:{},version:"13.x",_relativePath:"13.x/cookbook/basics/custom-render.md"},{title:"Introduction",routePath:"/react-native-testing-library/cookbook/",lang:"",toc:[{text:"What's Inside the Cookbook?",id:"whats-inside-the-cookbook",depth:2,charIndex:434},{text:"What's Next?",id:"whats-next",depth:2,charIndex:1045}],frontmatter:{},version:"13.x",_relativePath:"13.x/cookbook/index.md"},{title:"Jotai",routePath:"/react-native-testing-library/cookbook/state-management/jotai",lang:"",toc:[{text:"Introduction",id:"introduction",depth:2,charIndex:3},{text:"Task List Example",id:"task-list-example",depth:2,charIndex:337},{text:"Starting with a Simple Test",id:"starting-with-a-simple-test",depth:2,charIndex:566},{text:"Custom Render Function to populate Jotai Atoms with Initial Values",id:"custom-render-function-to-populate-jotai-atoms-with-initial-values",depth:2,charIndex:860},{text:"Testing the `TaskList` Component with initial tasks",id:"testing-the-tasklist-component-with-initial-tasks",depth:2,charIndex:-1},{text:"Modifying atom outside of React components",id:"modifying-atom-outside-of-react-components",depth:2,charIndex:1773},{text:"Testing atom outside of React components",id:"testing-atom-outside-of-react-components",depth:2,charIndex:2022},{text:"Conclusion",id:"conclusion",depth:2,charIndex:2358}],frontmatter:{},version:"13.x",_relativePath:"13.x/cookbook/state-management/jotai.md"},{title:"Testing environment",routePath:"/react-native-testing-library/docs/advanced/testing-env",lang:"",toc:[{text:"React renderers",id:"react-renderers",depth:2,charIndex:659},{text:"React Test Renderer",id:"react-test-renderer",depth:2,charIndex:1382},{text:"Element tree",id:"element-tree",depth:2,charIndex:2783},{text:"Host and composite components",id:"host-and-composite-components",depth:2,charIndex:3389},{text:"Differentiating between host and composite elements",id:"differentiating-between-host-and-composite-elements",depth:3,charIndex:5113},{text:"Tree nodes",id:"tree-nodes",depth:2,charIndex:5538},{text:"Asserting props",id:"asserting-props",depth:3,charIndex:5854},{text:"Tree navigation",id:"tree-navigation",depth:2,charIndex:6557},{text:"Queries",id:"queries",depth:2,charIndex:7290}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/advanced/testing-env.mdx"},{title:"Third-Party Library Integration",routePath:"/react-native-testing-library/docs/advanced/third-party-integration",lang:"",toc:[{text:"Handling Events in Third-Party Libraries",id:"handling-events-in-third-party-libraries",depth:2,charIndex:234},{text:"Example: React Native Gesture Handler",id:"example-react-native-gesture-handler",depth:3,charIndex:1026}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/advanced/third-party-integration.mdx"},{title:"Understanding `act` function",routePath:"/react-native-testing-library/docs/advanced/understanding-act",lang:"",toc:[{text:"`act` warnings",id:"act-warnings",depth:2,charIndex:-1},{text:"Synchronous `act`",id:"synchronous-act",depth:2,charIndex:-1},{text:"Responsibility",id:"responsibility",depth:3,charIndex:575},{text:"When to use act",id:"when-to-use-act",depth:3,charIndex:1673},{text:"Implementation",id:"implementation",depth:3,charIndex:2765},{text:"Asynchronous `act`",id:"asynchronous-act",depth:2,charIndex:-1},{text:"Asynchronous code",id:"asynchronous-code",depth:3,charIndex:3756},{text:"Solution with fake timers",id:"solution-with-fake-timers",depth:3,charIndex:4462},{text:"Solution with real timers",id:"solution-with-real-timers",depth:3,charIndex:4772},{text:"Async act warning",id:"async-act-warning",depth:3,charIndex:5594},{text:"References",id:"references",depth:2,charIndex:6029}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/advanced/understanding-act.mdx"},{title:"API Overview",routePath:"/react-native-testing-library/docs/api",lang:"",toc:[],frontmatter:{uri:"/api"},version:"13.x",_relativePath:"13.x/docs/api.md"},{title:"Fire Event API",routePath:"/react-native-testing-library/docs/api/events/fire-event",lang:"",toc:[{text:"`fireEvent`",id:"fireevent",depth:2,charIndex:-1},{text:"`fireEvent.press`",id:"fireeventpress",depth:3,charIndex:-1},{text:"`fireEvent.changeText`",id:"fireeventchangetext",depth:3,charIndex:-1},{text:"`fireEvent.scroll`",id:"fireeventscroll",depth:3,charIndex:-1},{text:"On a `ScrollView`",id:"on-a-scrollview",depth:4,charIndex:-1},{text:"`fireEventAsync`",id:"fireeventasync",depth:2,charIndex:-1},{text:"`fireEventAsync.press`",id:"fireeventasyncpress",depth:3,charIndex:-1},{text:"`fireEventAsync.changeText`",id:"fireeventasyncchangetext",depth:3,charIndex:-1},{text:"`fireEventAsync.scroll`",id:"fireeventasyncscroll",depth:3,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/events/fire-event.mdx"},{title:"User Event interactions",routePath:"/react-native-testing-library/docs/api/events/user-event",lang:"",toc:[{text:"Comparison with Fire Event API",id:"comparison-with-fire-event-api",depth:2,charIndex:3},{text:"`setup()`",id:"setup",depth:2,charIndex:-1},{text:"Options",id:"options",depth:3,charIndex:-1},{text:"`press()`",id:"press",depth:2,charIndex:-1},{text:"`longPress()`",id:"longpress",depth:2,charIndex:-1},{text:"Options",id:"options-1",depth:3,charIndex:-1},{text:"`type()`",id:"type",depth:2,charIndex:-1},{text:"Options",id:"options-2",depth:3,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events",depth:3,charIndex:-1},{text:"`clear()`",id:"clear",depth:2,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-1",depth:3,charIndex:-1},{text:"`paste()`",id:"paste",depth:2,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-2",depth:3,charIndex:-1},{text:"`scrollTo()`",id:"scroll-to",depth:2,charIndex:-1},{text:"Options",id:"options-3",depth:3,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-3",depth:3,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/events/user-event.mdx"},{title:"Jest matchers",routePath:"/react-native-testing-library/docs/api/jest-matchers",lang:"",toc:[{text:"Setup",id:"setup",depth:2,charIndex:173},{text:"Migration from legacy Jest Native matchers.",id:"migration-from-legacy-jest-native-matchers",depth:2,charIndex:355},{text:"Checking element existence",id:"checking-element-existence",depth:2,charIndex:519},{text:"`toBeOnTheScreen()`",id:"tobeonthescreen",depth:3,charIndex:-1},{text:"Element Content",id:"element-content",depth:2,charIndex:773},{text:"`toHaveTextContent()`",id:"tohavetextcontent",depth:3,charIndex:-1},{text:"`toContainElement()`",id:"tocontainelement",depth:3,charIndex:-1},{text:"`toBeEmptyElement()`",id:"tobeemptyelement",depth:3,charIndex:-1},{text:"Checking element state",id:"checking-element-state",depth:2,charIndex:1259},{text:"`toHaveDisplayValue()`",id:"tohavedisplayvalue",depth:3,charIndex:-1},{text:"`toHaveAccessibilityValue()`",id:"tohaveaccessibilityvalue",depth:3,charIndex:-1},{text:"`toBeEnabled()` / `toBeDisabled`",id:"tobeenabled--tobedisabled",depth:3,charIndex:-1},{text:"`toBeSelected()`",id:"tobeselected",depth:3,charIndex:-1},{text:"`toBeChecked()` / `toBePartiallyChecked()`",id:"tobechecked--tobepartiallychecked",depth:3,charIndex:-1},{text:"`toBeExpanded()` / `toBeCollapsed()`",id:"tobeexpanded--tobecollapsed",depth:3,charIndex:-1},{text:"`toBeBusy()`",id:"tobebusy",depth:3,charIndex:-1},{text:"Checking element style",id:"checking-element-style",depth:2,charIndex:3871},{text:"`toBeVisible()`",id:"tobevisible",depth:3,charIndex:-1},{text:"`toHaveStyle()`",id:"tohavestyle",depth:3,charIndex:-1},{text:"Other matchers",id:"other-matchers",depth:2,charIndex:4260},{text:"`toHaveAccessibleName()`",id:"tohaveaccessiblename",depth:3,charIndex:-1},{text:"`toHaveProp()`",id:"tohaveprop",depth:3,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/jest-matchers.mdx"},{title:"Accessibility",routePath:"/react-native-testing-library/docs/api/misc/accessibility",lang:"",toc:[{text:"`isHiddenFromAccessibility`",id:"ishiddenfromaccessibility",depth:2,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/misc/accessibility.mdx"},{title:"Async utilities",routePath:"/react-native-testing-library/docs/api/misc/async",lang:"",toc:[{text:"`findBy*` queries",id:"findby-queries",depth:2,charIndex:-1},{text:"`waitFor`",id:"waitfor",depth:2,charIndex:-1},{text:"`waitForElementToBeRemoved`",id:"waitforelementtoberemoved",depth:2,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/misc/async.mdx"},{title:"Configuration",routePath:"/react-native-testing-library/docs/api/misc/config",lang:"",toc:[{text:"`configure`",id:"configure",depth:2,charIndex:-1},{text:"`asyncUtilTimeout` option",id:"asyncutiltimeout-option",depth:3,charIndex:-1},{text:"`defaultIncludeHiddenElements` option",id:"defaultincludehiddenelements-option",depth:3,charIndex:-1},{text:"`defaultDebugOptions` option",id:"defaultdebugoptions-option",depth:3,charIndex:-1},{text:"`concurrentRoot` option",id:"concurrentroot-option",depth:3,charIndex:-1},{text:"`resetToDefaults()`",id:"resettodefaults",depth:2,charIndex:-1},{text:"Environment variables",id:"environment-variables",depth:2,charIndex:946},{text:"`RNTL_SKIP_AUTO_CLEANUP`",id:"rntl_skip_auto_cleanup",depth:3,charIndex:-1},{text:"`RNTL_SKIP_AUTO_DETECT_FAKE_TIMERS`",id:"rntl_skip_auto_detect_fake_timers",depth:3,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/misc/config.mdx"},{title:"Other helpers",routePath:"/react-native-testing-library/docs/api/misc/other",lang:"",toc:[{text:"`within`, `getQueriesForElement`",id:"within-getqueriesforelement",depth:2,charIndex:-1},{text:"`act`",id:"act",depth:2,charIndex:-1},{text:"`cleanup`",id:"cleanup",depth:2,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/misc/other.mdx"},{title:"`renderHook` function",routePath:"/react-native-testing-library/docs/api/misc/render-hook",lang:"",toc:[{text:"`renderHook`",id:"renderhook",depth:2,charIndex:-1},{text:"`options`",id:"options",depth:3,charIndex:-1},{text:"`initialProps`",id:"initialprops",depth:4,charIndex:-1},{text:"`wrapper`",id:"wrapper",depth:4,charIndex:-1},{text:"`concurrentRoot`",id:"concurrentroot",depth:3,charIndex:-1},{text:"Result",id:"result",depth:3,charIndex:1240},{text:"`result`",id:"result-1",depth:4,charIndex:-1},{text:"`rerender`",id:"rerender",depth:4,charIndex:-1},{text:"`unmount`",id:"unmount",depth:4,charIndex:-1},{text:"Examples",id:"examples",depth:3,charIndex:1956},{text:"With `initialProps`",id:"with-initialprops",depth:4,charIndex:-1},{text:"With `wrapper`",id:"with-wrapper",depth:4,charIndex:-1},{text:"`renderHookAsync` function",id:"renderhookasync-function",depth:2,charIndex:-1},{text:"Result",id:"result-2",depth:3,charIndex:1240}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/misc/render-hook.mdx"},{title:"Queries",routePath:"/react-native-testing-library/docs/api/queries",lang:"",toc:[{text:"Accessing queries",id:"accessing-queries",depth:2,charIndex:226},{text:"Using `screen` object",id:"using-screen-object",depth:3,charIndex:-1},{text:"Using `render` result",id:"using-render-result",depth:3,charIndex:-1},{text:"Query parts",id:"query-parts",depth:2,charIndex:848},{text:"Query variant",id:"query-variant",depth:2,charIndex:1095},{text:"`getBy*` queries",id:"getby-queries",depth:3,charIndex:-1},{text:"`getAllBy*` queries",id:"getallby-queries",depth:3,charIndex:-1},{text:"`queryBy*` queries",id:"queryby-queries",depth:3,charIndex:-1},{text:"`queryAllBy*` queries",id:"queryallby-queries",depth:3,charIndex:-1},{text:"`findBy*` queries",id:"findby-queries",depth:3,charIndex:-1},{text:"`findAllBy*` queries",id:"findallby-queries",depth:3,charIndex:-1},{text:"Query predicates",id:"query-predicates",depth:2,charIndex:3631},{text:"`*ByRole`",id:"byrole",depth:3,charIndex:-1},{text:"Options",id:"options",depth:4,charIndex:-1},{text:"`*ByLabelText`",id:"bylabeltext",depth:3,charIndex:-1},{text:"`*ByPlaceholderText`",id:"byplaceholdertext",depth:3,charIndex:-1},{text:"`*ByDisplayValue`",id:"bydisplayvalue",depth:3,charIndex:-1},{text:"`*ByText`",id:"bytext",depth:3,charIndex:-1},{text:"`*ByHintText`",id:"byhinttext",depth:3,charIndex:-1},{text:"`*ByTestId`",id:"bytestid",depth:3,charIndex:-1},{text:"Common options",id:"common-options",depth:3,charIndex:9754},{text:"`includeHiddenElements` option",id:"includehiddenelements-option",depth:4,charIndex:-1},{text:"TextMatch type",id:"textmatch-type",depth:2,charIndex:10468},{text:"Examples",id:"examples",depth:3,charIndex:10603},{text:"Options",id:"options-1",depth:3,charIndex:-1},{text:"Precision",id:"precision",depth:4,charIndex:10704},{text:"Normalization",id:"normalization",depth:4,charIndex:11487},{text:"Legacy unit testing helpers",id:"legacy-unit-testing-helpers",depth:2,charIndex:12753},{text:"`UNSAFE_ByType`",id:"unsafe_bytype",depth:3,charIndex:-1},{text:"`UNSAFE_ByProps`",id:"unsafe_byprops",depth:3,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/queries.mdx"},{title:"`render` API",routePath:"/react-native-testing-library/docs/api/render",lang:"",toc:[{text:"`render` function",id:"render-function",depth:2,charIndex:-1},{text:"Options",id:"options",depth:3,charIndex:470},{text:"`wrapper`",id:"wrapper",depth:4,charIndex:-1},{text:"`concurrentRoot`",id:"concurrentroot",depth:4,charIndex:-1},{text:"`createNodeMock`",id:"createnodemock",depth:4,charIndex:-1},{text:"`unstable_validateStringsRenderedWithinText`",id:"unstable_validatestringsrenderedwithintext",depth:4,charIndex:-1},{text:"Result",id:"result",depth:3,charIndex:1982},{text:"`renderAsync` function",id:"renderasync-function",depth:2,charIndex:-1},{text:"Options",id:"options-1",depth:3,charIndex:2521},{text:"Result",id:"result-1",depth:3,charIndex:2581}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/render.mdx"},{title:"`screen` object",routePath:"/react-native-testing-library/docs/api/screen",lang:"",toc:[{text:"`...queries`",id:"queries",depth:3,charIndex:-1},{text:"Example",id:"example",depth:4,charIndex:549},{text:"`rerender`",id:"rerender",depth:3,charIndex:-1},{text:"`rerenderAsync`",id:"rerenderasync",depth:3,charIndex:-1},{text:"`unmount`",id:"unmount",depth:3,charIndex:-1},{text:"`unmountAsync`",id:"unmountasync",depth:3,charIndex:-1},{text:"`debug`",id:"debug",depth:3,charIndex:-1},{text:"`message` option",id:"message-option",depth:4,charIndex:-1},{text:"`mapProps` option",id:"mapprops-option",depth:4,charIndex:-1},{text:"`toJSON`",id:"tojson",depth:3,charIndex:-1},{text:"`root`",id:"root",depth:3,charIndex:-1},{text:"`UNSAFE_root`",id:"unsafe_root",depth:3,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/api/screen.mdx"},{title:"Community resources",routePath:"/react-native-testing-library/docs/guides/community-resources",lang:"",toc:[{text:"Recommended content",id:"recommended-content",depth:2,charIndex:3},{text:"Older, potentially outdated content",id:"older-potentially-outdated-content",depth:2,charIndex:601}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/guides/community-resources.mdx"},{title:"FAQ",routePath:"/react-native-testing-library/docs/guides/faq",lang:"",toc:[{text:"Can I test the native features of React Native apps?",id:"can-i-test-the-native-features-of-react-native-apps",depth:2,charIndex:3},{text:"Should I use/migrate to `screen` queries?",id:"should-i-usemigrate-to-screen-queries",depth:2,charIndex:-1},{text:"Should I use/migrate to User Event interactions?",id:"should-i-usemigrate-to-user-event-interactions",depth:2,charIndex:1595}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/guides/faq.mdx"},{title:"How should I query?",routePath:"/react-native-testing-library/docs/guides/how-to-query",lang:"",toc:[{text:"Query parts",id:"query-parts",depth:2,charIndex:273},{text:"Query variant",id:"query-variant",depth:2,charIndex:521},{text:"Idiomatic query variants",id:"idiomatic-query-variants",depth:3,charIndex:1386},{text:"Query predicate",id:"query-predicate",depth:2,charIndex:2339},{text:"Idiomatic query predicates",id:"idiomatic-query-predicates",depth:3,charIndex:3113},{text:"1. By Role query",id:"1-by-role-query",depth:3,charIndex:-1},{text:"Name option",id:"name-option",depth:4,charIndex:-1},{text:"2. Text input queries",id:"2-text-input-queries",depth:3,charIndex:-1},{text:"3. Other accessible queries",id:"3-other-accessible-queries",depth:3,charIndex:-1},{text:"4. Test ID query",id:"4-test-id-query",depth:3,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/guides/how-to-query.mdx"},{title:"React 19 & Suspense Support",routePath:"/react-native-testing-library/docs/guides/react-19",lang:"",toc:[{text:"New async APIs",id:"new-async-apis",depth:2,charIndex:384},{text:"APIs that remain unchanged",id:"apis-that-remain-unchanged",depth:2,charIndex:738},{text:"What changes in your tests",id:"what-changes-in-your-tests",depth:2,charIndex:1053},{text:"Making tests async",id:"making-tests-async",depth:3,charIndex:1083},{text:"When to use async APIs",id:"when-to-use-async-apis",depth:3,charIndex:1253},{text:"Migration strategy",id:"migration-strategy",depth:2,charIndex:1492},{text:"New projects",id:"new-projects",depth:3,charIndex:1514},{text:"Existing projects",id:"existing-projects",depth:3,charIndex:1662},{text:"Future direction",id:"future-direction",depth:3,charIndex:1874}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/guides/react-19.mdx"},{title:"Troubleshooting",routePath:"/react-native-testing-library/docs/guides/troubleshooting",lang:"",toc:[{text:"Matching React Native, React & React Test Renderer versions",id:"matching-react-native-react--react-test-renderer-versions",depth:2,charIndex:116},{text:"Example repository",id:"example-repository",depth:2,charIndex:1005},{text:"Undefined component error",id:"undefined-component-error",depth:2,charIndex:1254},{text:"Mocking React Native",id:"mocking-react-native",depth:3,charIndex:2110},{text:"Act warnings",id:"act-warnings",depth:2,charIndex:2372}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/guides/troubleshooting.mdx"},{title:"Migration to built-in Jest matchers",routePath:"/react-native-testing-library/docs/migration/jest-matchers",lang:"",toc:[{text:"General notes",id:"general-notes",depth:2,charIndex:119},{text:"Usage",id:"usage",depth:2,charIndex:533},{text:"Gradual migration",id:"gradual-migration",depth:3,charIndex:715},{text:"Migration details",id:"migration-details",depth:2,charIndex:946},{text:"Matchers not requiring changes",id:"matchers-not-requiring-changes",depth:3,charIndex:967},{text:"Replaced matchers",id:"replaced-matchers",depth:3,charIndex:1274},{text:"Added matchers",id:"added-matchers",depth:3,charIndex:1667},{text:"Noteworthy details",id:"noteworthy-details",depth:3,charIndex:1729}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/migration/jest-matchers.mdx"},{title:"Migration to 11.x",routePath:"/react-native-testing-library/docs/migration/previous/v11",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:153},{text:"Update to Jest 28 if you use fake timers",id:"update-to-jest-28-if-you-use-fake-timers",depth:3,charIndex:173},{text:"Refactor legacy `waitForOptions` position",id:"refactor-legacy-waitforoptions-position",depth:3,charIndex:-1},{text:'Triggering non-touch events on targets with `pointerEvents="box-none"` prop',id:"triggering-non-touch-events-on-targets-with-pointereventsbox-none-prop",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:1263}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/migration/previous/v11.mdx"},{title:"Migration to 12.x",routePath:"/react-native-testing-library/docs/migration/previous/v12",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:484},{text:"1. All queries exclude elements hidden from accessibility by default",id:"1-all-queries-exclude-elements-hidden-from-accessibility-by-default",depth:3,charIndex:504},{text:"2. `*ByRole` queries now return only accessibility elements",id:"2-byrole-queries-now-return-only-accessibility-elements",depth:3,charIndex:-1},{text:"Examples",id:"examples",depth:4,charIndex:1510},{text:"3. `*ByText`, `*ByDisplayValue`, `*ByPlaceholderText` queries now return host elements",id:"3-bytext-bydisplayvalue-byplaceholdertext-queries-now-return-host-elements",depth:3,charIndex:-1},{text:"4. `container` API has been renamed to `UNSAFE_root`.",id:"4-container-api-has-been-renamed-to-unsafe_root",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:2923}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/migration/previous/v12.mdx"},{title:"Migration to 2.x",routePath:"/react-native-testing-library/docs/migration/previous/v2",lang:"",toc:[{text:"Dropping Node 8",id:"dropping-node-8",depth:2,charIndex:100},{text:"Auto Cleanup",id:"auto-cleanup",depth:2,charIndex:325},{text:"WaitFor API changes",id:"waitfor-api-changes",depth:2,charIndex:1248},{text:"Removed global `debug` function",id:"removed-global-debug-function",depth:2,charIndex:-1},{text:"Removed global `shallow` function",id:"removed-global-shallow-function",depth:2,charIndex:-1},{text:"Removed functions",id:"removed-functions",depth:2,charIndex:2145},{text:"Some `ByTestId` queries behavior changes",id:"some-bytestid-queries-behavior-changes",depth:2,charIndex:-1},{text:"Deprecated `flushMicrotasksQueue`",id:"deprecated-flushmicrotasksqueue",depth:2,charIndex:-1}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/migration/previous/v2.mdx"},{title:"Migration to 7.x",routePath:"/react-native-testing-library/docs/migration/previous/v7",lang:"",toc:[{text:"Guide for `react-native-testing-library` users",id:"guide-for-react-native-testing-library-users",depth:2,charIndex:-1},{text:"Renaming the library",id:"renaming-the-library",depth:3,charIndex:452},{text:"New aliases",id:"new-aliases",depth:3,charIndex:1352},{text:"Renaming `ByPlaceholder` queries",id:"renaming-byplaceholder-queries",depth:3,charIndex:-1},{text:"`fireEvent` support for disabled components",id:"fireevent-support-for-disabled-components",depth:3,charIndex:-1},{text:"Guide for `@testing-library/react-native` users",id:"guide-for-testing-libraryreact-native-users",depth:2,charIndex:-1},{text:'Renaming "wait" helpers',id:"renaming-wait-helpers",depth:3,charIndex:2874},{text:"Changes to `ByTestId` queries",id:"changes-to-bytestid-queries",depth:3,charIndex:-1},{text:"No `ByTitle` queries",id:"no-bytitle-queries",depth:3,charIndex:-1},{text:"No custom Jest configuration",id:"no-custom-jest-configuration",depth:3,charIndex:3628},{text:"Cleanup is included by default",id:"cleanup-is-included-by-default",depth:3,charIndex:3917},{text:"No NativeTestInstance abstraction",id:"no-nativetestinstance-abstraction",depth:3,charIndex:4313},{text:"No `container` nor `baseElement` returned from `render`",id:"no-container-nor-baseelement-returned-from-render",depth:3,charIndex:-1},{text:"Firing events changes",id:"firing-events-changes",depth:3,charIndex:4823}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/migration/previous/v7.mdx"},{title:"Migration to 9.x",routePath:"/react-native-testing-library/docs/migration/previous/v9",lang:"",toc:[{text:"Support for text match options a.k.a string precision API",id:"support-for-text-match-options-aka-string-precision-api",depth:2,charIndex:284},{text:"Reverted matching text across several nodes",id:"reverted-matching-text-across-several-nodes",depth:2,charIndex:924},{text:"Future plans",id:"future-plans",depth:2,charIndex:1437}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/migration/previous/v9.mdx"},{title:"Migration to 13.x",routePath:"/react-native-testing-library/docs/migration/v13",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:228},{text:"Supported React and React Native versions",id:"supported-react-and-react-native-versions",depth:3,charIndex:248},{text:"Concurrent rendering by default",id:"concurrent-rendering-by-default",depth:3,charIndex:593},{text:"Extend Jest matchers by default",id:"extend-jest-matchers-by-default",depth:3,charIndex:980},{text:"Removed deprecated `*ByAccessibilityState` queries",id:"removed-deprecated-byaccessibilitystate-queries",depth:3,charIndex:-1},{text:"Removed deprecated `*ByAccessibilityValue` queries",id:"removed-deprecated-byaccessibilityvalue-queries",depth:3,charIndex:-1},{text:"Removed Jest preset",id:"removed-jest-preset",depth:3,charIndex:2245},{text:"Removed `debug.shallow`",id:"removed-debugshallow",depth:3,charIndex:-1},{text:"Changes to accessibility label calculation",id:"changes-to-accessibility-label-calculation",depth:3,charIndex:2565},{text:"Other changes",id:"other-changes",depth:2,charIndex:2798},{text:"Removed host component names autodetection",id:"removed-host-component-names-autodetection",depth:3,charIndex:2815},{text:"Use React implementation of `act` instead of React Test Renderer one",id:"use-react-implementation-of-act-instead-of-react-test-renderer-one",depth:3,charIndex:-1},{text:"Updated `flushMicroTasks` internal method",id:"updated-flushmicrotasks-internal-method",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:3147}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/migration/v13.mdx"},{title:"Introduction",routePath:"/react-native-testing-library/docs/start/intro",lang:"",toc:[{text:"The problem",id:"the-problem",depth:2,charIndex:3},{text:"This solution",id:"this-solution",depth:2,charIndex:479},{text:"Example",id:"example",depth:2,charIndex:988}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/start/intro.md"},{title:"Quick Start",routePath:"/react-native-testing-library/docs/start/quick-start",lang:"",toc:[{text:"Installation",id:"installation",depth:2,charIndex:3},{text:"Jest matchers",id:"jest-matchers",depth:3,charIndex:223},{text:"ESLint plugin",id:"eslint-plugin",depth:3,charIndex:461}],frontmatter:{},version:"13.x",_relativePath:"13.x/docs/start/quick-start.mdx"},{title:"",routePath:"/react-native-testing-library/",lang:"",toc:[],frontmatter:{pageType:"home",hero:{name:"React Native",text:"Testing Library",image:{src:"/img/owl.png"},tagline:"Helps you to write better tests with less effort.",actions:[{theme:"brand",text:"Quick Start",link:"/docs/start/quick-start"},{theme:"alt",text:"Explore API",link:"/docs/api"}]},features:[{title:"Maintainable",details:"Write maintainable tests for your React Native apps.",icon:"✨"},{title:"Reliable",details:"Promotes testing public APIs and avoiding implementation details.",icon:"βœ…"},{title:"Community Driven",details:"Supported by React Native community and its core contributors.",icon:"❀️"}]},version:"13.x",_relativePath:"13.x/index.md"},{title:"Network Requests",routePath:"/react-native-testing-library/14.x/cookbook/advanced/network-requests",lang:"",toc:[{text:"Introduction",id:"introduction",depth:2,charIndex:3},{text:"Phonebook Example",id:"phonebook-example",depth:2,charIndex:568},{text:"Start testing with a simple test",id:"start-testing-with-a-simple-test",depth:2,charIndex:1294},{text:"Testing error handling",id:"testing-error-handling",depth:2,charIndex:2353},{text:"Global guarding against unwanted API requests",id:"global-guarding-against-unwanted-api-requests",depth:2,charIndex:2920},{text:"Conclusion",id:"conclusion",depth:2,charIndex:3508},{text:"Further Reading and Alternatives",id:"further-reading-and-alternatives",depth:2,charIndex:4130}],frontmatter:{},version:"14.x",_relativePath:"14.x/cookbook/advanced/network-requests.md"},{title:"Async tests",routePath:"/react-native-testing-library/14.x/cookbook/basics/async-tests",lang:"",toc:[{text:"Summary",id:"summary",depth:2,charIndex:3},{text:"Example",id:"example",depth:3,charIndex:911},{text:"Async utilities",id:"async-utilities",depth:2,charIndex:1008},{text:"`findBy*` queries",id:"findby-queries",depth:3,charIndex:-1},{text:"Example",id:"example-1",depth:4,charIndex:1622},{text:"`waitFor` function",id:"waitfor-function",depth:3,charIndex:-1},{text:"Example",id:"example-2",depth:4,charIndex:2128},{text:"`waitForElementToBeRemoved` function",id:"waitforelementtoberemoved-function",depth:3,charIndex:-1},{text:"Example",id:"example-3",depth:4,charIndex:2743},{text:"Fake Timers",id:"fake-timers",depth:2,charIndex:2756}],frontmatter:{},version:"14.x",_relativePath:"14.x/cookbook/basics/async-tests.md"},{title:"Custom `render` function",routePath:"/react-native-testing-library/14.x/cookbook/basics/custom-render",lang:"",toc:[{text:"Summary",id:"summary",depth:3,charIndex:25},{text:"Example",id:"example",depth:3,charIndex:318},{text:"More info",id:"more-info",depth:3,charIndex:360},{text:"Additional params",id:"additional-params",depth:4,charIndex:372},{text:"Multiple functions",id:"multiple-functions",depth:4,charIndex:571},{text:"Async function",id:"async-function",depth:4,charIndex:787}],frontmatter:{},version:"14.x",_relativePath:"14.x/cookbook/basics/custom-render.md"},{title:"Introduction",routePath:"/react-native-testing-library/14.x/cookbook/",lang:"",toc:[{text:"What's Inside the Cookbook?",id:"whats-inside-the-cookbook",depth:2,charIndex:434},{text:"What's Next?",id:"whats-next",depth:2,charIndex:1045}],frontmatter:{},version:"14.x",_relativePath:"14.x/cookbook/index.md"},{title:"Jotai",routePath:"/react-native-testing-library/14.x/cookbook/state-management/jotai",lang:"",toc:[{text:"Introduction",id:"introduction",depth:2,charIndex:3},{text:"Task List Example",id:"task-list-example",depth:2,charIndex:337},{text:"Starting with a Simple Test",id:"starting-with-a-simple-test",depth:2,charIndex:566},{text:"Custom Render Function to populate Jotai Atoms with Initial Values",id:"custom-render-function-to-populate-jotai-atoms-with-initial-values",depth:2,charIndex:860},{text:"Testing the `TaskList` Component with initial tasks",id:"testing-the-tasklist-component-with-initial-tasks",depth:2,charIndex:-1},{text:"Modifying atom outside of React components",id:"modifying-atom-outside-of-react-components",depth:2,charIndex:1773},{text:"Testing atom outside of React components",id:"testing-atom-outside-of-react-components",depth:2,charIndex:2022},{text:"Conclusion",id:"conclusion",depth:2,charIndex:2358}],frontmatter:{},version:"14.x",_relativePath:"14.x/cookbook/state-management/jotai.md"},{title:"Testing environment",routePath:"/react-native-testing-library/14.x/docs/advanced/testing-env",lang:"",toc:[{text:"React renderers",id:"react-renderers",depth:2,charIndex:659},{text:"Test Renderer",id:"test-renderer",depth:2,charIndex:1382},{text:"Element tree",id:"element-tree",depth:2,charIndex:2921},{text:"Host and composite components",id:"host-and-composite-components",depth:2,charIndex:3505},{text:"Differentiating between host and composite elements",id:"differentiating-between-host-and-composite-elements",depth:3,charIndex:5229},{text:"Tree nodes",id:"tree-nodes",depth:2,charIndex:5648},{text:"Asserting props",id:"asserting-props",depth:3,charIndex:5964},{text:"Tree navigation",id:"tree-navigation",depth:2,charIndex:6667},{text:"Queries",id:"queries",depth:2,charIndex:7394}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/advanced/testing-env.mdx"},{title:"Third-Party Library Integration",routePath:"/react-native-testing-library/14.x/docs/advanced/third-party-integration",lang:"",toc:[{text:"Handling Events in Third-Party Libraries",id:"handling-events-in-third-party-libraries",depth:2,charIndex:234},{text:"Example: React Native Gesture Handler",id:"example-react-native-gesture-handler",depth:3,charIndex:1026}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/advanced/third-party-integration.mdx"},{title:"Understanding `act` function",routePath:"/react-native-testing-library/14.x/docs/advanced/understanding-act",lang:"",toc:[{text:"`act` warnings",id:"act-warnings",depth:2,charIndex:-1},{text:"Synchronous `act`",id:"synchronous-act",depth:2,charIndex:-1},{text:"Responsibility",id:"responsibility",depth:3,charIndex:575},{text:"When to use act",id:"when-to-use-act",depth:3,charIndex:1827},{text:"Implementation",id:"implementation",depth:3,charIndex:2918},{text:"Asynchronous `act`",id:"asynchronous-act",depth:2,charIndex:-1},{text:"Asynchronous code",id:"asynchronous-code",depth:3,charIndex:3980},{text:"Solution with fake timers",id:"solution-with-fake-timers",depth:3,charIndex:4686},{text:"Solution with real timers",id:"solution-with-real-timers",depth:3,charIndex:5092},{text:"Async act warning",id:"async-act-warning",depth:3,charIndex:5914},{text:"References",id:"references",depth:2,charIndex:6349}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/advanced/understanding-act.mdx"},{title:"API Overview",routePath:"/react-native-testing-library/14.x/docs/api",lang:"",toc:[],frontmatter:{uri:"/api"},version:"14.x",_relativePath:"14.x/docs/api.md"},{title:"Fire Event API",routePath:"/react-native-testing-library/14.x/docs/api/events/fire-event",lang:"",toc:[{text:"`fireEvent`",id:"fireevent",depth:2,charIndex:-1},{text:"`fireEvent.press`",id:"fireeventpress",depth:3,charIndex:-1},{text:"`fireEvent.changeText`",id:"fireeventchangetext",depth:3,charIndex:-1},{text:"`fireEvent.scroll`",id:"fireeventscroll",depth:3,charIndex:-1},{text:"On a `ScrollView`",id:"on-a-scrollview",depth:4,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/events/fire-event.mdx"},{title:"User Event interactions",routePath:"/react-native-testing-library/14.x/docs/api/events/user-event",lang:"",toc:[{text:"Comparison with Fire Event API",id:"comparison-with-fire-event-api",depth:2,charIndex:3},{text:"`setup()`",id:"setup",depth:2,charIndex:-1},{text:"Options",id:"options",depth:3,charIndex:-1},{text:"`press()`",id:"press",depth:2,charIndex:-1},{text:"`longPress()`",id:"longpress",depth:2,charIndex:-1},{text:"Options",id:"options-1",depth:3,charIndex:-1},{text:"`type()`",id:"type",depth:2,charIndex:-1},{text:"Options",id:"options-2",depth:3,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events",depth:3,charIndex:-1},{text:"`clear()`",id:"clear",depth:2,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-1",depth:3,charIndex:-1},{text:"`paste()`",id:"paste",depth:2,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-2",depth:3,charIndex:-1},{text:"`scrollTo()`",id:"scroll-to",depth:2,charIndex:-1},{text:"Options",id:"options-3",depth:3,charIndex:-1},{text:"Sequence of events",id:"sequence-of-events-3",depth:3,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/events/user-event.mdx"},{title:"Jest matchers",routePath:"/react-native-testing-library/14.x/docs/api/jest-matchers",lang:"",toc:[{text:"Setup",id:"setup",depth:2,charIndex:173},{text:"Migration from legacy Jest Native matchers.",id:"migration-from-legacy-jest-native-matchers",depth:2,charIndex:355},{text:"Checking element existence",id:"checking-element-existence",depth:2,charIndex:519},{text:"`toBeOnTheScreen()`",id:"tobeonthescreen",depth:3,charIndex:-1},{text:"Element Content",id:"element-content",depth:2,charIndex:773},{text:"`toHaveTextContent()`",id:"tohavetextcontent",depth:3,charIndex:-1},{text:"`toContainElement()`",id:"tocontainelement",depth:3,charIndex:-1},{text:"`toBeEmptyElement()`",id:"tobeemptyelement",depth:3,charIndex:-1},{text:"Checking element state",id:"checking-element-state",depth:2,charIndex:1259},{text:"`toHaveDisplayValue()`",id:"tohavedisplayvalue",depth:3,charIndex:-1},{text:"`toHaveAccessibilityValue()`",id:"tohaveaccessibilityvalue",depth:3,charIndex:-1},{text:"`toBeEnabled()` / `toBeDisabled`",id:"tobeenabled--tobedisabled",depth:3,charIndex:-1},{text:"`toBeSelected()`",id:"tobeselected",depth:3,charIndex:-1},{text:"`toBeChecked()` / `toBePartiallyChecked()`",id:"tobechecked--tobepartiallychecked",depth:3,charIndex:-1},{text:"`toBeExpanded()` / `toBeCollapsed()`",id:"tobeexpanded--tobecollapsed",depth:3,charIndex:-1},{text:"`toBeBusy()`",id:"tobebusy",depth:3,charIndex:-1},{text:"Checking element style",id:"checking-element-style",depth:2,charIndex:3871},{text:"`toBeVisible()`",id:"tobevisible",depth:3,charIndex:-1},{text:"`toHaveStyle()`",id:"tohavestyle",depth:3,charIndex:-1},{text:"Other matchers",id:"other-matchers",depth:2,charIndex:4260},{text:"`toHaveAccessibleName()`",id:"tohaveaccessiblename",depth:3,charIndex:-1},{text:"`toHaveProp()`",id:"tohaveprop",depth:3,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/jest-matchers.mdx"},{title:"Accessibility",routePath:"/react-native-testing-library/14.x/docs/api/misc/accessibility",lang:"",toc:[{text:"`isHiddenFromAccessibility`",id:"ishiddenfromaccessibility",depth:2,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/misc/accessibility.mdx"},{title:"Async utilities",routePath:"/react-native-testing-library/14.x/docs/api/misc/async",lang:"",toc:[{text:"`findBy*` queries",id:"findby-queries",depth:2,charIndex:-1},{text:"`waitFor`",id:"waitfor",depth:2,charIndex:-1},{text:"`waitForElementToBeRemoved`",id:"waitforelementtoberemoved",depth:2,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/misc/async.mdx"},{title:"Configuration",routePath:"/react-native-testing-library/14.x/docs/api/misc/config",lang:"",toc:[{text:"`configure`",id:"configure",depth:2,charIndex:-1},{text:"`asyncUtilTimeout` option",id:"asyncutiltimeout-option",depth:3,charIndex:-1},{text:"`defaultIncludeHiddenElements` option",id:"defaultincludehiddenelements-option",depth:3,charIndex:-1},{text:"`defaultDebugOptions` option",id:"defaultdebugoptions-option",depth:3,charIndex:-1},{text:"`concurrentRoot` option",id:"concurrentroot-option",depth:3,charIndex:-1},{text:"`resetToDefaults()`",id:"resettodefaults",depth:2,charIndex:-1},{text:"Environment variables",id:"environment-variables",depth:2,charIndex:946},{text:"`RNTL_SKIP_AUTO_CLEANUP`",id:"rntl_skip_auto_cleanup",depth:3,charIndex:-1},{text:"`RNTL_SKIP_AUTO_DETECT_FAKE_TIMERS`",id:"rntl_skip_auto_detect_fake_timers",depth:3,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/misc/config.mdx"},{title:"Other helpers",routePath:"/react-native-testing-library/14.x/docs/api/misc/other",lang:"",toc:[{text:"`within`",id:"within",depth:2,charIndex:-1},{text:"`act`",id:"act",depth:2,charIndex:-1},{text:"`cleanup`",id:"cleanup",depth:2,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/misc/other.mdx"},{title:"`renderHook` function",routePath:"/react-native-testing-library/14.x/docs/api/misc/render-hook",lang:"",toc:[{text:"`renderHook`",id:"renderhook",depth:2,charIndex:-1},{text:"`options`",id:"options",depth:3,charIndex:-1},{text:"`initialProps`",id:"initialprops",depth:4,charIndex:-1},{text:"`wrapper`",id:"wrapper",depth:4,charIndex:-1},{text:"Result",id:"result",depth:3,charIndex:1525},{text:"`result`",id:"result-1",depth:4,charIndex:-1},{text:"`rerender`",id:"rerender",depth:4,charIndex:-1},{text:"`unmount`",id:"unmount",depth:4,charIndex:-1},{text:"Examples",id:"examples",depth:3,charIndex:2398},{text:"With `initialProps`",id:"with-initialprops",depth:4,charIndex:-1},{text:"With `wrapper`",id:"with-wrapper",depth:4,charIndex:-1},{text:"With React Suspense",id:"with-react-suspense",depth:4,charIndex:2510}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/misc/render-hook.mdx"},{title:"Queries",routePath:"/react-native-testing-library/14.x/docs/api/queries",lang:"",toc:[{text:"Accessing queries",id:"accessing-queries",depth:2,charIndex:226},{text:"Using `screen` object",id:"using-screen-object",depth:3,charIndex:-1},{text:"Using `render` result",id:"using-render-result",depth:3,charIndex:-1},{text:"Query parts",id:"query-parts",depth:2,charIndex:848},{text:"Query variant",id:"query-variant",depth:2,charIndex:1095},{text:"`getBy*` queries",id:"getby-queries",depth:3,charIndex:-1},{text:"`getAllBy*` queries",id:"getallby-queries",depth:3,charIndex:-1},{text:"`queryBy*` queries",id:"queryby-queries",depth:3,charIndex:-1},{text:"`queryAllBy*` queries",id:"queryallby-queries",depth:3,charIndex:-1},{text:"`findBy*` queries",id:"findby-queries",depth:3,charIndex:-1},{text:"`findAllBy*` queries",id:"findallby-queries",depth:3,charIndex:-1},{text:"Query predicates",id:"query-predicates",depth:2,charIndex:3589},{text:"`*ByRole`",id:"byrole",depth:3,charIndex:-1},{text:"Options",id:"options",depth:4,charIndex:-1},{text:"`*ByLabelText`",id:"bylabeltext",depth:3,charIndex:-1},{text:"`*ByPlaceholderText`",id:"byplaceholdertext",depth:3,charIndex:-1},{text:"`*ByDisplayValue`",id:"bydisplayvalue",depth:3,charIndex:-1},{text:"`*ByText`",id:"bytext",depth:3,charIndex:-1},{text:"`*ByHintText`",id:"byhinttext",depth:3,charIndex:-1},{text:"`*ByTestId`",id:"bytestid",depth:3,charIndex:-1},{text:"Common options",id:"common-options",depth:3,charIndex:9664},{text:"`includeHiddenElements` option",id:"includehiddenelements-option",depth:4,charIndex:-1},{text:"TextMatch type",id:"textmatch-type",depth:2,charIndex:10378},{text:"Examples",id:"examples",depth:3,charIndex:10513},{text:"Options",id:"options-1",depth:3,charIndex:-1},{text:"Precision",id:"precision",depth:4,charIndex:10614},{text:"Normalization",id:"normalization",depth:4,charIndex:11397},{text:"Legacy unit testing helpers",id:"legacy-unit-testing-helpers",depth:2,charIndex:12663},{text:"`UNSAFE_ByType`",id:"unsafe_bytype",depth:3,charIndex:-1},{text:"`UNSAFE_ByProps`",id:"unsafe_byprops",depth:3,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/queries.mdx"},{title:"`render` API",routePath:"/react-native-testing-library/14.x/docs/api/render",lang:"",toc:[{text:"`render` function",id:"render-function",depth:2,charIndex:-1},{text:"Options",id:"options",depth:3,charIndex:670},{text:"`wrapper`",id:"wrapper",depth:4,charIndex:-1},{text:"`concurrentRoot`",id:"concurrentroot",depth:4,charIndex:-1},{text:"`createNodeMock`",id:"createnodemock",depth:4,charIndex:-1},{text:"Result",id:"result",depth:3,charIndex:1952}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/render.mdx"},{title:"`screen` object",routePath:"/react-native-testing-library/14.x/docs/api/screen",lang:"",toc:[{text:"`...queries`",id:"queries",depth:3,charIndex:-1},{text:"Example",id:"example",depth:4,charIndex:549},{text:"`rerender`",id:"rerender",depth:3,charIndex:-1},{text:"`unmount`",id:"unmount",depth:3,charIndex:-1},{text:"`debug`",id:"debug",depth:3,charIndex:-1},{text:"`message` option",id:"message-option",depth:4,charIndex:-1},{text:"`mapProps` option",id:"mapprops-option",depth:4,charIndex:-1},{text:"`toJSON`",id:"tojson",depth:3,charIndex:-1},{text:"`container`",id:"container",depth:3,charIndex:-1},{text:"`root`",id:"root",depth:3,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/api/screen.mdx"},{title:"Community resources",routePath:"/react-native-testing-library/14.x/docs/guides/community-resources",lang:"",toc:[{text:"Recommended content",id:"recommended-content",depth:2,charIndex:3},{text:"Older, potentially outdated content",id:"older-potentially-outdated-content",depth:2,charIndex:601}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/guides/community-resources.mdx"},{title:"FAQ",routePath:"/react-native-testing-library/14.x/docs/guides/faq",lang:"",toc:[{text:"Can I test the native features of React Native apps?",id:"can-i-test-the-native-features-of-react-native-apps",depth:2,charIndex:3},{text:"Should I use/migrate to `screen` queries?",id:"should-i-usemigrate-to-screen-queries",depth:2,charIndex:-1},{text:"Should I use/migrate to User Event interactions?",id:"should-i-usemigrate-to-user-event-interactions",depth:2,charIndex:1589}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/guides/faq.mdx"},{title:"How should I query?",routePath:"/react-native-testing-library/14.x/docs/guides/how-to-query",lang:"",toc:[{text:"Query parts",id:"query-parts",depth:2,charIndex:273},{text:"Query variant",id:"query-variant",depth:2,charIndex:521},{text:"Idiomatic query variants",id:"idiomatic-query-variants",depth:3,charIndex:1344},{text:"Query predicate",id:"query-predicate",depth:2,charIndex:2297},{text:"Idiomatic query predicates",id:"idiomatic-query-predicates",depth:3,charIndex:3071},{text:"1. By Role query",id:"1-by-role-query",depth:3,charIndex:-1},{text:"Name option",id:"name-option",depth:4,charIndex:-1},{text:"2. Text input queries",id:"2-text-input-queries",depth:3,charIndex:-1},{text:"3. Other accessible queries",id:"3-other-accessible-queries",depth:3,charIndex:-1},{text:"4. Test ID query",id:"4-test-id-query",depth:3,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/guides/how-to-query.mdx"},{title:"React 19 & Suspense Support",routePath:"/react-native-testing-library/14.x/docs/guides/react-19",lang:"",toc:[{text:"New async APIs",id:"new-async-apis",depth:2,charIndex:384},{text:"APIs that remain unchanged",id:"apis-that-remain-unchanged",depth:2,charIndex:746},{text:"What changes in your tests",id:"what-changes-in-your-tests",depth:2,charIndex:1061},{text:"Making tests async",id:"making-tests-async",depth:3,charIndex:1091},{text:"When to use async APIs",id:"when-to-use-async-apis",depth:3,charIndex:1263},{text:"Migration strategy",id:"migration-strategy",depth:2,charIndex:1502},{text:"New projects",id:"new-projects",depth:3,charIndex:1524},{text:"Existing projects",id:"existing-projects",depth:3,charIndex:1667},{text:"Migration",id:"migration",depth:3,charIndex:1907}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/guides/react-19.mdx"},{title:"Troubleshooting",routePath:"/react-native-testing-library/14.x/docs/guides/troubleshooting",lang:"",toc:[{text:"Matching React Native, React & Test Renderer versions",id:"matching-react-native-react--test-renderer-versions",depth:2,charIndex:116},{text:"Example repository",id:"example-repository",depth:2,charIndex:1014},{text:"Undefined component error",id:"undefined-component-error",depth:2,charIndex:1263},{text:"Mocking React Native",id:"mocking-react-native",depth:3,charIndex:2119},{text:"Act warnings",id:"act-warnings",depth:2,charIndex:2381}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/guides/troubleshooting.mdx"},{title:"Migration to built-in Jest matchers",routePath:"/react-native-testing-library/14.x/docs/migration/jest-matchers",lang:"",toc:[{text:"General notes",id:"general-notes",depth:2,charIndex:119},{text:"Usage",id:"usage",depth:2,charIndex:533},{text:"Gradual migration",id:"gradual-migration",depth:3,charIndex:715},{text:"Migration details",id:"migration-details",depth:2,charIndex:946},{text:"Matchers not requiring changes",id:"matchers-not-requiring-changes",depth:3,charIndex:967},{text:"Replaced matchers",id:"replaced-matchers",depth:3,charIndex:1274},{text:"Added matchers",id:"added-matchers",depth:3,charIndex:1667},{text:"Noteworthy details",id:"noteworthy-details",depth:3,charIndex:1729}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/jest-matchers.mdx"},{title:"Migration to 11.x",routePath:"/react-native-testing-library/14.x/docs/migration/previous/v11",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:153},{text:"Update to Jest 28 if you use fake timers",id:"update-to-jest-28-if-you-use-fake-timers",depth:3,charIndex:173},{text:"Refactor legacy `waitForOptions` position",id:"refactor-legacy-waitforoptions-position",depth:3,charIndex:-1},{text:'Triggering non-touch events on targets with `pointerEvents="box-none"` prop',id:"triggering-non-touch-events-on-targets-with-pointereventsbox-none-prop",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:1263}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/previous/v11.mdx"},{title:"Migration to 12.x",routePath:"/react-native-testing-library/14.x/docs/migration/previous/v12",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:484},{text:"1. All queries exclude elements hidden from accessibility by default",id:"1-all-queries-exclude-elements-hidden-from-accessibility-by-default",depth:3,charIndex:504},{text:"2. `*ByRole` queries now return only accessibility elements",id:"2-byrole-queries-now-return-only-accessibility-elements",depth:3,charIndex:-1},{text:"Examples",id:"examples",depth:4,charIndex:1510},{text:"3. `*ByText`, `*ByDisplayValue`, `*ByPlaceholderText` queries now return host elements",id:"3-bytext-bydisplayvalue-byplaceholdertext-queries-now-return-host-elements",depth:3,charIndex:-1},{text:"4. `container` API has been renamed to `UNSAFE_root`.",id:"4-container-api-has-been-renamed-to-unsafe_root",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:2917}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/previous/v12.mdx"},{title:"Migration to 2.x",routePath:"/react-native-testing-library/14.x/docs/migration/previous/v2",lang:"",toc:[{text:"Dropping Node 8",id:"dropping-node-8",depth:2,charIndex:100},{text:"Auto Cleanup",id:"auto-cleanup",depth:2,charIndex:325},{text:"WaitFor API changes",id:"waitfor-api-changes",depth:2,charIndex:1248},{text:"Removed global `debug` function",id:"removed-global-debug-function",depth:2,charIndex:-1},{text:"Removed global `shallow` function",id:"removed-global-shallow-function",depth:2,charIndex:-1},{text:"Removed functions",id:"removed-functions",depth:2,charIndex:2145},{text:"Some `ByTestId` queries behavior changes",id:"some-bytestid-queries-behavior-changes",depth:2,charIndex:-1},{text:"Deprecated `flushMicrotasksQueue`",id:"deprecated-flushmicrotasksqueue",depth:2,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/previous/v2.mdx"},{title:"Migration to 7.x",routePath:"/react-native-testing-library/14.x/docs/migration/previous/v7",lang:"",toc:[{text:"Guide for `react-native-testing-library` users",id:"guide-for-react-native-testing-library-users",depth:2,charIndex:-1},{text:"Renaming the library",id:"renaming-the-library",depth:3,charIndex:452},{text:"New aliases",id:"new-aliases",depth:3,charIndex:1352},{text:"Renaming `ByPlaceholder` queries",id:"renaming-byplaceholder-queries",depth:3,charIndex:-1},{text:"`fireEvent` support for disabled components",id:"fireevent-support-for-disabled-components",depth:3,charIndex:-1},{text:"Guide for `@testing-library/react-native` users",id:"guide-for-testing-libraryreact-native-users",depth:2,charIndex:-1},{text:'Renaming "wait" helpers',id:"renaming-wait-helpers",depth:3,charIndex:2874},{text:"Changes to `ByTestId` queries",id:"changes-to-bytestid-queries",depth:3,charIndex:-1},{text:"No `ByTitle` queries",id:"no-bytitle-queries",depth:3,charIndex:-1},{text:"No custom Jest configuration",id:"no-custom-jest-configuration",depth:3,charIndex:3628},{text:"Cleanup is included by default",id:"cleanup-is-included-by-default",depth:3,charIndex:3917},{text:"No NativeTestInstance abstraction",id:"no-nativetestinstance-abstraction",depth:3,charIndex:4313},{text:"No `container` nor `baseElement` returned from `render`",id:"no-container-nor-baseelement-returned-from-render",depth:3,charIndex:-1},{text:"Firing events changes",id:"firing-events-changes",depth:3,charIndex:4817}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/previous/v7.mdx"},{title:"Migration to 9.x",routePath:"/react-native-testing-library/14.x/docs/migration/previous/v9",lang:"",toc:[{text:"Support for text match options a.k.a string precision API",id:"support-for-text-match-options-aka-string-precision-api",depth:2,charIndex:284},{text:"Reverted matching text across several nodes",id:"reverted-matching-text-across-several-nodes",depth:2,charIndex:924},{text:"Future plans",id:"future-plans",depth:2,charIndex:1437}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/previous/v9.mdx"},{title:"Migration to 13.x",routePath:"/react-native-testing-library/14.x/docs/migration/v13",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:228},{text:"Supported React and React Native versions",id:"supported-react-and-react-native-versions",depth:3,charIndex:248},{text:"Concurrent rendering by default",id:"concurrent-rendering-by-default",depth:3,charIndex:593},{text:"Extend Jest matchers by default",id:"extend-jest-matchers-by-default",depth:3,charIndex:980},{text:"Removed deprecated `*ByAccessibilityState` queries",id:"removed-deprecated-byaccessibilitystate-queries",depth:3,charIndex:-1},{text:"Removed deprecated `*ByAccessibilityValue` queries",id:"removed-deprecated-byaccessibilityvalue-queries",depth:3,charIndex:-1},{text:"Removed Jest preset",id:"removed-jest-preset",depth:3,charIndex:2245},{text:"Removed `debug.shallow`",id:"removed-debugshallow",depth:3,charIndex:-1},{text:"Changes to accessibility label calculation",id:"changes-to-accessibility-label-calculation",depth:3,charIndex:2565},{text:"Other changes",id:"other-changes",depth:2,charIndex:2798},{text:"Removed host component names autodetection",id:"removed-host-component-names-autodetection",depth:3,charIndex:2815},{text:"Use React implementation of `act` instead of React Test Renderer one",id:"use-react-implementation-of-act-instead-of-react-test-renderer-one",depth:3,charIndex:-1},{text:"Updated `flushMicroTasks` internal method",id:"updated-flushmicrotasks-internal-method",depth:3,charIndex:-1},{text:"Full Changelog",id:"full-changelog",depth:2,charIndex:3147}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/v13.mdx"},{title:"Migration to 14.x",routePath:"/react-native-testing-library/14.x/docs/migration/v14",lang:"",toc:[{text:"Breaking changes",id:"breaking-changes",depth:2,charIndex:101},{text:"Test Renderer replaces React Test Renderer",id:"test-renderer-replaces-react-test-renderer",depth:3,charIndex:121},{text:"1. Update dependencies",id:"1-update-dependencies",depth:4,charIndex:737},{text:"2. Update type imports (if needed)",id:"2-update-type-imports-if-needed",depth:4,charIndex:868},{text:"`container` API reintroduced",id:"container-api-reintroduced",depth:3,charIndex:-1},{text:"`render` is now async by default",id:"render-is-now-async-by-default",depth:3,charIndex:-1},{text:"Step-by-step migration guide",id:"step-by-step-migration-guide",depth:4,charIndex:2195},{text:"Complete example",id:"complete-example",depth:4,charIndex:2585},{text:"Benefits of async `render`",id:"benefits-of-async-render",depth:4,charIndex:-1},{text:"`update` alias removed",id:"update-alias-removed",depth:3,charIndex:-1},{text:"`getQueriesForElement` export removed",id:"getqueriesforelement-export-removed",depth:3,charIndex:-1},{text:"`renderHook` is now async by default",id:"renderhook-is-now-async-by-default",depth:3,charIndex:-1},{text:"Step-by-step migration guide",id:"step-by-step-migration-guide-1",depth:4,charIndex:4212},{text:"Complete example",id:"complete-example-1",depth:4,charIndex:4473},{text:"Benefits of async `renderHook`",id:"benefits-of-async-renderhook",depth:4,charIndex:-1},{text:"`fireEvent` is now async by default",id:"fireevent-is-now-async-by-default",depth:3,charIndex:-1},{text:"Text string validation now enforced by default",id:"text-string-validation-now-enforced-by-default",depth:3,charIndex:5186},{text:"`act` is now async by default",id:"act-is-now-async-by-default",depth:3,charIndex:-1},{text:"Step-by-step migration guide",id:"step-by-step-migration-guide-2",depth:4,charIndex:6654},{text:"Complete example",id:"complete-example-2",depth:4,charIndex:6945},{text:"Benefits of async `act`",id:"benefits-of-async-act",depth:4,charIndex:-1}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/migration/v14.mdx"},{title:"Introduction",routePath:"/react-native-testing-library/14.x/docs/start/intro",lang:"",toc:[{text:"The problem",id:"the-problem",depth:2,charIndex:3},{text:"This solution",id:"this-solution",depth:2,charIndex:479},{text:"Example",id:"example",depth:2,charIndex:982}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/start/intro.md"},{title:"Quick Start",routePath:"/react-native-testing-library/14.x/docs/start/quick-start",lang:"",toc:[{text:"Installation",id:"installation",depth:2,charIndex:3},{text:"Jest matchers",id:"jest-matchers",depth:3,charIndex:325},{text:"ESLint plugin",id:"eslint-plugin",depth:3,charIndex:563}],frontmatter:{},version:"14.x",_relativePath:"14.x/docs/start/quick-start.mdx"},{title:"",routePath:"/react-native-testing-library/14.x/",lang:"",toc:[],frontmatter:{pageType:"home",hero:{name:"React Native",text:"Testing Library",image:{src:"/img/owl.png"},tagline:"Helps you to write better tests with less effort.",actions:[{theme:"brand",text:"Quick Start",link:"/docs/start/quick-start"},{theme:"alt",text:"Explore API",link:"/docs/api"}]},features:[{title:"Maintainable",details:"Write maintainable tests for your React Native apps.",icon:"✨"},{title:"Reliable",details:"Promotes testing public APIs and avoiding implementation details.",icon:"βœ…"},{title:"Community Driven",details:"Supported by React Native community and its core contributors.",icon:"❀️"}]},version:"14.x",_relativePath:"14.x/index.md"},{title:"",routePath:"/react-native-testing-library/404",lang:"",toc:[],frontmatter:{pageType:"custom"},version:"13.x",_relativePath:"404.mdx"}],markdown:{showLineNumbers:!1,defaultWrapCode:!1,codeHighlighter:"prism"}}},5365:function(e,t,n){"use strict";var r=n(3935),i=n.t(r,2),a=n(745),o=n.t(a,2),s=n(5893),l=n(436),c=n(8995),d=n(5552),u=n(7294),h=n(5378),p=n(405),x=Object.assign||function(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{},r=window.Promise||function(e){function t(){}e(t,t)},i=function(){for(var e=arguments.length,t=Array(e),n=0;n0&&void 0!==arguments[0]?arguments[0]:{},t=e.target,n=function(){var e={width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,left:0,top:0,right:0,bottom:0},t=void 0,n=void 0;if(h.container)if(h.container instanceof Object)t=(e=x({},e,h.container)).width-e.left-e.right-2*h.margin,n=e.height-e.top-e.bottom-2*h.margin;else{var r=(g(h.container)?h.container:document.querySelector(h.container)).getBoundingClientRect();e=x({},e,{width:r.width,height:r.height,left:r.left,top:r.top})}t=t||e.width-2*h.margin,n=n||e.height-2*h.margin;var i=p.zoomedHd||p.original,a=f(i)?t:i.naturalWidth||t,o=f(i)?n:i.naturalHeight||n,s=i.getBoundingClientRect(),l=s.top,c=s.left,d=s.width,u=s.height,m=Math.min(Math.min(Math.max(d,a),t)/d,Math.min(Math.max(u,o),n)/u),v=(-c+(t-d)/2+h.margin+e.left)/m,y=(-l+(n-u)/2+h.margin+e.top)/m,b="scale("+m+") translate3d("+v+"px, "+y+"px, 0)";p.zoomed.style.transform=b,p.zoomedHd&&(p.zoomedHd.style.transform=b)};return new r(function(e){if(t&&-1===l.indexOf(t)||p.zoomed)return void e(k);if(t)p.original=t;else{if(!(l.length>0))return void e(k);p.original=l[0]}if(p.original.dispatchEvent(w("medium-zoom:open",{detail:{zoom:k}})),u=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,d=!0,p.zoomed=b(p.original),document.body.appendChild(m),h.template){var r=g(h.template)?h.template:document.querySelector(h.template);p.template=document.createElement("div"),p.template.appendChild(r.content.cloneNode(!0)),document.body.appendChild(p.template)}if(p.original.parentElement&&"PICTURE"===p.original.parentElement.tagName&&p.original.currentSrc&&(p.zoomed.src=p.original.currentSrc),document.body.appendChild(p.zoomed),window.requestAnimationFrame(function(){document.body.classList.add("medium-zoom--opened")}),p.original.classList.add("medium-zoom-image--hidden"),p.zoomed.classList.add("medium-zoom-image--opened"),p.zoomed.addEventListener("click",o),p.zoomed.addEventListener("transitionend",function t(){d=!1,p.zoomed.removeEventListener("transitionend",t),p.original.dispatchEvent(w("medium-zoom:opened",{detail:{zoom:k}})),e(k)}),p.original.getAttribute("data-zoom-src")){p.zoomedHd=p.zoomed.cloneNode(),p.zoomedHd.removeAttribute("srcset"),p.zoomedHd.removeAttribute("sizes"),p.zoomedHd.removeAttribute("loading"),p.zoomedHd.src=p.zoomed.getAttribute("data-zoom-src"),p.zoomedHd.onerror=function(){clearInterval(i),console.warn("Unable to reach the zoom image target "+p.zoomedHd.src),p.zoomedHd=null,n()};var i=setInterval(function(){p.zoomedHd.complete&&(clearInterval(i),p.zoomedHd.classList.add("medium-zoom-image--opened"),p.zoomedHd.addEventListener("click",o),document.body.appendChild(p.zoomedHd),n())},10)}else if(p.original.hasAttribute("srcset")){p.zoomedHd=p.zoomed.cloneNode(),p.zoomedHd.removeAttribute("sizes"),p.zoomedHd.removeAttribute("loading");var a=p.zoomedHd.addEventListener("load",function(){p.zoomedHd.removeEventListener("load",a),p.zoomedHd.classList.add("medium-zoom-image--opened"),p.zoomedHd.addEventListener("click",o),document.body.appendChild(p.zoomedHd),n()})}else n()})},o=function(){return new r(function(e){if(d||!p.original)return void e(k);d=!0,document.body.classList.remove("medium-zoom--opened"),p.zoomed.style.transform="",p.zoomedHd&&(p.zoomedHd.style.transform=""),p.template&&(p.template.style.transition="opacity 150ms",p.template.style.opacity=0),p.original.dispatchEvent(w("medium-zoom:close",{detail:{zoom:k}})),p.zoomed.addEventListener("transitionend",function t(){p.original.classList.remove("medium-zoom-image--hidden"),document.body.removeChild(p.zoomed),p.zoomedHd&&document.body.removeChild(p.zoomedHd),document.body.removeChild(m),p.zoomed.classList.remove("medium-zoom-image--opened"),p.template&&document.body.removeChild(p.template),d=!1,p.zoomed.removeEventListener("transitionend",t),p.original.dispatchEvent(w("medium-zoom:closed",{detail:{zoom:k}})),p.original=null,p.zoomed=null,p.zoomedHd=null,p.template=null,e(k)})})},s=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.target;return p.original?o():a({target:t})},l=[],c=[],d=!1,u=0,h=n,p={original:null,zoomed:null,zoomedHd:null,template:null};"[object Object]"===Object.prototype.toString.call(t)?h=t:(t||"string"==typeof t)&&i(t);var m=y((h=x({margin:0,background:"#fff",scrollOffset:40,container:null,template:null},h)).background);document.addEventListener("click",function(e){var t=e.target;if(t===m)return void o();-1!==l.indexOf(t)&&s({target:t})}),document.addEventListener("keyup",function(e){var t=e.key||e.keyCode;("Escape"===t||"Esc"===t||27===t)&&o()}),document.addEventListener("scroll",function(){if(!d&&p.original){var e=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;Math.abs(u-e)>h.scrollOffset&&setTimeout(o,150)}}),window.addEventListener("resize",o);var k={open:a,close:o,toggle:s,update:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(e.background&&(m.style.background=e.background),e.container&&e.container instanceof Object&&(e.container=x({},h.container,e.container)),e.template){var t=g(e.template)?e.template:document.querySelector(e.template);e.template=t}return h=x({},h,e),l.forEach(function(e){e.dispatchEvent(w("medium-zoom:update",{detail:{zoom:k}}))}),k},clone:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return e(x({},h,t))},attach:i,detach:function(){for(var e=arguments.length,t=Array(e),n=0;n0?t.reduce(function(e,t){return[].concat(e,v(t))},[]):l;return r.forEach(function(e){e.classList.remove("medium-zoom-image"),e.dispatchEvent(w("medium-zoom:detach",{detail:{zoom:k}}))}),l=l.filter(function(e){return -1===r.indexOf(e)}),k},on:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return l.forEach(function(r){r.addEventListener("medium-zoom:"+e,t,n)}),c.push({type:"medium-zoom:"+e,listener:t,options:n}),k},off:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return l.forEach(function(r){r.removeEventListener("medium-zoom:"+e,t,n)}),c=c.filter(function(n){return n.type!=="medium-zoom:"+e||n.listener.toString()!==t.toString()}),k},getOptions:function(){return h},getImages:function(){return l},getZoomedImage:function(){return p.original}};return k};n(8046);var I=()=>{window.va||(window.va=function(...e){(window.vaq=window.vaq||[]).push(e)})};function D(){return"undefined"!=typeof window}function E(){return"production"}function F(){return(D()?window.vam:E())||"production"}function A(){return"development"===F()}var C=function(e={debug:!0}){var t;if(!D())return;!function(e="auto"){if("auto"===e){window.vam=E();return}window.vam=e}(e.mode),I(),e.beforeSend&&(null==(t=window.va)||t.call(window,"beforeSend",e.beforeSend));let n=e.scriptSrc?e.scriptSrc:A()?"https://va.vercel-scripts.com/v1/script.debug.js":e.basePath?`${e.basePath}/insights/script.js`:"/_vercel/insights/script.js";if(document.head.querySelector(`script[src*="${n}"]`))return;let r=document.createElement("script");r.src=n,r.defer=!0,r.dataset.sdkn="@vercel/analytics"+(e.framework?`/${e.framework}`:""),r.dataset.sdkv="1.5.0",e.disableAutoTrack&&(r.dataset.disableAutoTrack="1"),e.endpoint?r.dataset.endpoint=e.endpoint:e.basePath&&(r.dataset.endpoint=`${e.basePath}/insights`),e.dsn&&(r.dataset.dsn=e.dsn),r.onerror=()=>{let e=A()?"Please check if any ad blockers are enabled and try again.":"Be sure to enable Web Analytics for your project and deploy again. See https://vercel.com/docs/analytics/quickstart for more information.";console.log(`[Vercel Web Analytics] Failed to load script from ${n}. ${e}`)},A()&&!1===e.debug&&(r.dataset.debug="false"),document.head.appendChild(r)};let j=[[function(e){let{pathname:t}=(0,l.TH)(),{selector:n=".rspress-doc img",options:r={}}=e;return(0,u.useEffect)(()=>{let e,t=setTimeout(()=>{e=k(document.querySelectorAll(n),{...r,background:"var(--rp-c-bg)"})},100);return()=>{clearTimeout(t),null==e||e.detach(),null==e||e.close()}},[t]),null},{}],[function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return u.useLayoutEffect(()=>{C(e)},[]),null},{mode:"production"}]];async function P(e){var t,n;let r=(0,l.Ww)(e);if(r){let e=await r.preload(),t=(0,c.bw)(r.filePath),i=h.Z.pages.find(e=>{let t=e=>e.replace(/\/$/,"").toLowerCase();return(0,l.pV)(t(e.routePath),t(r.path))}),a=encodeURIComponent(t),o=(null==(n=e.default.__RSPRESS_PAGE_META)?void 0:n[a])||{},{toc:s=[],title:d="",frontmatter:u={},...p}=c.I6.test(r.filePath)?o:e;return{siteData:h.Z,page:{...p,pagePath:t,...i,pageType:(null==u?void 0:u.pageType)||"doc",title:d,frontmatter:u,toc:s}}}let i=h.Z.lang||"",a=(null==(t=h.Z.multiVersion)?void 0:t.default)||"";if(h.Z.lang&&"undefined"!=typeof window){let e=location.pathname.replace(h.Z.base,"").split("/").slice(0,2);if(h.Z.locales.length){let t=h.Z.locales.find(t=>{let{lang:n}=t;return e.includes(n)});t&&(i=t.lang)}if(h.Z.multiVersion.versions){let t=h.Z.multiVersion.versions.find(t=>e.includes(t));t&&(a=t)}}return{siteData:h.Z,page:{pagePath:"",pageType:"404",routePath:"/404",lang:i,frontmatter:{},title:"404",toc:[],version:a,_filepath:"",_relativePath:""}}}function S(e){let{helmetContext:t}=e,{setData:n,data:r}=(0,u.useContext)(l.R0),i=r.page.frontmatter||{},{pathname:a,search:o}=(0,l.TH)(),c=new URLSearchParams(o),h="globalUIComponents",x=!1===i[h]||"0"===c.get(h);return(0,u.useLayoutEffect)(()=>{!async function(){try{let e=await P(a);null==n||n(e)}catch(e){console.log(e)}}()},[a,n]),(0,s.jsxs)(p.B6,{context:t,children:[(0,s.jsx)(d.ZP.Layout,{}),!x&&j.map((e,t)=>{if(Array.isArray(e)){let[n,r]=e;return u.createElement(n,{key:t,...r})}return u.createElement(e,{key:t})})]})}n(6297),n(149);var T={"react-dom":function(e){e.exports=i},"react-dom/client":function(e){e.exports=o}},N={};let _=h.Z.ssg;!async function(){let e=document.getElementById("root"),t=async()=>{let e=await P(window.location.pathname);return function(){let[t,n]=(0,u.useState)(e),[r,i]=(0,d.ls)();return(0,s.jsx)(l.Ni.Provider,{value:(0,u.useMemo)(()=>({theme:r,setTheme:i}),[r,i]),children:(0,s.jsx)(l.R0.Provider,{value:(0,u.useMemo)(()=>({data:t,setData:n}),[t,n]),children:(0,s.jsx)(l.VK,{children:(0,s.jsx)(S,{})})})})}},n=await t();{let{createRoot:t,hydrateRoot:r}=function e(t){var n=N[t];if(void 0!==n)return n.exports;var r=N[t]={exports:{}};return T[t](r,r.exports,e),r.exports}("react-dom/client");(0,c.yv)()&&_?r(e,(0,s.jsx)(n,{})):t(e).render((0,s.jsx)(n,{}))}}()},5751:function(e){e.exports=function(e){return e&&e.__esModule?e:{default:e}},e.exports.__esModule=!0,e.exports.default=e.exports},65:function(e,t,n){"use strict";n.d(t,{Zo:()=>s,ah:()=>a});var r=n(7294);let i=r.createContext({});function a(e){let t=r.useContext(i);return r.useMemo(()=>"function"==typeof e?e(t):{...t,...e},[t,e])}let o={};function s({components:e,children:t,disableParentContext:n}){let s;return s=n?"function"==typeof e?e({}):e||o:a(e),r.createElement(i.Provider,{value:s},t)}},8995:function(e,t,n){"use strict";n.d(t,{$U:()=>v,E9:()=>D,I6:()=>a,Kw:()=>m,Qj:()=>x,_f:()=>u,bw:()=>c,lm:()=>d,mi:()=>p,nY:()=>h,pJ:()=>I,pZ:()=>f,rp:()=>o,t6:()=>s,tz:()=>k,xM:()=>y,xf:()=>g,yc:()=>w,yv:()=>l});let r=/\?.*$/s,i=/#.*$/s,a=/\.mdx?$/,o="rspress-theme-appearance",s="search_index",l=()=>!0,c=e=>e.replace(i,"").replace(r,"");function d(e){return e.replace(/#.*$/,"")}let u=()=>!0;function h(e){return"/"===e.charAt(0)||g(e)?e:`/${e}`}function p(e){return"/"===e.charAt(e.length-1)?e:`${e}/`}function x(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function m(e){return x(h(function(e){let t=e.replace(/\\/g,"/"),n=t.startsWith("/"),r=t.split("/"),i=[];for(let e of r)"."===e||""===e||(".."===e?i.length>0&&".."!==i[i.length-1]?i.pop():n&&i.push(".."):i.push(e));let a=i.join("/");return n&&(a=`/${a}`),a}(e)))}function g(e=""){return e.startsWith("http://")||e.startsWith("https://")||e.startsWith("mailto:")||e.startsWith("tel:")}function f(e=""){return/^\s*data:/i.test(e)}function v(e,t,n,r="",i=!1,a=!1){let o=D(e,r);(!o||a)&&(o=i?"/index":"/index.html"),o.endsWith("/")&&(o+=i?"/index":"/index.html");let s="",l="",c="",d=o.split("/").filter(Boolean);return n.current&&n.current!==n.default&&(s=d.shift()||""),t.target!==t.default?(l=t.target,t.current!==t.default&&d.shift()):d.shift(),c=d.join("/")||"",(s||l)&&!c&&(c=i?"index":"index.html"),I(h([s,l,c].filter(Boolean).join("/")),r)}function y(e,t,n="",r=!1,i=!1){let a=D(e,n);(!a||i)&&(a=r?"/index":"/index.html");let o="",s=a.split("/").filter(Boolean);t.target!==t.default?(o=t.target,t.current!==t.default&&s.shift()):s.shift();let l=s.join("/")||"";return o&&!l&&(l=r?"index":"index.html"),I(h([o,l].filter(Boolean).join("/")),n)}let b=e=>{let[t,n=""]=e.split("#");return{url:t,hash:n}};function w(e,t=!1){if(!e)return"/";if(g(e))return e;let{url:n,hash:r}=b(decodeURIComponent(e));return t||n.endsWith(".html")||(n.endsWith("/")?n+="index.html":n+=".html"),t&&n.endsWith("/")&&(n+="index"),t&&n.endsWith(".html")&&(n=n.replace(/\.html$/,"")),h(r?`${n}#${r}`:n)}function k(e,t){return h(e).replace(m(t),"")}function I(e,t){let n=h(e),r=m(t);return n.startsWith(r)?n:`${r}${n}`}function D(e,t){return h(e).replace(RegExp(`^${m(t)}`),"")}},5552:function(e,t,n){"use strict";let r;n.d(t,{qx:()=>nS,g2:()=>r0,zx:()=>rh,xK:()=>rv,JL:()=>rZ,SU:()=>r7,ls:()=>rd,rU:()=>nm,xB:()=>rb,pU:()=>it,OK:()=>io,TJ:()=>nY,Qe:()=>r9,mQ:()=>ia,O9:()=>rk,BZ:()=>rf,mi:()=>rx,ZP:()=>ig,Vp:()=>im,ol:()=>ix});var i,a,o,s,l={};n.r(l),n.d(l,{onSearch:()=>tB}),n(6612);var c=n(5893),d=n(65),u=n(436);let h=/[\0-\x1F!-,\.\/:-@\[-\^`\{-\xA9\xAB-\xB4\xB6-\xB9\xBB-\xBF\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0378\u0379\u037E\u0380-\u0385\u0387\u038B\u038D\u03A2\u03F6\u0482\u0530\u0557\u0558\u055A-\u055F\u0589-\u0590\u05BE\u05C0\u05C3\u05C6\u05C8-\u05CF\u05EB-\u05EE\u05F3-\u060F\u061B-\u061F\u066A-\u066D\u06D4\u06DD\u06DE\u06E9\u06FD\u06FE\u0700-\u070F\u074B\u074C\u07B2-\u07BF\u07F6-\u07F9\u07FB\u07FC\u07FE\u07FF\u082E-\u083F\u085C-\u085F\u086B-\u089F\u08B5\u08C8-\u08D2\u08E2\u0964\u0965\u0970\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09F2-\u09FB\u09FD\u09FF\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A76-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF0-\u0AF8\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B54\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B70\u0B72-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BF0-\u0BFF\u0C0D\u0C11\u0C29\u0C3A-\u0C3C\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5B-\u0C5F\u0C64\u0C65\u0C70-\u0C7F\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDD\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0CFF\u0D0D\u0D11\u0D45\u0D49\u0D4F-\u0D53\u0D58-\u0D5E\u0D64\u0D65\u0D70-\u0D79\u0D80\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DE5\u0DF0\u0DF1\u0DF4-\u0E00\u0E3B-\u0E3F\u0E4F\u0E5A-\u0E80\u0E83\u0E85\u0E8B\u0EA4\u0EA6\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F01-\u0F17\u0F1A-\u0F1F\u0F2A-\u0F34\u0F36\u0F38\u0F3A-\u0F3D\u0F48\u0F6D-\u0F70\u0F85\u0F98\u0FBD-\u0FC5\u0FC7-\u0FFF\u104A-\u104F\u109E\u109F\u10C6\u10C8-\u10CC\u10CE\u10CF\u10FB\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u1360-\u137F\u1390-\u139F\u13F6\u13F7\u13FE-\u1400\u166D\u166E\u1680\u169B-\u169F\u16EB-\u16ED\u16F9-\u16FF\u170D\u1715-\u171F\u1735-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17D4-\u17D6\u17D8-\u17DB\u17DE\u17DF\u17EA-\u180A\u180E\u180F\u181A-\u181F\u1879-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191F\u192C-\u192F\u193C-\u1945\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DA-\u19FF\u1A1C-\u1A1F\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1AA6\u1AA8-\u1AAF\u1AC1-\u1AFF\u1B4C-\u1B4F\u1B5A-\u1B6A\u1B74-\u1B7F\u1BF4-\u1BFF\u1C38-\u1C3F\u1C4A-\u1C4C\u1C7E\u1C7F\u1C89-\u1C8F\u1CBB\u1CBC\u1CC0-\u1CCF\u1CD3\u1CFB-\u1CFF\u1DFA\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FBD\u1FBF-\u1FC1\u1FC5\u1FCD-\u1FCF\u1FD4\u1FD5\u1FDC-\u1FDF\u1FED-\u1FF1\u1FF5\u1FFD-\u203E\u2041-\u2053\u2055-\u2070\u2072-\u207E\u2080-\u208F\u209D-\u20CF\u20F1-\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F-\u215F\u2189-\u24B5\u24EA-\u2BFF\u2C2F\u2C5F\u2CE5-\u2CEA\u2CF4-\u2CFF\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D70-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E00-\u2E2E\u2E30-\u3004\u3008-\u3020\u3030\u3036\u3037\u303D-\u3040\u3097\u3098\u309B\u309C\u30A0\u30FB\u3100-\u3104\u3130\u318F-\u319F\u31C0-\u31EF\u3200-\u33FF\u4DC0-\u4DFF\u9FFD-\u9FFF\uA48D-\uA4CF\uA4FE\uA4FF\uA60D-\uA60F\uA62C-\uA63F\uA673\uA67E\uA6F2-\uA716\uA720\uA721\uA789\uA78A\uA7C0\uA7C1\uA7CB-\uA7F4\uA828-\uA82B\uA82D-\uA83F\uA874-\uA87F\uA8C6-\uA8CF\uA8DA-\uA8DF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA954-\uA95F\uA97D-\uA97F\uA9C1-\uA9CE\uA9DA-\uA9DF\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A-\uAA5F\uAA77-\uAA79\uAAC3-\uAADA\uAADE\uAADF\uAAF0\uAAF1\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F\uAB5B\uAB6A-\uAB6F\uABEB\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uE000-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB29\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBB2-\uFBD2\uFD3E-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFC-\uFDFF\uFE10-\uFE1F\uFE30-\uFE32\uFE35-\uFE4C\uFE50-\uFE6F\uFE75\uFEFD-\uFF0F\uFF1A-\uFF20\uFF3B-\uFF3E\uFF40\uFF5B-\uFF65\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFFF]|\uD800[\uDC0C\uDC27\uDC3B\uDC3E\uDC4E\uDC4F\uDC5E-\uDC7F\uDCFB-\uDD3F\uDD75-\uDDFC\uDDFE-\uDE7F\uDE9D-\uDE9F\uDED1-\uDEDF\uDEE1-\uDEFF\uDF20-\uDF2C\uDF4B-\uDF4F\uDF7B-\uDF7F\uDF9E\uDF9F\uDFC4-\uDFC7\uDFD0\uDFD6-\uDFFF]|\uD801[\uDC9E\uDC9F\uDCAA-\uDCAF\uDCD4-\uDCD7\uDCFC-\uDCFF\uDD28-\uDD2F\uDD64-\uDDFF\uDF37-\uDF3F\uDF56-\uDF5F\uDF68-\uDFFF]|\uD802[\uDC06\uDC07\uDC09\uDC36\uDC39-\uDC3B\uDC3D\uDC3E\uDC56-\uDC5F\uDC77-\uDC7F\uDC9F-\uDCDF\uDCF3\uDCF6-\uDCFF\uDD16-\uDD1F\uDD3A-\uDD7F\uDDB8-\uDDBD\uDDC0-\uDDFF\uDE04\uDE07-\uDE0B\uDE14\uDE18\uDE36\uDE37\uDE3B-\uDE3E\uDE40-\uDE5F\uDE7D-\uDE7F\uDE9D-\uDEBF\uDEC8\uDEE7-\uDEFF\uDF36-\uDF3F\uDF56-\uDF5F\uDF73-\uDF7F\uDF92-\uDFFF]|\uD803[\uDC49-\uDC7F\uDCB3-\uDCBF\uDCF3-\uDCFF\uDD28-\uDD2F\uDD3A-\uDE7F\uDEAA\uDEAD-\uDEAF\uDEB2-\uDEFF\uDF1D-\uDF26\uDF28-\uDF2F\uDF51-\uDFAF\uDFC5-\uDFDF\uDFF7-\uDFFF]|\uD804[\uDC47-\uDC65\uDC70-\uDC7E\uDCBB-\uDCCF\uDCE9-\uDCEF\uDCFA-\uDCFF\uDD35\uDD40-\uDD43\uDD48-\uDD4F\uDD74\uDD75\uDD77-\uDD7F\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDFF\uDE12\uDE38-\uDE3D\uDE3F-\uDE7F\uDE87\uDE89\uDE8E\uDE9E\uDEA9-\uDEAF\uDEEB-\uDEEF\uDEFA-\uDEFF\uDF04\uDF0D\uDF0E\uDF11\uDF12\uDF29\uDF31\uDF34\uDF3A\uDF45\uDF46\uDF49\uDF4A\uDF4E\uDF4F\uDF51-\uDF56\uDF58-\uDF5C\uDF64\uDF65\uDF6D-\uDF6F\uDF75-\uDFFF]|\uD805[\uDC4B-\uDC4F\uDC5A-\uDC5D\uDC62-\uDC7F\uDCC6\uDCC8-\uDCCF\uDCDA-\uDD7F\uDDB6\uDDB7\uDDC1-\uDDD7\uDDDE-\uDDFF\uDE41-\uDE43\uDE45-\uDE4F\uDE5A-\uDE7F\uDEB9-\uDEBF\uDECA-\uDEFF\uDF1B\uDF1C\uDF2C-\uDF2F\uDF3A-\uDFFF]|\uD806[\uDC3B-\uDC9F\uDCEA-\uDCFE\uDD07\uDD08\uDD0A\uDD0B\uDD14\uDD17\uDD36\uDD39\uDD3A\uDD44-\uDD4F\uDD5A-\uDD9F\uDDA8\uDDA9\uDDD8\uDDD9\uDDE2\uDDE5-\uDDFF\uDE3F-\uDE46\uDE48-\uDE4F\uDE9A-\uDE9C\uDE9E-\uDEBF\uDEF9-\uDFFF]|\uD807[\uDC09\uDC37\uDC41-\uDC4F\uDC5A-\uDC71\uDC90\uDC91\uDCA8\uDCB7-\uDCFF\uDD07\uDD0A\uDD37-\uDD39\uDD3B\uDD3E\uDD48-\uDD4F\uDD5A-\uDD5F\uDD66\uDD69\uDD8F\uDD92\uDD99-\uDD9F\uDDAA-\uDEDF\uDEF7-\uDFAF\uDFB1-\uDFFF]|\uD808[\uDF9A-\uDFFF]|\uD809[\uDC6F-\uDC7F\uDD44-\uDFFF]|[\uD80A\uD80B\uD80E-\uD810\uD812-\uD819\uD824-\uD82B\uD82D\uD82E\uD830-\uD833\uD837\uD839\uD83D\uD83F\uD87B-\uD87D\uD87F\uD885-\uDB3F\uDB41-\uDBFF][\uDC00-\uDFFF]|\uD80D[\uDC2F-\uDFFF]|\uD811[\uDE47-\uDFFF]|\uD81A[\uDE39-\uDE3F\uDE5F\uDE6A-\uDECF\uDEEE\uDEEF\uDEF5-\uDEFF\uDF37-\uDF3F\uDF44-\uDF4F\uDF5A-\uDF62\uDF78-\uDF7C\uDF90-\uDFFF]|\uD81B[\uDC00-\uDE3F\uDE80-\uDEFF\uDF4B-\uDF4E\uDF88-\uDF8E\uDFA0-\uDFDF\uDFE2\uDFE5-\uDFEF\uDFF2-\uDFFF]|\uD821[\uDFF8-\uDFFF]|\uD823[\uDCD6-\uDCFF\uDD09-\uDFFF]|\uD82C[\uDD1F-\uDD4F\uDD53-\uDD63\uDD68-\uDD6F\uDEFC-\uDFFF]|\uD82F[\uDC6B-\uDC6F\uDC7D-\uDC7F\uDC89-\uDC8F\uDC9A-\uDC9C\uDC9F-\uDFFF]|\uD834[\uDC00-\uDD64\uDD6A-\uDD6C\uDD73-\uDD7A\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDE41\uDE45-\uDFFF]|\uD835[\uDC55\uDC9D\uDCA0\uDCA1\uDCA3\uDCA4\uDCA7\uDCA8\uDCAD\uDCBA\uDCBC\uDCC4\uDD06\uDD0B\uDD0C\uDD15\uDD1D\uDD3A\uDD3F\uDD45\uDD47-\uDD49\uDD51\uDEA6\uDEA7\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3\uDFCC\uDFCD]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85-\uDE9A\uDEA0\uDEB0-\uDFFF]|\uD838[\uDC07\uDC19\uDC1A\uDC22\uDC25\uDC2B-\uDCFF\uDD2D-\uDD2F\uDD3E\uDD3F\uDD4A-\uDD4D\uDD4F-\uDEBF\uDEFA-\uDFFF]|\uD83A[\uDCC5-\uDCCF\uDCD7-\uDCFF\uDD4C-\uDD4F\uDD5A-\uDFFF]|\uD83B[\uDC00-\uDDFF\uDE04\uDE20\uDE23\uDE25\uDE26\uDE28\uDE33\uDE38\uDE3A\uDE3C-\uDE41\uDE43-\uDE46\uDE48\uDE4A\uDE4C\uDE50\uDE53\uDE55\uDE56\uDE58\uDE5A\uDE5C\uDE5E\uDE60\uDE63\uDE65\uDE66\uDE6B\uDE73\uDE78\uDE7D\uDE7F\uDE8A\uDE9C-\uDEA0\uDEA4\uDEAA\uDEBC-\uDFFF]|\uD83C[\uDC00-\uDD2F\uDD4A-\uDD4F\uDD6A-\uDD6F\uDD8A-\uDFFF]|\uD83E[\uDC00-\uDFEF\uDFFA-\uDFFF]|\uD869[\uDEDE-\uDEFF]|\uD86D[\uDF35-\uDF3F]|\uD86E[\uDC1E\uDC1F]|\uD873[\uDEA2-\uDEAF]|\uD87A[\uDFE1-\uDFFF]|\uD87E[\uDE1E-\uDFFF]|\uD884[\uDF4B-\uDFFF]|\uDB40[\uDC00-\uDCFF\uDDF0-\uDFFF]/g;var p=n(7294),x=n(8995);let m=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)};var g="object"==typeof global&&global&&global.Object===Object&&global,f="object"==typeof self&&self&&self.Object===Object&&self,v=g||f||Function("return this")();let y=function(){return v.Date.now()};var b=/\s/;let w=function(e){for(var t=e.length;t--&&b.test(e.charAt(t)););return t};var k=/^\s+/,I=v.Symbol,D=Object.prototype,E=D.hasOwnProperty,F=D.toString,A=I?I.toStringTag:void 0;let C=function(e){var t=E.call(e,A),n=e[A];try{e[A]=void 0;var r=!0}catch(e){}var i=F.call(e);return r&&(t?e[A]=n:delete e[A]),i};var j=Object.prototype.toString,P=I?I.toStringTag:void 0;let S=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":P&&P in Object(e)?C(e):j.call(e)},T=function(e){return"symbol"==typeof e||null!=e&&"object"==typeof e&&"[object Symbol]"==S(e)};var N=0/0,_=/^[-+]0x[0-9a-f]+$/i,B=/^0b[01]+$/i,O=/^0o[0-7]+$/i,R=parseInt;let q=function(e){if("number"==typeof e)return e;if(T(e))return N;if(m(e)){var t,n="function"==typeof e.valueOf?e.valueOf():e;e=m(n)?n+"":n}if("string"!=typeof e)return 0===e?e:+e;e=(t=e)?t.slice(0,w(t)+1).replace(k,""):t;var r=B.test(e);return r||O.test(e)?R(e.slice(2),r?2:8):_.test(e)?N:+e};var L=Math.max,M=Math.min;let z=function(e,t,n){var r,i,a,o,s,l,c=0,d=!1,u=!1,h=!0;if("function"!=typeof e)throw TypeError("Expected a function");function p(t){var n=r,a=i;return r=i=void 0,c=t,o=e.apply(a,n)}function x(e){var n=e-l,r=e-c;return void 0===l||n>=t||n<0||u&&r>=a}function g(){var e,n,r,i=y();if(x(i))return f(i);s=setTimeout(g,(e=i-l,n=i-c,r=t-e,u?M(r,a-n):r))}function f(e){return(s=void 0,h&&r)?p(e):(r=i=void 0,o)}function v(){var e,n=y(),a=x(n);if(r=arguments,i=this,l=n,a){if(void 0===s)return c=e=l,s=setTimeout(g,t),d?p(e):o;if(u)return clearTimeout(s),s=setTimeout(g,t),p(l)}return void 0===s&&(s=setTimeout(g,t)),o}return t=q(t)||0,m(n)&&(d=!!n.leading,a=(u="maxWait"in n)?L(q(n.maxWait)||0,t):a,h="trailing"in n?!!n.trailing:h),v.cancel=function(){void 0!==s&&clearTimeout(s),c=0,r=l=i=s=void 0},v.flush=function(){return void 0===s?o:f(y())},v},H=function(e,t,n){var r=!0,i=!0;if("function"!=typeof e)throw TypeError("Expected a function");return m(n)&&(r="leading"in n?!!n.leading:r,i="trailing"in n?!!n.trailing:i),z(e,t,{leading:r,maxWait:t,trailing:i})};var $=n(5598);let W=e=>(0,c.jsx)("svg",{width:"1em",height:"1em",viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M22 16 12 26l-1.4-1.4 8.6-8.6-8.6-8.6L12 6z"})}),K=e=>(0,c.jsx)("svg",{width:"1em",height:"1em",viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M4 6h24v2H4zm0 18h24v2H4zm0-12h24v2H4zm0 6h24v2H4z"})});var U=n(4865);n(9284);var V=n(405);let G=e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:32,height:32,viewBox:"0 0 24 24",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M16 7H3V5h13zM3 19h13v-2H3zm19-7-4-3v2H3v2h15v2z"})}),Z=e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:32,height:32,viewBox:"0 0 24 24",...e,children:(0,c.jsx)("path",{fill:"#22a041",d:"M21 5H3v2h18zM3 19h7v-2H3zm0-6h15c1 0 2 .43 2 2s-1 2-2 2h-2v-2l-4 3 4 3v-2h2c2.95 0 4-1.27 4-4 0-2.72-1-4-4-4H3z"})}),J=e=>(0,c.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:32,height:32,viewBox:"0 0 30 30",...e,children:[(0,c.jsx)("path",{fill:"currentColor",d:"M28 10v18H10V10zm0-2H10a2 2 0 0 0-2 2v18a2 2 0 0 0 2 2h18a2 2 0 0 0 2-2V10a2 2 0 0 0-2-2"}),(0,c.jsx)("path",{fill:"currentColor",d:"M4 18H2V4a2 2 0 0 1 2-2h14v2H4Z"})]}),Q=e=>(0,c.jsx)("svg",{width:32,height:32,viewBox:"0 0 30 30",...e,children:(0,c.jsx)("path",{fill:"#49cd37",d:"m13 24-9-9 1.414-1.414L13 21.171 26.586 7.586 28 9z"})});var Y=n(640);function X(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0;return(function(e){if(0===e.length||1===e.length)return e;var t,n=e.join(".");return eo[n]||(eo[n]=0===(t=e.length)||1===t?e:2===t?[e[0],e[1],"".concat(e[0],".").concat(e[1]),"".concat(e[1],".").concat(e[0])]:3===t?[e[0],e[1],e[2],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0])]:t>=4?[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]:void 0),eo[n]})(e.filter(function(e){return"token"!==e})).reduce(function(e,t){return ea(ea({},e),n[t])},t)}(s.className,Object.assign({},s.style,void 0===i?{}:i),r)})}else h=ea(ea({},s),{},{className:s.className.join(" ")});var v=x(n.children);return p.createElement(c,er({key:o},h),v)}}({node:e,stylesheet:n,useInlineStyles:r,key:"code-segement".concat(t)})})}function eg(e){return e&&void 0!==e.highlightAuto}var ef=n(1215),ev=n.n(ef),ey=(i=ev(),a={},function(e){var t=e.language,n=e.children,r=e.style,o=void 0===r?a:r,s=e.customStyle,l=void 0===s?{}:s,c=e.codeTagProps,d=void 0===c?{className:t?"language-".concat(t):void 0,style:ec(ec({},o['code[class*="language-"]']),o['code[class*="language-'.concat(t,'"]')])}:c,u=e.useInlineStyles,h=void 0===u||u,x=e.showLineNumbers,m=void 0!==x&&x,g=e.showInlineLineNumbers,f=void 0===g||g,v=e.startingLineNumber,y=void 0===v?1:v,b=e.lineNumberContainerStyle,w=e.lineNumberStyle,k=void 0===w?{}:w,I=e.wrapLines,D=e.wrapLongLines,E=void 0!==D&&D,F=e.lineProps,A=e.renderer,C=e.PreTag,j=void 0===C?"pre":C,P=e.CodeTag,S=void 0===P?"code":P,T=e.code,N=void 0===T?(Array.isArray(n)?n[0]:n)||"":T,_=e.astGenerator,B=function(e,t){if(null==e)return{};var n,r,i=function(e,t){if(null==e)return{};var n={};for(var r in e)if(({}).hasOwnProperty.call(e,r)){if(-1!==t.indexOf(r))continue;n[r]=e[r]}return n}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r1&&void 0!==arguments[1]?arguments[1]:[],r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],i=0;i2&&void 0!==arguments[2]?arguments[2]:[];return t||c.length>0?function(e,a){var c=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return ex({children:e,lineNumber:a,lineNumberStyle:s,largestLineNumber:o,showInlineLineNumbers:i,lineProps:n,className:c,showLineNumbers:r,wrapLongLines:l,wrapLines:t})}(e,a,c):function(e,t){if(r&&t&&i){var n=ep(s,t,o);e.unshift(eh(t,n))}return e}(e,a)}for(;p=r))));t++);if(n)return a?eJ(l,r,0):void(t[t.length]=l)}return!n&&l}function eJ(e,t,n){return e=1===e.length?e[0]:[].concat.apply([],e),n||e.length>t?e.slice(n,n+t):e}function eQ(e,t,n,r){return e=n?(e=e[(r=r&&t>n)?t:n])&&e[r?n:t]:e[t]}function eY(e,t,n,r,i){let a=0;if(e.constructor===Array)if(i)-1!==(t=e.indexOf(t))?1=this.B&&(u||!d[x])){var a=eV(h,r,p),o="";switch(this.G){case"full":if(2a;s--)if(s-a>=this.B){var l=eV(h,r,p,i,a);eG(this,d,o=x.substring(a,s),l,e,n)}break}case"reverse":if(1=this.B&&eG(this,d,o,eV(h,r,p,i,s),e,n);o=""}case"forward":if(1=this.B&&eG(this,d,o,a,e,n);break}default:if(this.C&&(a=Math.min(a/this.C(t,x,p)|0,h-1)),eG(this,d,x,a,e,n),u&&1=this.B&&!i[x]){i[x]=1;let t=this.l&&x>a;eG(this,c,t?a:x,eV(o+(r/2>o?0:1),r,p,s-1,l-1),e,n,t?x:a)}}}}}this.m||(this.register[e]=1)}}return this},s.search=function(e,t,n){let r,i,a;n||(!t&&eA(e)?e=(n=e).query:eA(t)&&(n=t));let o=[],s,l,c=0;if(n){e=n.query||e,t=n.limit,c=n.offset||0;var d=n.context;l=n.suggest}if(e&&1<(s=(e=this.encode(""+e)).length)){n=eD();var u=[];for(let t=0,r=0,i;t=this.B&&!n[i])if(!this.s&&!l&&!this.map[i])return o;else u[r++]=i,n[i]=1;s=(e=u).length}if(!s)return o;for(t||(t=100),d=this.depth&&1{a=e})),i||(i=0)){case 0:if(o="reg",this.m)for(let e in s=eD(),this.register)s[e]=1;else s=this.register;break;case 1:o="cfg",s={doc:0,opt:+!!this.s};break;case 2:o="map",s=this.map;break;case 3:o="ctx",s=this.h;break;default:void 0===n&&a&&a();return}return eK(e,t||this,n,o,r,i,s,a),l},s.import=function(e,t){if(t)switch(eF(t)&&(t=JSON.parse(t)),e){case"cfg":this.s=!!t.opt;break;case"reg":this.m=!1,this.register=t;break;case"map":this.map=t;break;case"ctx":this.h=t}},eL(eU.prototype);let e1=0;function e0(e){var t;if(!(this instanceof e0))return new e0(e);e?eC(t=e.encode)&&(e.encode=t.toString()):e={},(t=(self||window)._factory)&&(t=t.toString());let r="undefined"==typeof window&&self.exports,i=this;this.o=function(e,t,r){let i;try{i=t?new(n(7770)).Worker("//node/node.js"):e?new Worker(URL.createObjectURL(new Blob(["onmessage="+eX.toString()],{type:"text/javascript"}))):new Worker(eF(r)?r:"worker/worker.js",{type:"module"})}catch(e){}return i}(t,r,e.worker),this.h=eD(),this.o&&(r?this.o.on("message",function(e){i.h[e.id](e.msg),delete i.h[e.id]}):this.o.onmessage=function(e){e=e.data,i.h[e.id](e.msg),delete i.h[e.id]},this.o.postMessage({task:"init",factory:t,options:e}))}function e2(e){e0.prototype[e]=e0.prototype[e+"Async"]=function(){let t,n=this,r=[].slice.call(arguments);var i=r[r.length-1];return eC(i)&&(t=i,r.splice(r.length-1,1)),i=new Promise(function(t){setTimeout(function(){n.h[++e1]=t,n.o.postMessage({task:e,id:e1,args:r})})}),t?(i.then(t),this):i}}function e3(e){if(!(this instanceof e3))return new e3(e);var t,n=e.document||e.doc||e;this.K=[],this.h=[],this.A=[],this.register=eD(),this.key=(t=n.key||n.id)&&e4(t,this.A)||"id",this.m=ek(e.fastupdate),this.C=(t=n.store)&&!0!==t&&[],this.store=t&&eD(),this.I=(t=n.tag)&&e4(t,this.A),this.l=t&&eD(),this.cache=(t=e.cache)&&new eH(t),e.cache=!1,this.o=e.worker,this.async=!1,t=eD();let r=n.index||n.field||n;eF(r)&&(r=[r]);for(let n=0,i,a;nt||n)&&(i=i.slice(n,n+t)),r&&(i=e7.call(this,i)),{tag:e,result:i}}function e7(e){let t=Array(e.length);for(let n=0,r;n{a=e})),i||(i=0),r||(r=0),r(0,c.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:32,height:32,viewBox:"0 0 32 32",...e,children:[(0,c.jsx)("circle",{cx:8,cy:16,r:2,fill:"currentColor"}),(0,c.jsx)("circle",{cx:16,cy:16,r:2,fill:"currentColor"}),(0,c.jsx)("circle",{cx:24,cy:16,r:2,fill:"currentColor"})]});var tc=!1;if("undefined"!=typeof window){var td={get passive(){tc=!0;return}};window.addEventListener("testPassive",null,td),window.removeEventListener("testPassive",null,td)}var tu="undefined"!=typeof window&&window.navigator&&window.navigator.platform&&(/iP(ad|hone|od)/.test(window.navigator.platform)||"MacIntel"===window.navigator.platform&&window.navigator.maxTouchPoints>1),th=[],tp=!1,tx=-1,tm=void 0,tg=void 0,tf=void 0,tv=function(e){return th.some(function(t){return!!(t.options.allowTouchMove&&t.options.allowTouchMove(e))})},ty=function(e){var t=e||window.event;return!!tv(t.target)||t.touches.length>1||(t.preventDefault&&t.preventDefault(),!1)},tb=function(e){if(void 0===tf){var t=!!e&&!0===e.reserveScrollBarGap,n=window.innerWidth-document.documentElement.clientWidth;if(t&&n>0){var r=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right"),10);tf=document.body.style.paddingRight,document.body.style.paddingRight=r+n+"px"}}void 0===tm&&(tm=document.body.style.overflow,document.body.style.overflow="hidden")},tw=function(){void 0!==tf&&(document.body.style.paddingRight=tf,tf=void 0),void 0!==tm&&(document.body.style.overflow=tm,tm=void 0)},tk=function(){if(void 0!==tg){var e=-parseInt(document.body.style.top,10),t=-parseInt(document.body.style.left,10);document.body.style.position=tg.position,document.body.style.top=tg.top,document.body.style.left=tg.left,window.scrollTo(t,e),tg=void 0}},tI=function(e,t){var n=e.targetTouches[0].clientY-tx;return!tv(e.target)&&(t&&0===t.scrollTop&&n>0?ty(e):t&&t.scrollHeight-t.scrollTop<=t.clientHeight&&n<0?ty(e):(e.stopPropagation(),!0))},tD=function(e,t){if(!e)return void console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.");!th.some(function(t){return t.targetElement===e})&&(th=[].concat(function(e){if(!Array.isArray(e))return Array.from(e);for(var t=0,n=Array(e.length);t=r&&(document.body.style.top=-(t+e))})},300)}}):tb(t),tu&&(e.ontouchstart=function(e){1===e.targetTouches.length&&(tx=e.targetTouches[0].clientY)},e.ontouchmove=function(t){1===t.targetTouches.length&&tI(t,e)},tp||(document.addEventListener("touchmove",ty,tc?{passive:!1}:void 0),tp=!0)))},tE=function(){tu&&(th.forEach(function(e){e.targetElement.ontouchstart=null,e.targetElement.ontouchmove=null}),tp&&(document.removeEventListener("touchmove",ty,tc?{passive:!1}:void 0),tp=!1),tx=-1),tu?tk():tw(),th=[]};let tF=e=>(0,c.jsx)("svg",{width:18,height:18,viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M27.85 29H30l-6-15h-2.35l-6 15h2.15l1.6-4h6.85zm-7.65-6 2.62-6.56L25.45 23zM18 7V5h-7V2H9v3H2v2h10.74a14.7 14.7 0 0 1-3.19 6.18A13.5 13.5 0 0 1 7.26 9h-2.1a16.5 16.5 0 0 0 3 5.58A16.8 16.8 0 0 1 3 18l.75 1.86A18.5 18.5 0 0 0 9.53 16a16.9 16.9 0 0 0 5.76 3.84L16 18a14.5 14.5 0 0 1-5.12-3.37A17.64 17.64 0 0 0 14.8 7z"})}),tA=e=>(0,c.jsx)("svg",{width:"1em",height:"1em",viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M16 22 6 12l1.4-1.4 8.6 8.6 8.6-8.6L26 12z"})}),tC=e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",viewBox:"0 0 24 24",...e,children:(0,c.jsx)("path",{d:"M12.1 22h-.9c-5.5-.5-9.5-5.4-9-10.9.4-4.8 4.2-8.6 9-9 .4 0 .8.2 1 .5s.2.8-.1 1.1c-2 2.7-1.4 6.4 1.3 8.4 2.1 1.6 5 1.6 7.1 0 .3-.2.7-.3 1.1-.1.3.2.5.6.5 1-.2 2.7-1.5 5.1-3.6 6.8-1.9 1.4-4.1 2.2-6.4 2.2M9.3 4.4c-2.9 1-5 3.6-5.2 6.8-.4 4.4 2.8 8.3 7.2 8.7 2.1.2 4.2-.4 5.8-1.8 1.1-.9 1.9-2.1 2.4-3.4-2.5.9-5.3.5-7.5-1.1-2.8-2.2-3.9-5.9-2.7-9.2"})}),tj=e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",viewBox:"0 0 24 24",...e,children:(0,c.jsx)("path",{d:"M12 18c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6m0-10c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4M12 4c-.6 0-1-.4-1-1V1c0-.6.4-1 1-1s1 .4 1 1v2c0 .6-.4 1-1 1M12 24c-.6 0-1-.4-1-1v-2c0-.6.4-1 1-1s1 .4 1 1v2c0 .6-.4 1-1 1M5.6 6.6c-.3 0-.5-.1-.7-.3L3.5 4.9c-.4-.4-.4-1 0-1.4s1-.4 1.4 0l1.4 1.4c.4.4.4 1 0 1.4-.1.2-.4.3-.7.3M19.8 20.8c-.3 0-.5-.1-.7-.3l-1.4-1.4c-.4-.4-.4-1 0-1.4s1-.4 1.4 0l1.4 1.4c.4.4.4 1 0 1.4-.2.2-.5.3-.7.3M3 13H1c-.6 0-1-.4-1-1s.4-1 1-1h2c.6 0 1 .4 1 1s-.4 1-1 1M23 13h-2c-.6 0-1-.4-1-1s.4-1 1-1h2c.6 0 1 .4 1 1s-.4 1-1 1M4.2 20.8c-.3 0-.5-.1-.7-.3-.4-.4-.4-1 0-1.4l1.4-1.4c.4-.4 1-.4 1.4 0s.4 1 0 1.4l-1.4 1.4c-.2.2-.4.3-.7.3M18.4 6.6c-.3 0-.5-.1-.7-.3-.4-.4-.4-1 0-1.4l1.4-1.4c.4-.4 1-.4 1.4 0s.4 1 0 1.4l-1.4 1.4c-.2.2-.5.3-.7.3"})});var tP=n(3935);let tS=e=>(0,c.jsx)("svg",{width:"1em",height:"1em",viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M16 22 6 12l1.4-1.4 8.6 8.6 8.6-8.6L26 12z"})}),tT=e=>(0,c.jsx)("svg",{width:24,height:24,viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"var(--rp-c-gray)",d:"m29 27.586-7.552-7.552a11.018 11.018 0 1 0-1.414 1.414L27.586 29ZM4 13a9 9 0 1 1 9 9 9.01 9.01 0 0 1-9-9"})}),tN=e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M24 9.4 22.6 8 16 14.6 9.4 8 8 9.4l6.6 6.6L8 22.6 9.4 24l6.6-6.6 6.6 6.6 1.4-1.4-6.6-6.6z"})}),t_=e=>(0,c.jsx)("svg",{width:32,height:32,viewBox:"0 0 24 24",...e,children:(0,c.jsxs)("g",{fill:"none",stroke:"var(--rp-c-brand)",strokeLinecap:"round",strokeWidth:2,children:[(0,c.jsx)("path",{strokeDasharray:60,strokeDashoffset:60,strokeOpacity:.3,d:"M12 3a9 9 0 1 1 0 18 9 9 0 0 1 0-18Z",children:(0,c.jsx)("animate",{fill:"freeze",attributeName:"stroke-dashoffset",dur:"1.3s",values:"60;0"})}),(0,c.jsxs)("path",{strokeDasharray:15,strokeDashoffset:15,d:"M12 3a9 9 0 0 1 9 9",children:[(0,c.jsx)("animate",{fill:"freeze",attributeName:"stroke-dashoffset",dur:"0.3s",values:"15;0"}),(0,c.jsx)("animateTransform",{attributeName:"transform",dur:"1.5s",repeatCount:"indefinite",type:"rotate",values:"0 12 12;360 12 12"})]})]})}),tB=()=>{},tO=e=>(0,c.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:48,height:48,fill:"none",viewBox:"0 0 48 48",...e,children:[(0,c.jsx)("path",{stroke:"currentColor",strokeWidth:4,d:"M24 5v6m7 1 4-4m-18 4-4-4m27 33H8a2 2 0 0 1-2-2v-8.46a2 2 0 0 1 .272-1.007l6.15-10.54A2 2 0 0 1 14.148 18H33.85a2 2 0 0 1 1.728.992l6.149 10.541A2 2 0 0 1 42 30.541V39a2 2 0 0 1-2 2Z"}),(0,c.jsx)("path",{stroke:"currentColor",strokeWidth:4,d:"M41.5 30H28s-1 3-4 3-4-3-4-3H6.5"})]}),tR=e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M13.414 17.586 18 22.172V8H8V6h10a2 2 0 0 1 2 2v14.172l4.586-4.586L26 19l-7 7-7-7Z"})});function tq(){let{siteData:{themeConfig:e}}=(0,u.Vi)(),t=e.hideNavbar??"never",[n,r]=(0,p.useState)(!1),{pathname:i}=(0,u.TH)(),a=(0,p.useRef)(0);return"never"!==t&&("always"===t||((0,p.useEffect)(()=>{r(!1);let e=H(()=>{let{scrollTop:e}=document.documentElement;e!==a.current&&(r(a.current>0&&e-a.current>0),a.current=e<=0?0:e)},200);return window.addEventListener("scroll",e),()=>{window.removeEventListener("scroll",e)}},[i]),n))}function tL(){let e=(0,u.Vi)(),{page:{lang:t}}=e,n=e?.siteData?.themeConfig??{},r=e.siteData.lang??"",i=n?.locales;return i&&0!==i.length?{...i.find(e=>e.lang===t),langRoutePrefix:t===r?"/":(0,x.mi)(t)}:{nav:n.nav,sidebar:n.sidebar,prevPageText:n.prevPageText,nextPageText:n.nextPageText,sourceCodeText:n.sourceCodeText,searchPlaceholderText:n.searchPlaceholderText,searchNoResultsText:n.searchNoResultsText,searchSuggestedQueryText:n.searchSuggestedQueryText,overview:n.overview}}function tM(){let{page:e,siteData:t}=(0,u.Vi)(),{frontmatter:n}=e,{themeConfig:r}=t,i=tL(),a=(0,u.TH)(),o=n?.overview??!1,s=()=>{let e="undefined"==typeof window||window.top===window.self;return(n?.outline??r?.outline??e)&&!o},[l,c]=function(){let{siteData:{themeConfig:e},page:{frontmatter:t={}}}=(0,u.Vi)(),n=(t?.navbar??!0)&&e?.hideNavbar!=="always",[r,i]=(0,p.useState)(n);return[r,i]}(),d=tq(),[h,x]=(0,p.useState)(s()),[m,g]=(0,p.useState)(n?.footer??!0),f=i.sidebar||{},v=n?.sidebar!==!1&&Object.keys(f).length>0,{width:y}=(0,u.iP)(),b=y<=960||y<=1280&&e.toc.length>0;(0,p.useEffect)(()=>{x(s())},[e,t]),(0,p.useEffect)(()=>{let e=new URLSearchParams(a.search),t=document.documentElement.style,n=t.getPropertyValue("--rp-sidebar-width"),r=t.getPropertyValue("--rp-aside-width"),i=e.get("navbar"),o=e.get("sidebar"),s=e.get("outline"),d=e.get("footer");return"0"===i&&c(!1),"0"===o&&document.documentElement.style.setProperty("--rp-sidebar-width","0px"),"0"===s&&document.documentElement.style.setProperty("--rp-aside-width","0px"),"0"===d&&g(!1),()=>{document.documentElement.style.setProperty("--rp-sidebar-width",n),document.documentElement.style.setProperty("--rp-aside-width",r),c(l),g(m)}},[a.search]);let w=d?0:y<=768?56:72,k=46*!!b;return{showAside:h,showNavbar:l,showSidebar:v,showSidebarMenu:b,showDocFooter:m,navbarHeight:w,sidebarMenuHeight:k,scrollPaddingTop:w+k}}function tz(e,t){let n=Number.parseInt(window.getComputedStyle(e).paddingTop,10);return Math.round(window.scrollY+e.getBoundingClientRect().top-t-n)}function tH(e,t,n){window.scrollTo({left:0,top:tz(e,n),...t?{behavior:"smooth"}:{}})}function t$(e){let{scrollPaddingTop:t}=tM();(0,p.useEffect)(()=>{let n=document.getElementById("aside-container"),r=Array.from(document.querySelectorAll(".rspress-doc .header-anchor")).filter(e=>e.parentElement?.tagName!=="H1");if(!n||!r.length||!e.length)return;let i=null,a=(e,t)=>{if(e[t]){let r=e[t].getAttribute("href"),a=n?.querySelector(`a[href="#${r?.slice(1)}"]`);a&&(i&&i.classList.remove("aside-active"),(i=a).classList.add("aside-active"))}},o=()=>{if(document.documentElement.scrollTop+window.innerHeight>=document.documentElement.scrollHeight)a(r,r.length-1);else for(let e=0;e=s&&o{i&&i.classList.remove("aside-active"),window.removeEventListener("scroll",s)}},[t,e.length])}function tW(){if((0,x._f)()){let{scrollPaddingTop:e}=tM();(0,p.useEffect)(()=>{window.addEventListener("click",t=>{let n=t.target.closest("a");if(!n)return;let{origin:r,hash:i,target:a,pathname:o,search:s}=n,l=window.location;i&&"_blank"!==a&&r===l.origin&&(o===l.pathname&&s===l.search&&i&&n.classList.contains("header-anchor")?(t.preventDefault(),history.pushState(null,"",i),function(e,t,n=!1,r){let i=null;try{i=e.classList.contains("header-anchor")?e:document.getElementById(decodeURIComponent(t.slice(1)))}catch(e){console.warn(e)}i&&tH(i,n,r)}(n,i,!0,e),window.dispatchEvent(new Event("hashchange"))):window.addEventListener("RspressReloadContent",()=>{location.hash.length>1&&tH(document.getElementById(location.hash.slice(1)),!1,e)}))},{capture:!0}),window.addEventListener("hashchange",e=>{e.preventDefault()})},[e])}}function tK(e){return e?"number"==typeof e?e:/<([a-z]+)([^<]*)(?:>(.*?)<\/\1>|\s*\/>)/i.test(e)?$(e):e.replace(/\\/g,">").replace(/</g,"<").replace(/>/g,">"):""}let tU=/`(.*?)`/g,tV=/\*{2}(?!\*)(.*?)\*{2}(?!\*)/g,tG=/\*(?!\*)(.*?)\*(?!\*)/g,tZ=/\~{2}(.*?)\~{2}/g;function tJ(e){return tK(e.replace(/`[^`]+`/g,e=>e.replace(/$1").replace(tG,"$1").replace(tZ,"$1").replace(tU,"$1"))}let tQ=({header:e,baseHeaderLevel:t})=>(0,c.jsx)("li",{children:(0,c.jsx)("a",{href:`#${e.id}`,title:e.text.replace(tV,"$1").replace(tG,"$1").replace(tZ,"$1").replace(tU,"$1"),className:"aside-link transition-all duration-300 hover:text-text-1 text-text-2 block",style:{marginLeft:(e.depth-t)*12,fontWeight:"semibold"},onClick:t=>{t.preventDefault(),window.location.hash=e.id},children:(0,c.jsx)("span",{className:"aside-link-text block",children:tJ(e.text)})})});function tY({headers:e,outlineTitle:t}){let{scrollPaddingTop:n}=tM(),r=e[0]?.depth||2,{hash:i="",pathname:a}=(0,u.TH)(),o=(0,p.useMemo)(()=>decodeURIComponent(i),[i]);return t$(e),(0,p.useEffect)(()=>{if(0===o.length)window.scrollTo(0,0);else{let e=document.getElementById(o.slice(1));e&&tH(e,!1,n)}},[o,e,a]),(0,c.jsx)("div",{className:"flex flex-col",children:(0,c.jsxs)("div",{id:"aside-container",className:"relative text-sm font-medium",children:[(0,c.jsx)("div",{className:"leading-7 block text-sm font-semibold pl-3",children:t}),(0,c.jsx)("nav",{className:"mt-1",children:(0,c.jsx)("ul",{className:"relative",children:e.map(e=>(0,c.jsx)(tQ,{baseHeaderLevel:r,header:e},`${a}#${e.id}`))})})]})})}let tX=(e,t)=>{let n=(0,u.pJ)(e);if(n===t)return!0;let r=(0,x.mi)(n);if(t.startsWith(r))return!0;let i=`${n}.`;return t.startsWith(i)};function t1(e,t){let n=(0,u.Tm)((0,u.pJ)(e)),r=(0,u.Tm)(t);return null!==(0,u.LX)(n,r)}let t0=(e,t)=>{for(let n of Object.keys(e).sort((e,t)=>t.length-e.length))if(tX(n,t))return e[n];return[]};function t2(){let{sidebar:e}=tL(),{pathname:t}=(0,u.TH)(),n=decodeURIComponent(t);return(0,p.useMemo)(()=>t0(e,n),[e,n])}function t3(){let{prevPage:e,nextPage:t}=function(){let{pathname:e}=(0,u.TH)(),t=t2(),n=[],r=e=>{"items"in e?(e.link&&n.push({text:e.text,link:e.link}),e.items.forEach(e=>{"dividerType"in e||r(e)})):n.push(e)};t.forEach(e=>!("dividerType"in e)&&r(e));let i=n.findIndex(t=>(0,u.pV)((0,u.pJ)(t.link),e));return{prevPage:n[i-1]||null,nextPage:n[i+1]||null}}(),{lastUpdated:n=!1}=tL(),{siteData:r}=(0,u.Vi)(),{themeConfig:i}=r,a=i.lastUpdated||n;return(0,c.jsxs)("footer",{className:"mt-8",children:[(0,c.jsx)("div",{className:"xs:flex pb-5 px-2 justify-end items-center",children:a&&(0,c.jsx)(rk,{})}),(0,c.jsx)("div",{className:"flex flex-col",children:(0,c.jsx)(rx,{})}),(0,c.jsxs)("div",{className:"flex flex-col sm:flex-row sm:justify-around gap-4 pt-6",children:[(0,c.jsx)("div",{className:"prev_c92d1 flex flex-col",children:e?(0,c.jsx)(r9,{type:"prev",text:e.text,href:(0,u.AP)(e.link)}):null}),(0,c.jsx)("div",{className:"next_c11be flex flex-col",children:t?(0,c.jsx)(r9,{type:"next",text:t.text,href:(0,u.AP)(t.link)}):null})]})]})}let t4={hidden:"hidden_f8586",container:"container_e4235",navContainer:"navContainer_d18b1",relative:"relative_bb7f1",sticky:"sticky_ddfa7",leftNav:"leftNav_e6722",rightNav:"rightNav_a2fea",singleItem:"singleItem_c1154",activeItem:"activeItem_a28b5",navBarTitle:"navBarTitle_c5f07",menuItem:"menu-item_b8238",mobileNavMenu:"mobileNavMenu_e7045"},t5=()=>{let{siteData:e}=(0,u.Vi)(),t=tL(),{logo:n,logoText:r}=e,i=t.title??e.title,a=(0,p.useMemo)(()=>n?"string"==typeof n?(0,c.jsx)("img",{src:(0,u.i6)(n),alt:"logo",id:"logo",className:"rspress-logo"}):(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)("img",{src:(0,u.i6)(n.light),alt:"logo",id:"logo",className:"rspress-logo dark:hidden"}),(0,c.jsx)("img",{src:(0,u.i6)(n.dark),alt:"logo",id:"logo",className:"rspress-logo hidden dark:block"})]}):null,[n]);return(0,c.jsx)("div",{className:`${t4.navBarTitle}`,children:(0,c.jsxs)(nm,{href:t.langRoutePrefix,className:"flex items-center w-full h-full text-base font-semibold transition-opacity duration-300 hover:opacity-60",children:[a&&(0,c.jsx)("div",{className:"mr-1 min-w-8",children:a}),r&&(0,c.jsx)("span",{children:r}),!a&&!r&&(0,c.jsx)("span",{children:i})]})})};function t6(e){let{depth:t,dividerType:n}=e;return(0,c.jsx)("div",{className:`${"dashed"===n?"border-dashed":"border-solid"} border-t border-divider-light my-3`,style:{marginLeft:0===t?0:"18px"}})}function t7({icon:e,...t}){return e?"string"==typeof e?(0,c.jsx)("img",{src:e,alt:"",...t}):(0,c.jsx)(e,{...t}):null}let t8={navTitleMask:"navTitleMask_fb17c",sidebar:"sidebar_dd719",sidebarContent:"sidebarContent_da296",open:"open_becbd",menuLink:"menuLink_bb039",menuItem:"menuItem_ac22e",collapseContainer:"collapseContainer_d6e4e",menuItemActive:"menuItemActive_de63c"},t9=e=>"dividerType"in e,ne=e=>!("items"in e)&&"link"in e,nt=e=>"sectionHeaderText"in e,nn=e=>"link"in e&&(0,x.xf)(e.link),nr=e=>{let t=(0,u.Ww)(e);t&&t.preload()},ni=()=>{let{pathname:e}=(0,u.TH)();return(0,p.useCallback)(t=>t1(t,decodeURIComponent(e)),[e])};function na(e){let{item:t,depth:n=0,activeMatcher:r,id:i,setSidebarData:a}=e,o=(0,u.s0)(),s=(0,p.useRef)(null),l=(0,p.useRef)(),d=(0,p.useRef)(null),h=(0,p.useRef)(!0),x=(0,p.useRef)("collapsed"in t&&t.collapsed),m=t.link&&r(t.link),{collapsed:g,collapsible:f=!0}=t,v=(0,c.jsx)("div",{style:{cursor:"pointer",transition:"transform 0.2s ease-out",transform:g?"rotate(0deg)":"rotate(90deg)"},children:(0,c.jsx)(t7,{icon:W})});(0,p.useEffect)(()=>{if(h.current||!s.current||!d.current)return;l.current&&clearTimeout(l.current);let e=s.current,t=d.current,n=t.clientHeight+4;g?(e.style.maxHeight=`${n}px`,e.style.transitionDuration="0.5s",t.style.opacity="0",l.current=window.setTimeout(()=>{s.current&&(s.current.style.maxHeight="0px")},0)):(e.style.maxHeight=`${n}px`,e.style.transitionDuration="0.3s",t.style.opacity="1",l.current=window.setTimeout(()=>{s.current&&s.current.style.removeProperty("max-height")},300))},[g]),(0,p.useEffect)(()=>{h.current=!1},[]);let y=e=>{e.stopPropagation(),a(e=>{let t=[...e],n=i.split("-").map(Number),r=t[n.shift()];for(let e of n)r=r.items[e];return"items"in r&&(r.collapsed=!r.collapsed),t})};return(0,c.jsxs)("section",{className:"rspress-sidebar-section mt-0.5 block","data-context":t.context,style:{marginLeft:0===n?0:"18px"},children:[(0,c.jsxs)("div",{className:`rspress-sidebar-collapse flex justify-between items-center ${m?t8.menuItemActive:t8.menuItem}`,"data-context":t.context,onMouseEnter:()=>t.link&&nr(t.link),onClick:e=>{t.link&&o((0,u.pJ)((0,u.AP)(t.link))),f&&y(e)},style:{borderRadius:0===n?"0 var(--rp-radius) var(--rp-radius) 0":void 0,cursor:f||t.link?"pointer":"normal"},children:[(0,c.jsxs)("h2",{className:"py-2 px-3 text-sm font-medium flex",style:{...0===n?nl:{}},children:[(0,c.jsx)(im,{tag:t.tag}),(0,c.jsx)("span",{className:"flex-center",style:{fontSize:0===n?"14px":"13px"},children:tJ(t.text)})]}),f&&(0,c.jsx)("div",{className:`${t8.collapseContainer} p-2 rounded-xl`,onClick:y,children:v})]}),(0,c.jsx)("div",{ref:s,className:"transition-all duration-300 ease-in-out",style:{overflow:"hidden",maxHeight:x.current?0:void 0},children:(0,c.jsx)("div",{ref:d,className:"rspress-sidebar-group transition-opacity duration-500 ease-in-out",style:{opacity:+!x.current,marginLeft:0===n?"12px":0},children:t?.items?.map((t,r)=>t9(t)?(0,c.jsx)(t6,{depth:n+1,dividerType:t.dividerType},r):(0,c.jsx)("div",{className:"rspress-sidebar-item","data-context":t.context,children:(0,c.jsx)(no,{...e,item:t,depth:n+1,id:`${i}-${r}`})},r))})})]},i)}function no(e){let{item:t,depth:n=0,activeMatcher:r,id:i,setSidebarData:a}=e,o="link"in t&&t.link&&r(t.link),s=(0,p.useRef)(null);return((0,p.useEffect)(()=>{o&&s.current?.scrollIntoView({block:"center"})},[]),"items"in t)?(0,c.jsx)(na,{id:i,activeMatcher:r,item:t,depth:n,collapsed:t.collapsed,setSidebarData:a},`${t.text}-${i}`):(0,c.jsx)(nm,{href:(0,u.AP)(t.link),className:t8.menuLink,children:(0,c.jsxs)("div",{ref:s,className:`${o?t8.menuItemActive:t8.menuItem} mt-0.5 py-2 px-3 font-medium flex`,style:{fontSize:0===n?"14px":"13px",marginLeft:0===n?0:"18px",borderRadius:"0 var(--rp-radius) var(--rp-radius) 0",...0===n?nl:{}},children:[(0,c.jsx)(im,{tag:t.tag}),(0,c.jsx)("span",{children:tJ(t.text)})]})})}function ns({sectionHeaderText:e,tag:t}){return(0,c.jsxs)("div",{className:"rspress-sidebar-section-header",children:[(0,c.jsx)(im,{tag:t}),(0,c.jsx)("span",{children:tJ(e)})]})}let nl={fontSize:"14px",paddingLeft:"24px",fontWeight:"bold"},nc=new WeakMap;function nd(e){let{isSidebarOpen:t,beforeSidebar:n,afterSidebar:i,uiSwitch:a,navTitle:o}=e,{pathname:s}=(0,u.TH)(),l=t2(),[d,h]=(0,p.useState)(()=>l.filter(Boolean).flat()),m=decodeURIComponent(s),g=ni();return(0,p.useEffect)(()=>((0,x._f)()&&(t?(r=document.body.style.overflow,document.body.style.overflow="hidden"):document.body.style.overflow=r||""),()=>{(0,x._f)()&&(document.body.style.overflow=r||"")}),[t]),(0,p.useEffect)(()=>{if(l===d)return;nc=new WeakMap;let e=t=>nc.has(t)?nc.get(t):"link"in t&&t.link&&g(t.link)||"items"in t&&t.items.some(t=>e(t))?(nc.set(t,!0),!0):(nc.set(t,!1),!1),t=n=>{"items"in n&&(n.items.forEach(t),e(n)&&(n.collapsed=!1))},n=l.filter(Boolean).flat();n.forEach(t),h(n)},[l,m]),(0,c.jsxs)("aside",{className:`${t8.sidebar} rspress-sidebar ${t?t8.open:""}`,children:[a?.showNavbar?(0,c.jsx)("div",{className:t8.navTitleMask,children:o||(0,c.jsx)(t5,{})}):null,(0,c.jsx)("div",{className:`rspress-scrollbar ${t8.sidebarContent}`,children:(0,c.jsxs)("nav",{className:"pb-2",children:[n,(0,c.jsx)(nu,{sidebarData:d,setSidebarData:h}),i]})})]})}function nu({sidebarData:e,setSidebarData:t}){let n=ni();return(0,c.jsx)(c.Fragment,{children:e.map((e,r)=>(0,c.jsx)(nh,{item:e,index:r,setSidebarData:t,activeMatcher:n},r))})}function nh(e){let{item:t,index:n,setSidebarData:r,activeMatcher:i}=e;return t9(t)?(0,c.jsx)(t6,{depth:0,dividerType:t.dividerType},n):nt(t)?(0,c.jsx)(ns,{sectionHeaderText:t.sectionHeaderText,tag:t.tag},n):nn(t)?(0,c.jsx)("div",{className:"rspress-sidebar-item rspress-sidebar-custom-link","data-context":t.context,children:(0,c.jsx)(no,{id:String(n),item:t,depth:0,collapsed:t.collapsed??!0,setSidebarData:r,activeMatcher:i},n)},n):(0,c.jsx)(no,{id:String(n),item:t,depth:0,activeMatcher:i,collapsed:t.collapsed??!0,setSidebarData:r},n)}let np={link:"link_a7cea"},nx=(e,t)=>{let{hash:n}=window.location,r=decodeURIComponent(n),i=r.length>1&&document.getElementById(r.slice(1));r&&i&&tH(i,e,t)};function nm(e){let{href:t="/",children:n,className:r="",onNavigate:i,onClick:a}=e,o=(0,u.s0)(),{pathname:s}=(0,u.TH)(),{scrollPaddingTop:l}=tM(),d=(0,p.useMemo)(()=>(0,u.pJ)((0,u.AP)(t)),[t]),h=(0,x.xf)(t),m=t.startsWith("#");if(h)return(0,c.jsx)("a",{...e,href:t,target:"_blank",rel:"noopener noreferrer",className:`${np.link} ${r}`,children:n});if(m)return(0,c.jsx)("a",{...e,href:t,className:`${np.link} ${r}`,children:n});let g=async e=>{if(0===e.button&&(!e.currentTarget.target||"_self"===e.currentTarget.target)&&!e.metaKey&&!e.shiftKey&&!e.altKey&&!e.ctrlKey){if(e.preventDefault(),!t1(d,s)){let e=(0,u.Ww)(d);if(e){let t=setTimeout(()=>{U.start()},200);await e.preload(),clearTimeout(t),U.done()}}i?.(),o(d,{replace:!1}),setTimeout(()=>{nx(!1,l)},100)}};return(0,c.jsx)("a",{...e,href:d,className:`${np.link} ${r}`,onMouseEnter:()=>nr(d),onClick:e=>{a?.(e),g(e)},children:n})}U.configure({showSpinner:!1});let ng=({header:e,onItemClick:t})=>(0,c.jsx)("li",{children:(0,c.jsx)(nm,{href:`#${e.id}`,className:"rspress-toc-link sm:text-normal text-sm",style:{marginLeft:(e.depth-2)*12},onClick:()=>{t?.(e)},children:(0,c.jsx)("span",{className:"rspress-toc-link-text block",children:tJ(e.text)})})});function nf({onItemClick:e}){let{page:t}=(0,u.Vi)();return t.toc.length>0&&(0,c.jsx)("ul",{children:t.toc.map(t=>(0,c.jsx)(ng,{header:t,onItemClick:e},t.id))})}function nv({isSidebarOpen:e,onIsSidebarOpenChange:t,outlineTitle:n,uiSwitch:r}){let{page:i}=(0,u.Vi)(),a=(0,p.useRef)(null),o=(0,p.useRef)(null),[s,l]=(0,p.useState)(!1),{pathname:d}=(0,u.TH)();(0,p.useEffect)(()=>{t(!1)},[d]),(0,p.useEffect)(()=>(document.addEventListener("mouseup",h),document.addEventListener("touchend",h),()=>{document.addEventListener("mouseup",h),document.removeEventListener("touchend",h)}),[]);let h=(0,p.useCallback)(e=>{let{current:t}=o;if(t?.contains(e.target))return;let{current:n}=a;n&&!n.contains(e.target)&&l(!1)},[]),x=(0,p.useCallback)(()=>{l(!1)},[]),m=i.toc.length>0;return(0,c.jsx)("div",{className:`rspress-sidebar-menu-container ${m?"":"no-toc"}`,children:(0,c.jsxs)("div",{className:"rspress-sidebar-menu",children:[r?.showSidebar&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)("button",{type:"button",onClick:function(){t(!0)},className:"flex-center mr-auto",children:[(0,c.jsx)("div",{className:"text-md mr-2",children:(0,c.jsx)(t7,{icon:K})}),(0,c.jsx)("span",{className:"text-sm",children:"Menu"})]}),e&&(0,c.jsx)("div",{onClick:function(){t(!1)},className:"rspress-sidebar-back-drop",style:{background:"rgba(0, 0, 0, 0.6)"}})]}),r?.showAside&&m&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)("button",{type:"button",onClick:()=>l(e=>!e),className:"flex-center ml-auto",ref:o,children:[(0,c.jsx)("span",{className:"text-sm",children:n}),(0,c.jsx)("div",{className:"text-md mr-2",style:{transform:s?"rotate(90deg)":"rotate(0deg)",transition:"transform 0.2s ease-out",marginTop:"2px"},children:(0,c.jsx)(t7,{icon:W})})]}),(0,c.jsx)("div",{className:`rspress-local-toc-container ${s?"rspress-local-toc-container-show":""}`,children:(0,c.jsx)(nf,{onItemClick:x})})]})]})})}let ny=(0,p.createContext)({tabData:{},setTabData:()=>{}}),nb="title_fb7eb",nw=e=>{let{href:t="",className:n=""}=e,{normalizeLinkHref:r}=function(){let e=(0,u.Jr)(),t=(0,u.aw)(),n=(0,u.Vi)(),r=n.siteData.lang,i=n.siteData.multiVersion.default;return{normalizeLinkHref:n=>{let a=n;if((r||i)&&!(0,x.xf)(a)&&!a.startsWith("#")){let n=(a=(0,u.E9)(a)).split("/").filter(Boolean),o="",s="",l="";return i&&(t!==i?(o=t,n[0]===t&&n.shift()):n[0]===i&&n.shift()),r&&(e!==r?(s=e,n[0]===e&&n.shift()):n[0]===r&&n.shift()),l=n.join("/"),(0,u.AP)((0,u.pJ)([o,s,l].filter(Boolean).join("/")))}return a}}}();return(0,c.jsx)(nm,{...e,className:`${n} link_a9ef4 inline-link_f855c`,href:r(t)})},nk=e=>(0,c.jsx)("h1",{...e,className:`rspress-doc-title text-3xl mb-10 leading-10 tracking-tight ${nb}`}),nI=e=>(0,c.jsx)("h2",{...e,className:`mt-12 mb-6 pt-8 text-2xl tracking-tight border-t-[1px] border-divider-light ${nb}`}),nD=e=>(0,c.jsx)("h3",{...e,className:`mt-10 mb-2 leading-7 text-xl ${nb}`}),nE=e=>(0,c.jsx)("h4",{...e,className:`mt-8 leading-6 text-lg ${nb}`}),nF=e=>(0,c.jsx)("h5",{...e,className:nb}),nA=e=>(0,c.jsx)("h6",{...e,className:nb}),nC={asideContainer:"aside-container_bc5fa",content:"content_ff766",docLayout:"docLayout_af141"};function nj(e){let{beforeDocFooter:t,afterDocFooter:n,beforeDoc:r,afterDoc:i,beforeDocContent:a,afterDocContent:o,beforeOutline:s,afterOutline:l,beforeSidebar:x,afterSidebar:m,uiSwitch:g,navTitle:f,components:v}=e,{siteData:y,page:b}=(0,u.Vi)(),{headingTitle:w,title:k,toc:I=[],frontmatter:D}=b,[E,F]=(0,p.useState)({}),{themeConfig:A}=y,C=A.enableScrollToTop??!1,j=tL(),P=j?.outlineTitle||A?.outlineTitle||"ON THIS PAGE",S=D?.overview??!1,T={...nY(),...v},N=(0,c.jsx)(ny.Provider,{value:{tabData:E,setTabData:F},children:(0,c.jsx)(d.Zo,{components:T,children:(0,c.jsx)(u.VY,{})})}),_=(0,p.useMemo)(()=>{var e;let t=k&&("string"!=typeof(e=k)?"":(e=e.toLowerCase()).replace(h,"").replace(/ /g,"-"));return!1!==y.themeConfig.fallbackHeadingTitle&&!w&&t&&(0,c.jsxs)(nk,{id:t,children:[k,(0,c.jsx)(nw,{className:"header-anchor",href:`#${t}`,"aria-hidden":!0,children:"#"})]})},[w,k,y.themeConfig.fallbackHeadingTitle]),[B,O]=(0,p.useState)(!1);return(0,c.jsxs)("div",{className:`${nC.docLayout} pt-0`,style:{...g?.showNavbar?{}:{marginTop:0}},children:[r,g?.showSidebar&&(0,c.jsx)(nd,{isSidebarOpen:B,beforeSidebar:x,afterSidebar:m,uiSwitch:g,navTitle:f}),(0,c.jsxs)("div",{className:"flex-1 relative min-w-0",children:[(0,c.jsx)(nv,{isSidebarOpen:B,onIsSidebarOpenChange:O,outlineTitle:P,uiSwitch:g}),(0,c.jsxs)("div",{className:`${nC.content} rspress-doc-container flex`,children:[(0,c.jsx)("div",{className:`flex-1 ${S?"":"overflow-x-auto"}`,children:S?(0,c.jsxs)(c.Fragment,{children:[a,(0,c.jsx)(r0,{content:N}),o]}):(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)("div",{className:"rspress-doc",children:[a,_,N,o]}),(0,c.jsxs)("div",{className:"rspress-doc-footer",children:[t,g?.showDocFooter&&(0,c.jsx)(t3,{}),n]})]})}),C&&(0,c.jsx)(u.ri,{children:(0,c.jsx)(it,{})}),g?.showAside&&I.length>0&&(0,c.jsxs)("div",{className:nC.asideContainer,style:g?.showNavbar?void 0:{marginTop:0,paddingTop:"32px"},children:[s,(0,c.jsx)(tY,{headers:I,outlineTitle:P}),l]})]})]}),i]})}let nP=(e,t)=>t?(e=e.trim(),(t=t.trim()).startsWith("-")||t.startsWith("|"))?`${e} ${t}`:`${e} - ${t}`:e;function nS(){let{siteData:e,page:t}=(0,u.Vi)(),n=e.lang,r=e.multiVersion.default;if(n&&"undefined"!=typeof window&&location.pathname.includes(`/${n}/`)){let e=location.pathname.replace(`/${n}/`,"/");return window.location.replace(e),(0,c.jsx)(c.Fragment,{})}let i="/";return r&&t.version!==r&&(i+=`${t.version}/`),n&&t.lang!==n&&(i+=`${t.lang}/`),(0,c.jsxs)("div",{className:"m-auto mt-50 p-16 sm:p-8 sm:pt-24 sm:pb-40 text-center flex-center flex-col",children:[(0,c.jsx)("p",{className:"text-6xl font-semibold",children:"404"}),(0,c.jsx)("h1",{className:"leading-5 pt-3 text-xl font-bold",children:"PAGE NOT FOUND"}),(0,c.jsx)("div",{style:{height:"1px"},className:"mt-6 mx-auto mb-4.5 w-16 bg-gray-light-1"}),(0,c.jsx)("div",{className:"pt-5",children:(0,c.jsx)("a",{className:"py-2 px-4 rounded-2xl inline-block border-solid border-brand text-brand font-medium hover:border-brand-dark hover:text-brand-dark transition-colors duration-300",href:(0,u.pJ)(i),"aria-label":"go to home",children:"Take me home"})})]})}let nT={"code-button-group":"code-button-group_fb445",codeButtonGroup:"code-button-group_fb445","code-copy-button":"code-copy-button_c5089",codeCopyButton:"code-copy-button_c5089","icon-success":"icon-success_d5ec0",iconSuccess:"icon-success_d5ec0","code-copied":"code-copied_e2224",codeCopied:"code-copied_e2224","icon-copy":"icon-copy_ef942",iconCopy:"icon-copy_ef942","icon-wrapped":"icon-wrapped_fb89b",iconWrapped:"icon-wrapped_fb89b","wrapped-btn":"wrapped-btn_a2562",wrappedBtn:"wrapped-btn_a2562","icon-wrap":"icon-wrap_ccd3d",iconWrap:"icon-wrap_ccd3d"},nN=new Map;function n_({codeBlockRef:e}){let t=(0,p.useRef)(null);return(0,c.jsxs)("button",{className:nT.codeCopyButton,onClick:()=>(function(e,t){let n="";if(!e)return;let r=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,null),i=r.nextNode();for(;i;)i.parentElement.classList.contains("linenumber")||(n+=i.nodeValue),i=r.nextNode();if(Y(n)&&t){t.classList.add(nT.codeCopied),clearTimeout(nN.get(t));let e=setTimeout(()=>{t.classList.remove(nT.codeCopied),t.blur(),nN.delete(t)},2e3);nN.set(t,e)}})(e.current,t.current),ref:t,title:"Copy code",children:[(0,c.jsx)(t7,{icon:J,className:nT.iconCopy}),(0,c.jsx)(t7,{icon:Q,className:nT.iconSuccess})]})}let nB={doctype:{color:"var(--code-token-text)",fontStyle:"italic"},token:{color:"var(--code-token-text)"},comment:{color:"var(--code-token-comment)"},punctuation:{color:"var(--code-token-punctuation)"},property:{color:"var(--code-token-parameter)"},constant:{color:"var(--code-token-constant)"},string:{color:"var(--code-token-string)"},symbol:{color:"var(--code-token-symbol)"},variable:{color:"var(--code-token-variable)"},"attr-name":{color:"var(--code-token-symbol)"},"attr-value":{color:"var(--code-token-string-expression)"},builtin:{color:"var(--code-token-symbol)"},function:{color:"var(--code-token-function)"},keyword:{color:"var(--code-token-keyword)"},tag:{color:"var(--code-token-function)"},inserted:{color:"var(--code-token-inserted)"},deleted:{color:"var(--code-token-deleted)"},regex:{color:"var(--code-token-keyword)"},key:{color:"var(--code-token-variable)"},title:{color:"var(--code-token-keyword)"},important:{color:"#EBCB8B",fontWeight:"bold"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"},table:{display:"content"}},nO=!1;function nR(e){let{siteData:t}=(0,u.Vi)(),{meta:n,language:r,codeWrap:i}=e,{showLineNumbers:a}=t.markdown,o="",s=[];return n&&(o=/{[\d,-]*}/i.exec(n)?.[0]||"")&&(s=o.replace(/[{}]/g,"").split(",").map(e=>{let[t,n]=e.split("-");return n?Array.from({length:Number(n)-Number(t)+1},(e,n)=>n+Number(t)):Number(t)}).flat()),nO||(Object.keys(ew).forEach(e=>{ey.registerLanguage(e,ew[e])}),ey.alias(eb),nO=!0),(0,c.jsx)(ey,{language:r,style:nB,wrapLines:!0,className:"code",wrapLongLines:i,customStyle:{backgroundColor:"inherit"},showLineNumbers:a||s.length>0,lineProps:e=>({style:{...s.includes(e)?{backgroundColor:"var(--rp-code-line-highlight-color)"}:{},display:"block",padding:"0 1.25rem"}}),children:String(e.children).trim()})}function nq(e){let{siteData:t}=(0,u.Vi)(),n=e.codeHighlighter??t.markdown.codeHighlighter,{defaultWrapCode:r}=t.markdown,[i,a]=(0,p.useState)(r),o=(0,p.useRef)(null),s=(0,p.useRef)(null),{className:l}=e,d=l?.replace(/language-/,"");if(!d)return(0,c.jsx)("code",{...e});let h=e=>{i?e?.classList.remove(nT.wrappedBtn):e?.classList.add(nT.wrappedBtn),a(!i)};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)("div",{ref:s,children:"prism"===n?(0,c.jsx)(nR,{...e,language:d,codeWrap:i}):(0,c.jsx)("pre",{...e,style:{overflowX:"auto"},children:(0,c.jsx)("code",{style:{whiteSpace:i?"pre-wrap":"pre"},children:e.children})})}),(0,c.jsxs)("div",{className:nT.codeButtonGroup,children:[(0,c.jsxs)("button",{ref:o,className:nT.codeWrapButton,onClick:()=>h(o.current),title:"Toggle code wrap",children:[(0,c.jsx)(t7,{icon:Z,className:nT.iconWrapped}),(0,c.jsx)(t7,{icon:G,className:nT.iconWrap})]}),(0,c.jsx)(n_,{codeBlockRef:s})]})]})}let nL=e=>(0,c.jsx)("hr",{...e,className:"my-12 border-t border-solid border-divider-light"}),nM=e=>(0,c.jsx)("img",{...e,src:(0,u.i6)(e.src||"")}),nz=e=>(0,c.jsx)("ol",{...e,className:"list-decimal pl-5 my-4 leading-7"}),nH=e=>(0,c.jsx)("ul",{...e,className:"list-disc pl-5 my-4 leading-7"}),n$=e=>(0,c.jsx)("li",{...e,className:"[&:not(:first-child)]:mt-2"}),nW=e=>(0,c.jsx)("p",{...e,className:"my-4 leading-7"}),nK=e=>(0,c.jsx)("blockquote",{...e,className:"border-l-2 border-solid border-divider pl-4 my-6 transition-colors duration-500 blockquote_f1063"}),nU=e=>(0,c.jsx)("strong",{...e,className:"font-semibold"});function nV({children:e}){let t=e=>{let{className:t,meta:n}=e.props,r=function(e){if(!e)return"";let t=e,n=/{[\d,-]*}/i;return n.exec(e)?.[0]&&(t=e.replace(n,"").trim()),t=t.split("=")[1]??"",t?.replace(/["'`]/g,"")}(n);return(0,c.jsxs)("div",{className:t||"language-bash",children:[r&&(0,c.jsx)("div",{className:"rspress-code-title",children:r}),(0,c.jsx)("div",{className:"rspress-code-content rspress-scrollbar",children:e})]})};return Array.isArray(e)?(0,c.jsx)("div",{children:e.map(e=>t(e))}):t(e)}let nG=e=>(0,c.jsx)("table",{...e,className:"block border-collapse text-base my-5 overflow-x-auto leading-7 border-gray-light-3 dark:border-divider"}),nZ=e=>(0,c.jsx)("tr",{...e,className:"border border-solid transition-colors duration-500 even:bg-soft border-gray-light-3 dark:border-divider"}),nJ=e=>(0,c.jsx)("td",{...e,className:"border border-solid px-4 py-2 border-gray-light-3 dark:border-divider"}),nQ=e=>(0,c.jsx)("th",{...e,className:"border border-solid px-4 py-2 text-text-1 text-base font-semibold border-gray-light-3 dark:border-divider"});function nY(){return{h1:nk,h2:nI,h3:nD,h4:nE,h5:nF,h6:nA,ul:nH,ol:nz,li:n$,table:nG,td:nJ,th:nQ,tr:nZ,hr:nL,p:nW,blockquote:nK,strong:nU,a:nw,code:nq,pre:nV,img:nM}}let nX="default",n1=/[\u3131-\u314e|\u314f-\u3163|\uac00-\ud7a3]/u,n0=/[\u0400-\u04FF]/u;function n2(e){let t=e.toString().toLowerCase().normalize("NFD");if(n0.test(String(e)))return t.normalize("NFC");let n=t.replace(/[\u0300-\u036f]/g,"");return n1.test(String(e))?n.normalize("NFC"):n}function n3(e){return e.replace(/https?:\/\/[^/]+/,"")}function n4(e){return e.charCodeAt(0)>255?3:1}let n5=e=>e.map(e=>"string"==typeof e?{value:e,label:e}:e);function n6(e,t){let n=0,r=0;for(let i=0;i=t);i++)r+=n4(e.charAt(i)),n++;return n}function n7(e){let t=0;for(let n=0;n{console.error("Failed to fetch search index, please reload the page and try again."),console.error(e)};try{let e=await fetch(o);if(e.ok)return e.json();s(e)}catch(e){s(e)}return[]}async fetchSearchIndex(e){if(this.#r)return this.#r;let{currentLang:t,currentVersion:n}=e,r="remote"!==e.mode&&e.versioned;return this.#r=this.#i(t,r?n:""),this.#r}async init(e){let t=(await this.fetchSearchIndex(e)).map(e=>({...e,normalizedContent:n2(e.content),headers:e.toc.map(e=>n2(e.text)).join(" "),normalizedTitle:n2(e.title)})),n={tokenize:"full",document:{id:"id",store:!0,index:["normalizedTitle","headers","normalizedContent"]},cache:100};for(let e of(this.#e=new e3(n),this.#t=new e3({...n,tokenize:e=>re(e,n8)}),this.#n=new e3({...n,tokenize:e=>re(e,n9)}),t))this.#e.addAsync(e.id,e),this.#t.addAsync(e.id,e),this.#n.addAsync(e.id,e)}async search(e){let{keyword:t,limit:n}=e,r={enrich:!0,limit:n,index:["normalizedTitle","headers","normalizedContent"]},i=await Promise.all([this.#e?.searchAsync(t,r),this.#t?.searchAsync(t,r),this.#n?.searchAsync(t,r)]),a=[],o=new Set;return i.forEach(e=>{e&&function(e){for(let t of e)t.result.forEach(e=>{let t=e.id;o.has(t)||(o.add(t),a.push(e.doc))})}(e)}),[{index:nX,hits:a}]}}class rn{#a;async init(e){this.#a=e}async fetchSearchIndex(e){return[]}async search(e){let{apiUrl:t,searchIndexes:n}=this.#a,{keyword:r,limit:i}=e,a=Object.entries({keyword:r,limit:i.toString(),searchIndexes:n?.map(e=>"string"==typeof e?e:e.value).join(",")||"",lang:this.#a?.currentLang??""}).map(e=>e.map(encodeURIComponent).join("=")).join("&");try{return(await fetch(`${t}?${a}`)).json()}catch(e){return console.error(e),[]}}}var rr=((o={}).Default="default",o.Custom="custom",o);class ri{#a;#o=nX;#s;constructor(e){this.#a=e,this.#o=e.indexName??nX,"remote"===e.mode?this.#s=new rn:this.#s=new rt}async init(){await this.#s?.init(this.#a)}async fetchSearchIndex(){return this.#s?.fetchSearchIndex(this.#a)}async match(e,t=7){let n=await this.#s?.search({keyword:e,limit:t}),r=n2(e),i=n?.find(e=>this.#l(e.index))||{index:nX,renderType:rr.Default,hits:[]};return[{group:this.#o,renderType:rr.Default,result:this.#c(r,i)},...(n?.filter(e=>!this.#l(e.index))||[]).map(e=>({group:e.index,renderType:rr.Default,result:this.#c(r,e)}))]}#c(e,t){let n=[];return t?.hits.forEach(t=>{this.#d(t,e,n);let r=this.#u(t,e,n);this.#h(t,e,n,r)}),n}#d(e,t,n){let{title:r=""}=e,i=n2(r);return!!i.includes(t)&&(n.push({type:"title",title:r,header:r,link:`${e.domain}${(0,u.AP)(e.routePath)}`,query:t,highlightInfoList:[{start:i.indexOf(t),length:n7(t)}]}),!0)}#u(e,t,n){let r=new WeakSet,{toc:i=[],domain:a="",title:o=""}=e;for(let[s,l]of i.entries())if(n2(l.text).includes(t)){let c=(function(e,t){let n=e[t],r=t,i=[n];for(;n&&n.depth>2;){let t=!1;for(let a=r-1;a>=0;a--){let o=e[a];if(o.depth>1&&o.depth===n.depth-1){n=o,r=a,i.unshift(n),t=!0;break}}if(!t)break}return i})(i,s).map(e=>e.text).join(" > "),d=n2(c).indexOf(t),h=`${o} > `;n.push({type:"header",title:e.title,header:`${h}${c}`,highlightInfoList:[{start:d+h.length,length:n7(t)}],link:`${a}${(0,u.AP)(e.routePath)}#${l.id}`,query:t}),r.add(l)}return r}#h(e,t,n,r){let{content:i,toc:a,domain:o}=e;if(!i.length)return;let s=n2(i),l=s.indexOf(t),c=a.map(e=>e.charIndex),d=e=>a[c.findIndex((t,n)=>{if(!(n=e)return!0}return!1})],h=e=>e&&r?.has(e);if(-1===l){let r=e._matchesPosition?.content;if(!r?.length)return;let a=e._matchesPosition.content[0].start,s=d(a);if(h(s))return;let l=n6(i,a),c=n6(i,a+100),p=i.slice(l,c),x=e._matchesPosition.content.filter(e=>e.start>=a&&e.start+e.length<=a+100).map(e=>({start:n6(i,e.start)-l+3,length:e.length}));n.push({type:"content",title:e.title,header:s?.text??e.title,link:`${o}${(0,u.AP)(e.routePath)}${s?`#${s.id}`:""}`,query:t,highlightInfoList:x,statement:`...${p}...`});return}for(;-1!==l;){let a=d(l),c=i.slice(0,l).lastIndexOf("\n");c=-1===c?0:c;let p=i.indexOf("\n\n",l+t.length),x=i.slice(c,p);x.length>100&&(x=this.#p(x,t));let m=n2(x).indexOf(t),g=[{start:m,length:n7(t)}];!h(a)&&(n.push({type:"content",title:e.title,header:a?.text??e.title,statement:x,highlightInfoList:g,link:`${o}${(0,u.AP)(e.routePath)}${a?`#${a.id}`:""}`,query:t}),a&&r?.add(a)),l=s.indexOf(t,l+x.length-m)}}#p(e,t){let n=n2(e).indexOf(n2(t)),r=Math.floor((100-t.length)/2),i=e.slice(0,n);i.length>r&&(i=`...${e.slice(n-r+3,n)}`);let a=e.slice(n+t.length);return a.length>r&&(a=`${e.slice(n+t.length,n+r-3)}...`),i+t+a}#l(e){return e===this.#o||e===nX}}let ra=e=>{let t=(0,p.useRef)(e);return t.current=e,(0,p.useRef)((...e)=>t.current(...e)).current},ro=e=>{let[t,n]=(0,p.useState)(()=>"undefined"!=typeof window&&window.matchMedia(e).matches);return(0,p.useEffect)(()=>{let t=window.matchMedia(e),r=e=>n(e.matches);return t.addEventListener("change",r),()=>t.removeEventListener("change",r)},[e]),t},rs=(e,t)=>{let[n,r]=(0,p.useState)(()=>"undefined"==typeof window?t:localStorage.getItem(e)??t),i=(0,p.useCallback)(t=>{r(n=>{let r="function"==typeof t?t(n):t;return null==r?localStorage.removeItem(e):localStorage.setItem(e,r),r})},[e]);return(0,p.useEffect)(()=>{let n=n=>{n.key===e&&r(localStorage.getItem(e)??t)};return window.addEventListener("storage",n),()=>{window.removeEventListener("storage",n)}},[e,t]),[n,i]},rl=e=>["light","dark","auto"].includes(e)?e:"auto",rc=!1===ts.Z.themeConfig.darkMode,rd=()=>{let e=ro("(prefers-color-scheme: dark)"),[t,n]=rs(x.rp,"auto"),r=ra(()=>{if(rc)return"light";let n=rl(t);return"auto"===n?e?"dark":"light":n}),[i,a]=(0,p.useState)(()=>{if("undefined"==typeof window)return"light";let e=window.RSPRESS_THEME??window.MODERN_THEME;return e?"dark"===e?"dark":"light":r()}),o=(0,p.useCallback)((e,t=e)=>{rc||(a(e),n(t),l(!0))},[]);(0,p.useEffect)(()=>{document.documentElement.classList.toggle("dark","dark"===i),document.documentElement.style.colorScheme=i},[i]);let[s,l]=(0,p.useState)(!0);return(0,p.useEffect)(()=>{l(!1)},[s]),(0,p.useEffect)(()=>{s||o(r(),rl(t))},[t]),(0,p.useEffect)(()=>{s||o(e?"dark":"light","auto")},[e]),[i,o]},ru={button:"button_e8e0d",medium:"medium_fe00b",big:"big_f7033",brand:"brand_dc619",alt:"alt_b0249"};function rh(e){let{theme:t="brand",size:n="big",href:r="/",external:i=!1,className:a=""}=e,o=null;return"button"===e.type?o="button":"a"===e.type&&(o=i?"a":nm),p.createElement(o??"a",{className:`${ru.button} ${ru[t]} ${ru[n]} ${a}`,href:r},e.text)}let rp={editLink:"editLink_e1cfa"};function rx(){let e=function(){let{siteData:e,page:t}=(0,u.Vi)(),n=tL().editLink??e.themeConfig?.editLink??{};if(!n.docRepoBaseUrl||!n.text)return null;let{docRepoBaseUrl:r}=n;r.endsWith("/")||(r+="/");let i=t._relativePath.replace(/\\/g,"/"),a=`${r}${i}`;return{text:n.text,link:a}}();if(!e)return null;let{text:t,link:n}=e;return(0,c.jsx)("a",{href:n,target:"_blank",className:rp.editLink,children:t})}let rm={"grid-2":"grid-2_bce10",grid2:"grid-2_bce10","grid-4":"grid-4_bd059",grid4:"grid-4_bd059","grid-6":"grid-6_ce438",grid6:"grid-6_ce438","grid-3":"grid-3_bf296",grid3:"grid-3_bf296",featureCard:"featureCard_a17b6"},rg=e=>{let{span:t}=e;return`grid-${t||4}`};function rf({frontmatter:e,routePath:t}){let n=e?.features;return(0,c.jsx)("div",{className:"overflow-hidden m-auto flex flex-wrap max-w-6xl",children:n?.map(e=>{let{icon:n,title:r,details:i,link:a}=e,o=a;return a&&(o=(0,x.xf)(a)?a:(0,u.AP)((0,x.pJ)(a,t))),(0,c.jsx)("div",{className:`${rm[rg(e)]} rounded hover:var(--rp-c-brand)`,children:(0,c.jsx)("div",{className:"h-full p-2",children:(0,c.jsxs)("article",{className:`rspress-home-feature-card ${rm.featureCard} h-full p-8 rounded-4xl border-transparent`,style:{cursor:o?"pointer":"auto"},onClick:()=>{o&&(window.location.href=o)},children:[n?(0,c.jsx)("div",{className:"flex-center",children:(0,c.jsx)("div",{className:"rspress-home-feature-icon w-12 h-12 text-3xl text-center",children:tK(n)})}):null,(0,c.jsx)("h2",{className:"rspress-home-feature-title font-bold text-center",children:r}),(0,c.jsx)("p",{className:"rspress-home-feature-detail leading-6 pt-2 text-sm text-text-2 font-medium",children:tK(i)})]},r)})},r)})})}function rv(){let{siteData:e}=(0,u.Vi)(),{message:t}=e.themeConfig.footer||{};return t?(0,c.jsx)("footer",{className:"absolute bottom-0 mt-12 py-8 px-6 sm:p-8 w-full border-t border-solid border-divider-light",children:(0,c.jsx)("div",{className:"m-auto w-full text-center",children:(0,c.jsx)("div",{className:"font-medium text-sm text-text-2",dangerouslySetInnerHTML:{__html:t}})})}):null}let ry={name:"modern",text:"modern ssg",tagline:"modern ssg",actions:[],image:void 0};function rb({frontmatter:e,routePath:t}){let n=e?.hero||ry,r=void 0!==n.image,i=r?"sm:max-w-xl":"sm:max-w-4xl",a=n.text?n.text.toString().split(/\n/g).filter(e=>""!==e):[],o="string"==typeof n.image?.src?{light:n.image.src,dark:n.image.src}:n.image?.src||{light:"",dark:""};return(0,c.jsxs)("div",{className:"m-auto pt-0 px-6 pb-12 sm:pt-10 sm:px-16 md:pt-16 md:px-16 md:pb-16 relative",children:[(0,c.jsx)("div",{className:"mask_bbaa6",style:{left:r?"75%":"50%"}}),(0,c.jsxs)("div",{className:"m-auto flex flex-col md:flex-row max-w-6xl min-h-[50vh] mt-12 sm:mt-0",children:[(0,c.jsxs)("div",{className:"flex flex-col justify-center items-center text-center max-w-xl sm:max-w-4xl m-auto order-2 md:order-1",children:[(0,c.jsx)("h1",{className:"font-bold text-3xl pb-2 sm:text-6xl md:text-7xl m-auto sm:m-4 md:m-0 md:pb-3 lg:pb-2 leading-tight z-10",children:(0,c.jsx)("span",{className:"clip_aacad",style:{lineHeight:"1.3"},children:tK(n.name)})}),0!==a.length&&a.map(e=>(0,c.jsx)("p",{className:`rspress-home-hero-text mx-auto md:m-0 text-3xl sm:text-5xl md:text-6xl sm:pb-2 font-bold z-10 ${i}`,style:{lineHeight:"1.2"},children:tK(e)},e)),(0,c.jsx)("p",{className:`rspress-home-hero-tagline whitespace-pre-wrap pt-4 m-auto md:m-0 text-sm sm:tex-xl md:text-[1.5rem] text-text-2 font-medium z-10 ${i}`,children:tK(n.tagline)}),n.actions?.length&&(0,c.jsx)("div",{className:"grid md:flex md:flex-wrap md:justify-center gap-3 m--1.5 pt-6 sm:pt-8 z-10",children:n.actions.map(e=>{let n=(0,x.xf)(e.link)?e.link:(0,u.AP)((0,x.pJ)(e.link,t));return(0,c.jsx)("div",{className:"flex flex-shrink-0 p-1",children:(0,c.jsx)(rh,{type:"a",href:n,text:tK(e.text),theme:e.theme,className:"w-full"})},n)})})]}),r?(0,c.jsxs)("div",{className:"rspress-home-hero-image md:flex-center m-auto order-1 md:order-2 sm:flex md:none lg:flex",children:[(0,c.jsx)("img",{src:(0,u.i6)(o.light),alt:n.image?.alt,srcSet:rw(n.image?.srcset),sizes:rw(n.image?.sizes),width:375,height:375,className:"dark:hidden"}),(0,c.jsx)("img",{src:(0,u.i6)(o.dark),alt:n.image?.alt,srcSet:rw(n.image?.srcset),sizes:rw(n.image?.sizes),width:375,height:375,className:"hidden dark:block"})]}):null]})]})}function rw(e){return(Array.isArray(e)?e:[e]).filter(Boolean).join(", ")||void 0}function rk(){let{lastUpdatedText:e="Last Updated"}=tL(),{page:{lastUpdatedTime:t},siteData:n}=(0,u.Vi)(),{themeConfig:r}=n,i=r?.lastUpdatedText||e;return(0,c.jsx)("div",{className:"flex text-sm text-text-2 leading-6 sm:leading-8 font-medium",children:(0,c.jsxs)("p",{children:[i,": ",(0,c.jsx)("span",{children:t})]})})}function rI(){let{nav:e}=tL(),t=(0,u.aw)();return Array.isArray(e)?e:[...e[t.length>0?t:"default"]]}function rD(e){let{pathname:t,base:n}=e,r=new RegExp(e.activeMatch||e.link).test((0,x.tz)(t,n));return(0,c.jsx)(nm,{href:(0,u.AP)(e.link),onClick:e.onClick,children:(0,c.jsxs)("div",{className:`rspress-nav-menu-item ${t4.singleItem} ${r?t4.activeItem:""} text-sm font-medium ${e.compact?"mx-0.5":"mx-1.5"} px-3 py-2 flex items-center`,children:[(0,c.jsx)(im,{tag:e.tag}),e.text,e.rightIcon]},e.text)})}function rE(){let{siteData:e,page:t}=(0,u.Vi)(),n=(0,u.aw)(),{pathname:r,search:i}=(0,u.TH)(),a=e.lang||"",o=e.multiVersion.default||"",s=Object.values(e.locales||e.themeConfig.locales||{}),l=e.route?.cleanUrls||!1,d=s.length>1,{lang:h,pageType:p}=t,{base:m}=e;return d?{text:(0,c.jsx)(t7,{icon:tF,style:{width:"18px",height:"18px"}}),items:s.map(e=>({text:e?.label,link:(0,x.$U)(r+i,{current:h,target:e.lang,default:a},{current:n,default:o},m,l,"404"===p)})),activeValue:s.find(e=>h===e.lang)?.label}:{items:[]}}function rF(){let{siteData:e,page:t}=(0,u.Vi)(),n=(0,u.aw)(),{pathname:r}=(0,u.TH)(),i=e.route?.cleanUrls||!1,a=e.multiVersion.default||"",o=e.multiVersion.versions||[],{base:s}=e;return{items:o.map(e=>({text:e,link:(0,x.xM)(r,{current:n,target:e,default:a},s,i,"404"===t.pageType)})),text:n,activeValue:n}}let rA={socialLinksIcon:"social-links-icon_a4ad0",menuItem:"menu-item_e90a6"},rC=e=>{let{link:t,popperStyle:n={}}=e,{icon:r,mode:i="link",content:a}=t,o=(0,c.jsx)(c.Fragment,{});if(r){let e="string"==typeof r?({github:''})[r]:r.svg;o=(0,c.jsx)("div",{dangerouslySetInnerHTML:{__html:e}})}let[s,l]=(0,p.useState)(!1),d=()=>{l(!0)},u=()=>{l(!1)};return"link"===i?(0,c.jsx)("a",{href:a,target:"_blank",rel:"noopener noreferrer",className:"social-links",children:(0,c.jsx)("div",{className:`${rA.socialLinksIcon}`,children:o})},a):"text"===i?(0,c.jsxs)("div",{className:`${rA.socialLinksIcon} cursor-pointer relative mx-3`,onMouseEnter:d,onMouseLeave:u,children:[o,s?(0,c.jsx)("div",{style:{boxShadow:"var(--rp-shadow-3)",border:"1px solid var(--rp-c-divider-light)",...n},className:"z-[1] p-3 w-50 absolute right-0 bg-white dark:bg-dark",children:(0,c.jsx)("div",{className:"text-md",children:a})}):null]}):"img"===i?(0,c.jsxs)("div",{className:`${rA.socialLinksIcon} cursor-pointer relative`,onMouseEnter:d,onMouseLeave:u,children:[o,s?(0,c.jsx)("div",{className:"break-all z-[1] p-3 w-[50px] h-[50px] absolute right-0 bg-white dark:bg-dark rounded-xl",style:{boxShadow:"var(--rp-shadow-3)",...n},children:(0,c.jsx)("img",{src:a,alt:"img"})}):null]}):"dom"===i?(0,c.jsxs)("div",{className:`${rA.socialLinksIcon} cursor-pointer relative`,onMouseEnter:d,onMouseLeave:u,children:[o,s?(0,c.jsx)("div",{className:"break-all z-[1] p-3 absolute right-0 bg-white dark:bg-dark rounded-xl",style:{boxShadow:"var(--rp-shadow-3)",...n},children:(0,c.jsx)("div",{dangerouslySetInnerHTML:{__html:a}})}):null]}):(0,c.jsx)("div",{})},rj=e=>{let{links:t}=e;return(0,c.jsx)("div",{style:{boxShadow:"var(--rp-shadow-3)",marginRight:"-2px",border:"1px solid var(--rp-c-divider-light)",background:"var(--rp-c-bg)"},className:"absolute top-8 right-0 z-1 p-3 w-32 rounded-2xl flex flex-wrap gap-4",children:t.map(e=>(0,c.jsx)(rC,{link:e,popperStyle:{top:"1.25rem"}},e.content))})},rP=e=>{let{links:t,moreIconVisible:n=!1,mouseEnter:r}=e;return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)("div",{className:"flex-center h-full gap-x-4 transition-colors duration-300 md:mr-2",children:t.map((e,t)=>(0,c.jsx)(rC,{link:e,popperStyle:{top:"2.5rem"}},t))}),n?(0,c.jsx)("div",{className:"md:ml-1 p-2",onMouseEnter:r,children:(0,c.jsx)(t7,{icon:tA})}):null]})},rS=({socialLinks:e})=>{let t=e.length>5,n=e.slice(0,5),r=e.slice(5),[i,a]=(0,p.useState)(!1),o=(0,p.useCallback)(()=>{a(!1)},[a]),s=(0,p.useCallback)(()=>{a(!0)},[a]);return(0,c.jsxs)("div",{className:`social-links ${rA.menuItem} flex-center relative`,onMouseLeave:o,children:[(0,c.jsx)(rP,{links:n,moreIconVisible:t,mouseEnter:s}),i?(0,c.jsx)(rj,{links:r}):null]})},rT=()=>"function"==typeof document?.startViewTransition&&!window.matchMedia("(prefers-reduced-motion: reduce)").matches,rN=()=>{let e=document.createElement("style");return e.innerHTML=` - .rspress-doc { - view-transition-name: none !important; - } - `,document.head.appendChild(e),()=>{document.head.removeChild(e)}};function r_({onClick:e}){let{theme:t,setTheme:n=()=>{}}=(0,p.useContext)(u.Ni);return(0,c.jsx)("div",{onClick:r=>{let i=rT(),a=ts.Z?.themeConfig?.enableAppearanceAnimation,o="dark"===t?"light":"dark",s="dark"===o;if(i&&a){let t=r.clientX,i=r.clientY,a=Math.hypot(Math.max(t,innerWidth-t+200),Math.max(i,innerHeight-i+200)),l=rN(),c=document.startViewTransition(async()=>{(0,tP.flushSync)(()=>{n(o),e?.()})}),d=[`circle(0px at ${t}px ${i}px)`,`circle(${a}px at ${t}px ${i}px)`];c.ready.then(()=>{document.documentElement.animate({clipPath:s?[...d].reverse():d},{duration:400,easing:"ease-in",pseudoElement:s?"::view-transition-old(root)":"::view-transition-new(root)",id:""}).finished.then(()=>{l()})})}else n(o),e?.()},className:"md:mr-2 rspress-nav-appearance",children:(0,c.jsxs)("div",{className:"p-1 border border-solid border-gray-300 text-gray-400 cursor-pointer rounded-md hover:border-gray-600 hover:text-gray-600 dark:hover:border-gray-200 dark:hover:text-gray-200 transition-all duration-300 w-7 h-7",children:[(0,c.jsx)(t7,{className:"dark:hidden",icon:tj,width:"18",height:"18",fill:"currentColor"}),(0,c.jsx)(t7,{className:"hidden dark:block",icon:tC,width:"18",height:"18",fill:"currentColor"})]})})}let rB={navScreen:"navScreen_ec30c",active:"active_d804e",container:"container_c935d",navMenu:"navMenu_b887b",navMenuItem:"navMenuItem_e7978",navAppearance:"navAppearance_bf893",socialAndAppearance:"socialAndAppearance_eda28",navScreenMenuGroup:"navScreenMenuGroup_e771d",open:"open_aaab4",button:"button_ea41e",buttonSpan:"buttonSpan_f4b8f",items:"items_dd149",down:"down_f631a"};function rO(e){let{activeValue:t}=e,[n,r]=(0,p.useState)(!1);function i({item:e}){return(0,c.jsx)("div",{className:"p-1 text-center",children:(0,c.jsx)("span",{className:"text-brand",children:e.text})})}function a({item:e}){return(0,c.jsx)("div",{className:"py-1 font-medium",children:(0,c.jsx)(nm,{href:e.link,children:(0,c.jsx)("div",{children:(0,c.jsx)("div",{className:"flex justify-center",children:(0,c.jsx)("span",{children:e.text})})})})})}let o=e=>t===e.text?(0,c.jsx)(i,{item:e},e.link):(0,c.jsx)(a,{item:e},e.link),s=e=>(0,c.jsxs)("div",{children:["link"in e?o(e):(0,c.jsx)("p",{className:"font-bold text-gray-400 my-1 not:first:border",children:e.text}),e.items.map(o)]});return(0,c.jsxs)("div",{className:`${n?rB.open:""} ${rB.navScreenMenuGroup} relative`,children:[(0,c.jsxs)("button",{className:rB.button,onClick:()=>{r(!n)},children:[(0,c.jsx)("span",{className:rB.buttonSpan,children:e.text}),(0,c.jsx)(tS,{className:`${n?rB.open:""} ${rB.down} `})]}),(0,c.jsx)("div",{children:(0,c.jsx)("div",{className:rB.items,children:e.items.map(e=>(0,c.jsx)("div",{children:"items"in e?s(e):o(e)},e.text))})})]})}let rR=()=>{let e=rE();return(0,c.jsx)("div",{className:"flex text-sm font-bold justify-center",children:(0,c.jsx)("div",{className:"mx-1.5 my-1",children:(0,c.jsx)(rO,{...e})})})},rq=()=>{let e=rF();return(0,c.jsx)("div",{className:`${rB.navTranslations} flex text-sm font-bold justify-center`,children:(0,c.jsx)("div",{className:"mx-1.5 my-1",children:(0,c.jsx)(rO,{...e})})})},rL=()=>(0,c.jsx)("div",{className:`mt-2 ${rB.navAppearance} flex justify-center`,children:(0,c.jsx)(u.ri,{children:(0,c.jsx)(r_,{})})}),rM=({menuItems:e,pathname:t,base:n,langs:r,toggleScreen:i})=>(0,c.jsx)("div",{className:rB.navMenu,children:e.map(e=>(0,c.jsx)("div",{className:`${rB.navMenuItem} w-full`,children:"link"in e?(0,c.jsx)(rD,{pathname:t,base:n,langs:r,onClick:i,...e},e.text):(0,c.jsx)("div",{className:"mx-3 last:mr-0",children:(0,c.jsx)(rO,{...e,items:"items"in e?e.items:e})},e.text)},e.text))});function rz(e){let{isScreenOpen:t,toggleScreen:n,siteData:r,pathname:i}=e,a=(0,p.useRef)(null),o=r.themeConfig.locales||[],s=o.length>1,l=r.multiVersion.versions.length>1,d=rI(),u=!1!==r.themeConfig.darkMode,h=r?.themeConfig?.socialLinks||[],x=h.length>0,m=o.map(e=>e.lang||"zh")||[],{base:g}=r;return(0,p.useEffect)(()=>(a.current&&t&&tD(a.current,{reserveScrollBarGap:!0}),()=>{tE()}),[t]),(0,c.jsx)("div",{className:`${rB.navScreen} ${t?rB.active:""} rspress-nav-screen`,ref:a,id:"navScreen",children:(0,c.jsxs)("div",{className:rB.container,children:[(0,c.jsx)(rM,{menuItems:d,base:g,langs:m,pathname:i,toggleScreen:n}),(0,c.jsxs)("div",{className:"flex-center flex-col gap-2",children:[u&&(0,c.jsx)(rL,{}),s&&(0,c.jsx)(rR,{}),l&&(0,c.jsx)(rq,{}),x&&(0,c.jsx)(rS,{socialLinks:h})]})]})})}let rH={navHamburger:"navHamburger_ac64c",active:"active_bc9a1"};function r$(e){let{siteData:t,pathname:n}=e,{isScreenOpen:r,toggleScreen:i}=function(){let{pathname:e}=(0,u.TH)(),[t,n]=(0,p.useState)(!1);function r(){n(!0),window.addEventListener("resize",a)}function i(){n(!1),window.removeEventListener("resize",a)}function a(){window.outerWidth>=768&&i()}return(0,p.useEffect)(()=>{i()},[e]),{isScreenOpen:t,openScreen:r,closeScreen:i,toggleScreen:function(){t?i():r()}}}();return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(rz,{isScreenOpen:r,toggleScreen:i,siteData:t,pathname:n}),(0,c.jsx)("button",{onClick:i,"aria-label":"mobile hamburger",className:`${r?rH.active:""} rspress-mobile-hamburger ${rH.navHamburger} text-gray-500`,children:(0,c.jsx)(t7,{icon:tl,fill:"currentColor"})})]})}function rW({item:e}){return(0,c.jsxs)("div",{className:"rounded-2xl my-1 flex",style:{padding:"0.4rem 1.5rem 0.4rem 0.75rem"},children:[e.tag&&(0,c.jsx)(im,{tag:e.tag}),(0,c.jsx)("span",{className:"text-brand",children:e.text})]},e.link)}function rK({item:e}){return(0,c.jsx)("div",{className:"font-medium my-1",children:(0,c.jsx)(nm,{href:e.link,children:(0,c.jsx)("div",{className:"rounded-2xl hover:bg-mute",style:{padding:"0.4rem 1.5rem 0.4rem 0.75rem"},children:(0,c.jsxs)("div",{className:"flex",children:[e.tag&&(0,c.jsx)(im,{tag:e.tag}),(0,c.jsx)("span",{children:e.text})]})})})},e.link)}function rU(e){let{activeValue:t,items:n,base:r="",link:i="",pathname:a=""}=e,[o,s]=(0,p.useState)(!1),l=(0,p.useRef)(),d=()=>{l.current&&(clearTimeout(l.current),l.current=void 0)},u=e=>{let n=new RegExp(e.activeMatch||e.link).test((0,x.tz)(a,r));return t===e.text||!t&&n?(0,c.jsx)(rW,{item:e},e.link):(0,c.jsx)(rK,{item:e},e.link)},h=e=>(0,c.jsxs)("div",{children:["link"in e?u(e):(0,c.jsx)("p",{className:"font-bold text-gray-400 my-1 not:first:border",children:e.text}),e.items.map(u)]});return(0,c.jsxs)("div",{className:"relative flex-center h-14",onMouseLeave:()=>{l.current=window.setTimeout(()=>{s(!1)},150)},children:[(0,c.jsx)("button",{onMouseEnter:()=>{d(),s(!0)},className:"rspress-nav-menu-group-button flex-center items-center font-medium text-sm text-text-1 hover:text-text-2 transition-colors duration-200",children:i?(0,c.jsx)(rD,{...e,rightIcon:(0,c.jsx)(t7,{icon:tS})}):(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)("span",{className:"text-sm font-medium flex",style:{marginRight:"2px"},children:[(0,c.jsx)(im,{tag:e.tag}),e.text]}),(0,c.jsx)(t7,{icon:tS})]})}),(0,c.jsx)("div",{className:"rspress-nav-menu-group-content absolute mx-0.8 transition-opacity duration-300",style:{opacity:+!!o,visibility:o?"visible":"hidden",right:0,top:"52px"},onMouseEnter:d,children:(0,c.jsx)("div",{className:"p-3 pr-2 w-full h-full max-h-100vh whitespace-nowrap",style:{boxShadow:"var(--rp-shadow-3)",zIndex:100,border:"1px solid var(--rp-c-divider-light)",borderRadius:"var(--rp-radius-large)",background:"var(--rp-c-bg)"},children:n.map(e=>(0,c.jsx)("div",{children:"items"in e?h(e):u(e)},e.text))})})]})}function rV(){let e=rE();return(0,c.jsx)("div",{className:`translation ${t4.menuItem} flex text-sm font-bold items-center px-3 py-2`,children:(0,c.jsx)("div",{children:(0,c.jsx)(rU,{...e})})})}function rG(){let e=rF();return(0,c.jsx)("div",{className:`translation ${t4.menuItem} flex text-sm font-bold items-center px-3 py-2`,children:(0,c.jsx)("div",{children:(0,c.jsx)(rU,{...e})})})}function rZ(e){let{beforeNavTitle:t,afterNavTitle:n,beforeNav:r,afterNavMenu:i,navTitle:a}=e,{siteData:o,page:s}=(0,u.Vi)(),{base:l}=o,{pathname:d}=(0,u.TH)(),{width:h}=(0,u.iP)(),p=tq(),x=h<1280,m=Object.values(o.locales||o.themeConfig.locales||{}),g=m.length>1,f=o.multiVersion.versions.length>1,v=o.themeConfig.socialLinks||[],y=v.length>0,b=m.map(e=>e.lang||"")||[],w=({menuItems:e})=>(0,c.jsx)("div",{className:"rspress-nav-menu menu h-14",children:e.map(t=>"items"in t||Array.isArray(t)?(0,c.jsx)("div",{className:"mx-3 last:mr-0",children:(0,c.jsx)(rU,{...t,base:l,pathname:d,langs:b,items:"items"in t?t.items:t})},t.text):(0,c.jsx)(rD,{pathname:d,langs:b,base:l,compact:e.length>5,...t},t.link))}),k=rI(),I=e=>e.position??"right",D=k.filter(e=>"left"===I(e)),E=k.filter(e=>"right"===I(e)),F=o?.themeConfig?.search!==!1,A=!1!==o.themeConfig.darkMode;return(0,c.jsxs)(c.Fragment,{children:[r,(0,c.jsx)("div",{className:`${t4.navContainer} rspress-nav px-6 ${p&&!x?t4.hidden:""} ${!x||!p||"doc"!==s.pageType?t4.sticky:t4.relative}`,children:(0,c.jsxs)("div",{className:`${t4.container} flex justify-between items-center h-full`,children:[t,a||(0,c.jsx)(t5,{}),n,(0,c.jsxs)("div",{className:"flex flex-1 justify-end items-center",children:[D.length>0?(0,c.jsx)("div",{className:t4.leftNav,children:(0,c.jsx)(w,{menuItems:D})}):null,(0,c.jsxs)("div",{className:t4.rightNav,children:[F&&(0,c.jsx)("div",{className:"flex sm:flex-1 items-center sm:pl-4 sm:pr-2",children:(0,c.jsx)(ix,{})}),(0,c.jsx)(w,{menuItems:E}),(0,c.jsxs)("div",{className:"flex-center flex-row",children:[g&&(0,c.jsx)(rV,{}),f&&(0,c.jsx)(rG,{}),A&&(0,c.jsx)("div",{className:"mx-2",children:(0,c.jsx)(r_,{})}),y&&(0,c.jsx)(rS,{socialLinks:v})]})]}),i,(0,c.jsxs)("div",{className:t4.mobileNavMenu,children:[x&&F&&(0,c.jsx)(ix,{}),(0,c.jsx)(r$,{siteData:o,pathname:d})]})]})]})})]})}let rJ={"header-anchor":"header-anchor_d4f17",headerAnchor:"header-anchor_d4f17","overview-groups":"overview-groups_ced08",overviewGroups:"overview-groups_ced08","overview-group-li":"overview-group-li_e0f17",overviewGroupLi:"overview-group-li_e0f17","level-2":"level-2_e4d63",level2:"level-2_e4d63","level-3":"level-3_b489a",level3:"level-3_b489a","level-4":"level-4_a9543",level4:"level-4_a9543","overview-group":"overview-group_f8331",overviewGroup:"overview-group_f8331",header:"header_ba4f6"},rQ=e=>e.toLowerCase().replace(/-/g," "),rY=(e,t)=>rQ(e).includes(rQ(t)),rX=({query:e,setQuery:t,searchRef:n,filterNameText:r,filterPlaceholderText:i})=>(0,c.jsxs)("div",{className:"flex items-center justify-start gap-4",children:[(0,c.jsx)("label",{htmlFor:"api-filter",children:r}),(0,c.jsx)("input",{ref:n,type:"search",placeholder:i,id:"api-filter",value:e,onChange:e=>t(e.target.value),className:"border border-gray-300 dark:border-gray-700 rounded-lg px-3 py-2 transition-shadow duration-250 ease-in-out focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-opacity-50"})]}),r1=({group:e,styles:t})=>(0,c.jsxs)("div",{className:"mb-16",children:[(0,c.jsx)("h2",{children:tJ(e.name)}),(0,c.jsx)("div",{className:t.overviewGroups,children:e.items.map(e=>(0,c.jsxs)("div",{className:t.overviewGroup,children:[(0,c.jsx)("div",{className:"flex",children:(0,c.jsx)("h3",{style:{marginBottom:8},children:(0,c.jsx)(nm,{href:(0,u.AP)(e.link),children:tJ(e.text)})})}),(0,c.jsx)("ul",{className:"list-none",children:e.headers?.map(n=>(0,c.jsx)("li",{className:`${t.overviewGroupLi} ${t[`level${n.depth}`]} first:mt-2`,children:(0,c.jsx)(nm,{href:`${(0,u.AP)(e.link)}#${n.id}`,children:tJ(n.text)})},n.id))})]},e.link))})]},e.name);function r0(e){let{siteData:t,page:{routePath:n,title:r,frontmatter:i}}=(0,u.Vi)(),{content:a,groups:o,defaultGroupTitle:s="Others"}=e,[l,d]=(0,p.useState)(""),h=(0,p.useRef)(null);(0,p.useEffect)(()=>{h.current?.focus()},[]);let x=e=>(0,u.pJ)(e).startsWith(n.replace(/overview$/,""))&&!(0,u.pV)((0,u.pJ)(e),n),m=e=>"link"in e&&e.link?e.link:"items"in e?m(e.items[0]):"",{pages:g}=t,f=g.filter(e=>x(e.routePath)),v=t2(),{overview:{filterNameText:y="Filter",filterPlaceholderText:b="Enter keyword",filterNoResultText:w="No matching API found"}={}}=tL();function k(t,r,i){if(t9(t)||(0,u.pJ)(t.link)===`${n}index`&&i?.overview===!0)return!1;let a=e?.overviewHeaders??t.overviewHeaders??i?.overviewHeaders??r?.overviewHeaders??[2],o=f.find(e=>(0,u.pV)(e.routePath,(0,u.pJ)(t.link||""))),s=m(t);return{...t,link:s,headers:o?.toc?.filter(e=>a.some(t=>e.depth===t))||[]}}v[0]?.link!==n&&(v=function e(t,n){let r,i=t.findIndex(e=>(function(e){if(t9(e))return!1;let t=(0,u.pJ)(e.link),r=t.endsWith("/index")?t.slice(0,-5):t,i=n.replace(/\/$/,"");return t===n||r===n||t===i||r===i})(e));if(-1===i)return t.map(t=>"items"in t?e(t.items,n):[]).flat();let a=t[i];if("items"in a&&Array.isArray(r=a.items)&&r.length>=1)return a.items.every(e=>!("items"in e))?[a]:a.items.filter(e=>!t9(e));let o=[...t];return"items"in a||o.splice(i,1),o.filter(e=>!t9(e))}(v,n));let I=o??(0,p.useMemo)(()=>v.filter(e=>Array.isArray(e?.items)?e.items.filter(e=>x(m(e))).length>0:!!(ne(e)&&x(m(e)))).map(e=>{let t=[];return e?.items?t=e?.items?.map(t=>k(t,e,i)).filter(Boolean):ne(e)&&(t=[k({link:e.link,text:e.text||"",tag:e.tag,_fileKey:e._fileKey,overviewHeaders:e.overviewHeaders},void 0,i)]),{name:e.text||"",items:t}}),[v,n,i]),D=(0,p.useMemo)(()=>l?I.map(e=>{if(rY(e.name,l))return e;let t=e.items.map(e=>{if(rY(e.text||"",l))return e;let t=e.headers?.filter(({text:e})=>rY(e,l));return t?.length?{...e,headers:t}:null}).filter(Boolean);return t.length?{...e,items:t}:null}).filter(Boolean):I,[I,l]);return(0,c.jsxs)("div",{className:"overview-index mx-auto",children:[(0,c.jsxs)("div",{className:"flex flex-col sm:flex-row items-start sm:items-center justify-between mb-10",children:[(0,c.jsx)("h1",{className:"text-3xl leading-10 tracking-tight",children:r||"Overview"}),(0,c.jsx)(rX,{query:l,setQuery:d,searchRef:h,filterNameText:y,filterPlaceholderText:b})]}),a,D.length>0?D.map(e=>(0,c.jsx)(r1,{group:e,styles:rJ},e?.name)):(0,c.jsx)("div",{className:"text-lg text-gray-500 text-center mt-9 pt-9 border-t border-gray-200 dark:border-gray-800",children:`${w}: ${l}`})]})}function r2(e){return(0,c.jsxs)("svg",{id:"Bun",width:"1.2em",height:"1.2em",viewBox:"0 0 80 70",...e,children:[(0,c.jsx)("path",{id:"Shadow",d:"M71.09,20.74c-.16-.17-.33-.34-.5-.5s-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5A26.46,26.46,0,0,1,75.5,35.7c0,16.57-16.82,30.05-37.5,30.05-11.58,0-21.94-4.23-28.83-10.86l.5.5.5.5.5.5.5.5.5.5.5.5.5.5C19.55,65.3,30.14,69.75,42,69.75c20.68,0,37.5-13.48,37.5-30C79.5,32.69,76.46,26,71.09,20.74Z"}),(0,c.jsxs)("g",{id:"Body",children:[(0,c.jsx)("path",{id:"Background",d:"M73,35.7c0,15.21-15.67,27.54-35,27.54S3,50.91,3,35.7C3,26.27,9,17.94,18.22,13S33.18,3,38,3s8.94,4.13,19.78,10C67,17.94,73,26.27,73,35.7Z",style:{fill:"#fbf0df"}}),(0,c.jsx)("path",{id:"Bottom_Shadow","data-name":"Bottom Shadow",d:"M73,35.7a21.67,21.67,0,0,0-.8-5.78c-2.73,33.3-43.35,34.9-59.32,24.94A40,40,0,0,0,38,63.24C57.3,63.24,73,50.89,73,35.7Z",style:{fill:"#f6dece"}}),(0,c.jsx)("path",{id:"Light_Shine","data-name":"Light Shine",d:"M24.53,11.17C29,8.49,34.94,3.46,40.78,3.45A9.29,9.29,0,0,0,38,3c-2.42,0-5,1.25-8.25,3.13-1.13.66-2.3,1.39-3.54,2.15-2.33,1.44-5,3.07-8,4.7C8.69,18.13,3,26.62,3,35.7c0,.4,0,.8,0,1.19C9.06,15.48,20.07,13.85,24.53,11.17Z",style:{fill:"#fffefc"}}),(0,c.jsx)("path",{id:"Top",d:"M35.12,5.53A16.41,16.41,0,0,1,29.49,18c-.28.25-.06.73.3.59,3.37-1.31,7.92-5.23,6-13.14C35.71,5,35.12,5.12,35.12,5.53Zm2.27,0A16.24,16.24,0,0,1,39,19c-.12.35.31.65.55.36C41.74,16.56,43.65,11,37.93,5,37.64,4.74,37.19,5.14,37.39,5.49Zm2.76-.17A16.42,16.42,0,0,1,47,17.12a.33.33,0,0,0,.65.11c.92-3.49.4-9.44-7.17-12.53C40.08,4.54,39.82,5.08,40.15,5.32ZM21.69,15.76a16.94,16.94,0,0,0,10.47-9c.18-.36.75-.22.66.18-1.73,8-7.52,9.67-11.12,9.45C21.32,16.4,21.33,15.87,21.69,15.76Z",style:{fill:"#ccbea7",fillRule:"evenodd"}}),(0,c.jsx)("path",{id:"Outline",d:"M38,65.75C17.32,65.75.5,52.27.5,35.7c0-10,6.18-19.33,16.53-24.92,3-1.6,5.57-3.21,7.86-4.62,1.26-.78,2.45-1.51,3.6-2.19C32,1.89,35,.5,38,.5s5.62,1.2,8.9,3.14c1,.57,2,1.19,3.07,1.87,2.49,1.54,5.3,3.28,9,5.27C69.32,16.37,75.5,25.69,75.5,35.7,75.5,52.27,58.68,65.75,38,65.75ZM38,3c-2.42,0-5,1.25-8.25,3.13-1.13.66-2.3,1.39-3.54,2.15-2.33,1.44-5,3.07-8,4.7C8.69,18.13,3,26.62,3,35.7,3,50.89,18.7,63.25,38,63.25S73,50.89,73,35.7C73,26.62,67.31,18.13,57.78,13,54,11,51.05,9.12,48.66,7.64c-1.09-.67-2.09-1.29-3-1.84C42.63,4,40.42,3,38,3Z"})]}),(0,c.jsxs)("g",{id:"Mouth",children:[(0,c.jsx)("g",{id:"Background-2","data-name":"Background",children:(0,c.jsx)("path",{d:"M45.05,43a8.93,8.93,0,0,1-2.92,4.71,6.81,6.81,0,0,1-4,1.88A6.84,6.84,0,0,1,34,47.71,8.93,8.93,0,0,1,31.12,43a.72.72,0,0,1,.8-.81H44.26A.72.72,0,0,1,45.05,43Z",style:{fill:"#b71422"}})}),(0,c.jsxs)("g",{id:"Tongue",children:[(0,c.jsx)("path",{id:"Background-3","data-name":"Background",d:"M34,47.79a6.91,6.91,0,0,0,4.12,1.9,6.91,6.91,0,0,0,4.11-1.9,10.63,10.63,0,0,0,1-1.07,6.83,6.83,0,0,0-4.9-2.31,6.15,6.15,0,0,0-5,2.78C33.56,47.4,33.76,47.6,34,47.79Z",style:{fill:"#ff6164"}}),(0,c.jsx)("path",{id:"Outline-2","data-name":"Outline",d:"M34.16,47a5.36,5.36,0,0,1,4.19-2.08,6,6,0,0,1,4,1.69c.23-.25.45-.51.66-.77a7,7,0,0,0-4.71-1.93,6.36,6.36,0,0,0-4.89,2.36A9.53,9.53,0,0,0,34.16,47Z"})]}),(0,c.jsx)("path",{id:"Outline-3","data-name":"Outline",d:"M38.09,50.19a7.42,7.42,0,0,1-4.45-2,9.52,9.52,0,0,1-3.11-5.05,1.2,1.2,0,0,1,.26-1,1.41,1.41,0,0,1,1.13-.51H44.26a1.44,1.44,0,0,1,1.13.51,1.19,1.19,0,0,1,.25,1h0a9.52,9.52,0,0,1-3.11,5.05A7.42,7.42,0,0,1,38.09,50.19Zm-6.17-7.4c-.16,0-.2.07-.21.09a8.29,8.29,0,0,0,2.73,4.37A6.23,6.23,0,0,0,38.09,49a6.28,6.28,0,0,0,3.65-1.73,8.3,8.3,0,0,0,2.72-4.37.21.21,0,0,0-.2-.09Z"})]}),(0,c.jsxs)("g",{id:"Face",children:[(0,c.jsx)("ellipse",{id:"Right_Blush","data-name":"Right Blush",cx:"53.22",cy:"40.18",rx:"5.85",ry:"3.44",style:{fill:"#febbd0"}}),(0,c.jsx)("ellipse",{id:"Left_Bluch","data-name":"Left Bluch",cx:"22.95",cy:"40.18",rx:"5.85",ry:"3.44",style:{fill:"#febbd0"}}),(0,c.jsx)("path",{id:"Eyes",d:"M25.7,38.8a5.51,5.51,0,1,0-5.5-5.51A5.51,5.51,0,0,0,25.7,38.8Zm24.77,0A5.51,5.51,0,1,0,45,33.29,5.5,5.5,0,0,0,50.47,38.8Z",style:{fillRule:"evenodd"}}),(0,c.jsx)("path",{id:"Iris",d:"M24,33.64a2.07,2.07,0,1,0-2.06-2.07A2.07,2.07,0,0,0,24,33.64Zm24.77,0a2.07,2.07,0,1,0-2.06-2.07A2.07,2.07,0,0,0,48.75,33.64Z",style:{fill:"#fff",fillRule:"evenodd"}})]})]})}function r3(e){return(0,c.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"1em",height:"1em",viewBox:"0 0 256 256",...e,children:[(0,c.jsx)("path",{fill:"#C12127",d:"M0 256V0h256v256z"}),(0,c.jsx)("path",{fill:"#FFF",d:"M48 48h160v160h-32V80h-48v128H48z"})]})}function r4(e){return(0,c.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"1em",height:"1em",viewBox:"0 0 128 128",...e,children:[(0,c.jsx)("path",{fill:"#f8ab00",d:"M0 .004V40h39.996V.004Zm43.996 0V40h40V.004Zm44.008 0V40H128V.004Zm0 43.996v39.996H128V44Z"}),(0,c.jsx)("path",{fill:"#4c4c4c",d:"M43.996 44v39.996h40V44ZM0 87.996v40h39.996v-40Zm43.996 0v40h40v-40Zm44.008 0v40H128v-40Z"})]})}function r5(e){return(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"1em",height:"1em",viewBox:"0 0 128 128",...e,children:(0,c.jsxs)("g",{fill:"#2c8ebb",children:[(0,c.jsx)("path",{d:"M99.24 80.71C94.9 80.76 91.1 83 87.89 85c-6 3.71-9 3.47-9 3.47l-.1-.17c-.41-.67 1.92-6.68-.69-13.84c-2.82-7.83-7.3-9.72-6.94-10.32c1.53-2.59 5.36-6.7 6.89-14.36c.91-4.64.67-12.28-1.39-16.28c-.38-.74-3.78 1.24-3.78 1.24s-3.18-7.09-4.07-7.66c-2.87-1.84-6 7.61-6 7.61a14 14 0 0 0-11.71 4.5a9.64 9.64 0 0 1-3.85 2.27c-.41.14-.91.12-2.15 3.47c-1.9 5.07 3.24 10.81 3.24 10.81s-6.13 4.33-8.4 9.72a24.78 24.78 0 0 0-1.75 11.68s-4.36 3.78-4.64 7.68a12.87 12.87 0 0 0 1.77 7.83a1.94 1.94 0 0 0 2.63.91s-2.9 3.38-.19 4.81c2.47 1.29 6.63 2 8.83-.19c1.6-1.6 1.92-5.17 2.51-6.63c.14-.34.62.57 1.08 1a10 10 0 0 0 1.36 1s-3.9 1.68-2.3 5.51c.53 1.27 2.42 2.08 5.51 2.06c1.15 0 13.76-.72 17.12-1.53a4.33 4.33 0 0 0 2.61-1.46a63 63 0 0 0 15.49-7c4.74-3.09 6.68-3.93 10.51-4.84c3.16-.75 2.95-5.65-1.24-5.58z"}),(0,c.jsx)("path",{d:"M64 2a62 62 0 1 0 62 62A62 62 0 0 0 64 2zm37.3 87.83c-3.35.81-4.91 1.44-9.41 4.36a67 67 0 0 1-15.56 7.18a8.71 8.71 0 0 1-3.64 1.77c-3.81.93-16.88 1.63-17.91 1.63h-.24c-4 0-6.27-1.24-7.49-2.54c-3.4 1.7-7.8 1-11-.69a5.55 5.55 0 0 1-3-3.9a6 6 0 0 1 0-2.06a6.66 6.66 0 0 1-.79-1A16.38 16.38 0 0 1 30 84.52c.29-3.73 2.87-7.06 4.55-8.83A28.56 28.56 0 0 1 36.61 64a26.82 26.82 0 0 1 6.82-9c-1.65-2.78-3.33-7.06-1.7-11.42c1.17-3.11 2.13-4.84 4.24-5.58a6.84 6.84 0 0 0 2.51-1.34A17.65 17.65 0 0 1 60.34 31c.19-.48.41-1 .65-1.46c1.6-3.4 3.3-5.31 5.29-6a4.88 4.88 0 0 1 4.4.5c.65.43 1.48 1 3.9 6a4.69 4.69 0 0 1 2.85-.1a3.81 3.81 0 0 1 2.39 1.94c2.47 4.74 2.8 13.19 1.72 18.62a33.8 33.8 0 0 1-5.84 13.31a25.73 25.73 0 0 1 5.77 9.43a25.42 25.42 0 0 1 1.41 10.41A28.7 28.7 0 0 0 86 81.91c3.06-1.89 7.68-4.74 13.19-4.81a6.62 6.62 0 0 1 7 5.7a6.35 6.35 0 0 1-4.89 7.03z"})]})})}function r6(e){if(e.startsWith("yarn create"))return e.replace(/(yarn create [^\s]+)@latest/,"$1");if(!e?.includes("install"))return e;let t=e.split(" ").filter(e=>!e.startsWith("-")&&!e.startsWith("--")).join(" ");return"yarn install"===t||"bun install"===t?e:e.replace("install","add")}function r7({command:e,additionalTabs:t=[]}){let n,r={npm:(0,c.jsx)(r3,{}),yarn:(0,c.jsx)(r5,{}),pnpm:(0,c.jsx)(r4,{}),bun:(0,c.jsx)(r2,{})};return t.forEach(e=>{r[e.tool]=e.icon}),"string"==typeof e?(n={npm:`npm ${e}`,yarn:`yarn ${e}`,pnpm:`pnpm ${e}`,bun:`bun ${e}`},t.forEach(t=>{n[t.tool]=`${t.tool} ${e}`})):n=e,n.yarn&&(n.yarn=r6(n.yarn)),n.bun&&(n.bun=r6(n.bun)),(0,c.jsx)(ia,{groupId:"package.manager",values:Object.entries(n).map(([e])=>(0,c.jsxs)("div",{style:{display:"flex",alignItems:"center",fontSize:15},children:[r[e],(0,c.jsx)("span",{style:{marginLeft:6,marginBottom:2},children:e})]},e)),children:Object.entries(n).map(([e,t])=>(0,c.jsx)(io,{children:(0,c.jsx)(nV,{children:(0,c.jsx)(nq,{className:"language-js",codeHighlighter:"prism",children:t})})},e))})}let r8={pagerLink:"pager-link_e0d2d",title:"title_a3acb",next:"next_ad355",desc:"desc_dcc01"};function r9(e){let{type:t,text:n,href:r}=e,{prevPageText:i="Previous Page",nextPageText:a="Next Page"}=tL(),o="prev"===t?r8.pagerLink:`${r8.pagerLink} ${r8.next}`;return(0,c.jsxs)(nm,{href:r,className:o,children:[(0,c.jsx)("span",{className:r8.desc,children:"prev"===t?i:a}),(0,c.jsx)("span",{className:r8.title,children:n})]})}let ie={scrollToTop:"scroll-to-top_e22be",entered:"entered_c8faf"};function it(){let[e,t]=(0,p.useState)(!1),n=()=>{t((window.scrollY||document.documentElement.scrollTop)>0)};return(0,p.useEffect)(()=>{window.addEventListener("scroll",n)},[]),(0,c.jsx)("button",{className:`${ie.scrollToTop} ${e?ie.entered:""}`,onClick:()=>{window.scrollTo({top:0,behavior:"smooth"})},children:(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",className:"w-6 h-6",children:(0,c.jsx)("path",{fillRule:"evenodd",d:"M11.47 2.47a.75.75 0 0 1 1.06 0l7.5 7.5a.75.75 0 1 1-1.06 1.06l-6.22-6.22V21a.75.75 0 0 1-1.5 0V4.81l-6.22 6.22a.75.75 0 1 1-1.06-1.06l7.5-7.5Z",clipRule:"evenodd"})})})}let ir={container:"container_df5ed",tabList:"tab-list_ccbcc",tab:"tab_cae68",notSelected:"not-selected_dab7a",selected:"selected_f5c1e",noScrollbar:"no-scrollbar_db61f"},ii=e=>e&&"object"==typeof e&&"label"in e?e.label||e.value:e,ia=(0,p.forwardRef)((e,t)=>{let{values:n,defaultValue:r,onChange:i,children:a,groupId:o,tabPosition:s="left",tabContainerClassName:l}=e,d=p.Children.toArray(a).filter(e=>"string"!=typeof e||""!==e.trim()),u=n||[];0===u.length&&(u=p.Children.map(d,e=>(0,p.isValidElement)(e)?{label:e.props?.label,value:e.props?.value||e.props?.label}:{label:void 0,value:void 0}));let{tabData:h,setTabData:x}=(0,p.useContext)(ny),[m,g]=(0,p.useState)(()=>void 0===r?0:u.findIndex(e=>"string"==typeof e?e===r:!!e&&"object"==typeof e&&"value"in e&&e.value===r)),[f,v]=rs(`rspress.tabs.${o}`,m.toString()),y=(0,p.useMemo)(()=>o?void 0!==h[o]?h[o]:Number.parseInt(f):m,[o&&h[o]]);(0,p.useEffect)(()=>{if(o){let e=Number.parseInt(f);y!==e&&x({...h,[o]:e})}},[f]);let b=o?y:m;return(0,c.jsxs)("div",{className:ir.container,ref:t,children:[(0,c.jsx)("div",{className:l,children:u.length?(0,c.jsx)("div",{className:`${ir.tabList} ${ir.noScrollbar}`,style:{justifyContent:"center"===s?"center":"flex-start"},children:u.map((e,t)=>(0,c.jsx)("div",{className:`${ir.tab} ${b===t?ir.selected:ir.notSelected}`,onClick:()=>{i?.(t),o?(x({...h,[o]:t}),v(t.toString())):g(t)},children:ii(e)},t))}):null}),(0,c.jsx)("div",{children:p.Children.toArray(d)[b]})]})});function io({children:e,...t}){return(0,c.jsx)("div",{...t,className:"rounded px-2",children:e})}function is({query:e}){let{searchNoResultsText:t="No results for",searchSuggestedQueryText:n="Please try again with a different keyword"}=tL();return(0,c.jsxs)("div",{className:"flex flex-col items-center pt-8 pb-2",children:[(0,c.jsx)(t7,{icon:tO,className:"mb-4 opacity-80"}),(0,c.jsxs)("p",{className:"mb-2",children:[t," ",(0,c.jsxs)("b",{children:['"',e,'"']})]}),(0,c.jsx)("p",{children:n})]})}let il={mask:"mask_ac6b3",modal:"modal_e4a04",inputForm:"inputForm_d4ba2",input:"input_f8add",close:"close_bee84",searchHits:"searchHits_dc1b2",groupTitle:"groupTitle_fe27c",navSearchButton:"navSearchButton_df1fb",searchWord:"searchWord_af2c1",suggestItem:"suggestItem_b1e66",suggestItemContainer:"suggestItemContainer_f5e47",contentWrapper:"contentWrapper_efb78",mark:"mark_b6cd5",titleForContent:"titleForContent_f2995",actionIcon:"actionIcon_f4ffd",current:"current_eb655",tabClassName:"tabClassName_b3f85",mobileNavSearchButton:"mobileNavSearchButton_d85a9"},ic={title:e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M4 4a2 2 0 0 1 2-2h8a1 1 0 0 1 .707.293l5 5A1 1 0 0 1 20 8v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2zm13.586 4L14 4.414V8zM12 4H6v16h12V10h-5a1 1 0 0 1-1-1z"})}),header:e=>(0,c.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 32 32",...e,children:(0,c.jsx)("path",{fill:"currentColor",d:"M28 12v-2h-6V4h-2v6h-8V4h-2v6H4v2h6v8H4v2h6v6h2v-6h8v6h2v-6h6v-2h-6v-8Zm-8 8h-8v-8h8Z"})}),content:e=>(0,c.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 32 32",...e,children:[(0,c.jsx)("circle",{cx:22,cy:24,r:2,fill:"currentColor"}),(0,c.jsx)("path",{fill:"none",d:"M22 28a4 4 0 1 1 4-4 4.004 4.004 0 0 1-4 4m0-6a2 2 0 1 0 2 2 2.003 2.003 0 0 0-2-2"}),(0,c.jsx)("path",{fill:"currentColor",d:"M29.777 23.479A8.64 8.64 0 0 0 22 18a8.64 8.64 0 0 0-7.777 5.479L14 24l.223.521A8.64 8.64 0 0 0 22 30a8.64 8.64 0 0 0 7.777-5.479L30 24ZM22 28a4 4 0 1 1 4-4 4.005 4.005 0 0 1-4 4"}),(0,c.jsx)("path",{fill:"currentColor",d:"M12 28H8V4h8v6a2.006 2.006 0 0 0 2 2h6v4h2v-6a.91.91 0 0 0-.3-.7l-7-7A.9.9 0 0 0 18 2H8a2.006 2.006 0 0 0-2 2v24a2.006 2.006 0 0 0 2 2h4Zm6-23.6 5.6 5.6H18Z"})]})};function id({suggestion:e,closeSearch:t,isCurrent:n,setCurrentSuggestionIndex:r,inCurrentDocIndex:i,scrollTo:a,onMouseMove:o}){let s=ic[e.type],l=i&&!(0,u.yv)()?n3(e.link):e.link,d=(0,p.useRef)(null);n&&d.current?.offsetTop&&a(d.current?.offsetTop,d.current?.offsetHeight);let h=(e,t)=>{let n=[],r=0;for(let i of t){let{start:t,length:a}=i,o=e.slice(r,t),s=function(e,t,n){var r=e.slice(t);let i="",a=0,o=r.length;for(let e=0;e0+n);e++)a>0&&(i+=r.charAt(e));return i}(e,t,a);n.push(o),n.push((0,c.jsx)("span",{className:il.mark,children:s},t)),r=t+s.length}return r{if("header"===e.type||"title"===e.type){let{header:t,highlightInfoList:n}=e;return(0,c.jsx)("div",{className:"font-medium",children:h(t,n)})}return(0,c.jsx)("div",{className:"font-medium",children:e.header})})();break;case"content":x=(0,c.jsxs)(c.Fragment,{children:[(()=>{if("content"!==e.type)return(0,c.jsx)("div",{});let{statement:t,highlightInfoList:n}=e;return(0,c.jsx)("div",{className:"text-sm text-gray-light w-full",children:h(t,n)})})(),(0,c.jsx)("p",{className:il.titleForContent,children:e.title})]})}return(0,c.jsx)("li",{className:`rspress-search-suggest-item ${il.suggestItem} ${n?il.current:""}`,onMouseEnter:r,onMouseMove:o,ref:d,children:(0,c.jsx)("a",{href:l,onClick:e=>{t(),e.stopPropagation()},target:i?"_self":"_blank",children:(0,c.jsxs)("div",{className:il.suggestItemContainer,children:[(0,c.jsx)("div",{className:il.hitIcon,children:(0,c.jsx)(t7,{icon:s})}),(0,c.jsx)("div",{className:il.contentWrapper,children:(0,c.jsx)("span",{children:x})}),(0,c.jsx)("div",{className:il.actionIcon,children:(0,c.jsx)(t7,{icon:tR})})]})})},e.link)}let iu={ARROW_UP:"ArrowUp",ARROW_DOWN:"ArrowDown",ENTER:"Enter",SEARCH:"KeyK",ESC:"Escape"},ih=e=>{let t=(0,p.useRef)(e);return t.current=e,(0,p.useCallback)(z((...e)=>t.current(...e),150),[])};function ip({focused:e,setFocused:t}){let[n,r]=(0,p.useState)(""),[i,a]=(0,p.useState)([]),o=(0,p.useRef)(null),[s,d]=(0,p.useState)(!1),[h,m]=(0,p.useState)(0),[g,f]=(0,p.useState)(0),v=(0,p.useRef)(null),y=(0,p.useRef)(null),[b,w]=(0,p.useState)("initial"),k=(0,p.useRef)(null),I=(0,p.useRef)(null),D=(0,p.useRef)({pageX:null,pageY:null}),[E,F]=(0,p.useState)(!1),A=(e,t)=>{let n=k.current?.offsetHeight,r=k.current?.scrollTop;if(E&&void 0!==n&&void 0!==r){let a=e+t-n-(1===i.length?50:-10);a>r&&k.current?.scrollTo({top:a});let o=1===i.length?e-70:e-10;o{if(v.current)return v.current;let e={currentLang:j,currentVersion:P};return v.current=new ri({indexName:N,...T,...e}),y.current=e,v.current};async function L(){if("initial"!==b)return;let e=q();w("initing"),await e.init(),w("inited");let t=o.current?.value;t&&(a(await e.match(t)||B),d(!1))}let M=()=>{t(!1),m(0),f(0)};(0,p.useEffect)(()=>{let n=n=>{switch(n.code){case iu.SEARCH:(n.ctrlKey||n.metaKey)&&(n.preventDefault(),t(!e));break;case iu.ARROW_DOWN:if(n.isComposing)return;e&&(n.preventDefault(),O&&R===rr.Default&&(F(!0),f((g+1)%O.length)));break;case iu.ARROW_UP:if(n.isComposing)return;if(e&&(n.preventDefault(),R===rr.Default)){let e=O.length;F(!0),f((g-1+e)%e)}break;case iu.ENTER:if(n.isComposing)return;if(g>=0&&R===rr.Default){let e=[...Object.values(H(O))].flat()[g];0===h?window.location.href=(0,x.yv)()?e.link:n3(e.link):window.open(e.link),M()}break;case iu.ESC:M()}};return document.addEventListener("keydown",n),()=>{document.removeEventListener("keydown",n)}},[f,t,e,h,O,g]),(0,p.useEffect)(()=>{e?(a(B),L()):r("")},[e]),(0,p.useEffect)(()=>{"requestIdleCallback"in window&&!v.current&&window.requestIdleCallback(()=>{q().fetchSearchIndex()})},[]),(0,p.useEffect)(()=>{let{currentLang:e,currentVersion:t}=y.current??{},n=_&&P!==t;(j!==e||n)&&(w("initial"),v.current=null,q().fetchSearchIndex())},[j,P,_]);let z=ih(async e=>{let t=e;if(r(t),T&&"remote"===T.mode&&T.searchLoading&&d(!0),t){let e=[];if("beforeSearch"in l){let e=await l.beforeSearch(t);e&&(t=e)}let n=await v.current?.match(t);if(n&&e.push(...n),"onSearch"in l){let n=await l.onSearch(t,e);n&&e.push(...n.map(e=>({renderType:rr.Custom,...e})))}"afterSearch"in l&&await l.afterSearch(t,e),o.current?.value===t&&(a(e||B),d(!1))}}),H=e=>e.reduce((e,t)=>{let n=t.title;return e[n]||(e[n]=[]),e[n].push(t),e},{}),$=(e,t,n)=>{if(n)return(0,c.jsx)("div",{className:"flex flex-col items-center",children:(0,c.jsx)(t7,{icon:t_,className:"m-8 opacity-80"})});if(0===e.length&&"inited"===b)return(0,c.jsx)(is,{query:t});let r=H(e),i=-1;return(0,c.jsx)("ul",{className:il.suggestList,children:Object.keys(r).map(e=>{let t=r[e]||[];return(0,c.jsx)("li",{children:(0,c.jsx)("ul",{className:"pb-2",children:t.map(e=>{let t=++i;return(0,c.jsx)(id,{suggestion:e,isCurrent:t===g,setCurrentSuggestionIndex:e=>{(D.current.pageX!==e.pageX||D.current.pageY!==e.pageY)&&(F(!1),f(t))},onMouseMove:e=>{D.current={pageX:e.pageX,pageY:e.pageY}},closeSearch:()=>{M()},inCurrentDocIndex:0===h,scrollTo:A},`${e.title}-${t}`)})})},e)})})};return(0,c.jsx)(c.Fragment,{children:e&&(0,tP.createPortal)((0,c.jsx)("div",{className:il.mask,onClick:()=>{M()},children:(0,c.jsxs)("div",{className:`${il.modal}`,onClick:e=>{t(!0),e.stopPropagation()},children:[(0,c.jsxs)("div",{className:"flex items-center",children:[(0,c.jsxs)("div",{className:il.inputForm,children:[(0,c.jsx)("label",{children:(0,c.jsx)(t7,{icon:tT})}),(0,c.jsx)("input",{className:`rspress-search-panel-input ${il.input}`,ref:o,placeholder:S,"aria-label":"SearchPanelInput",autoComplete:"off",autoFocus:!0,onChange:e=>z(e.target.value)}),(0,c.jsx)("label",{children:(0,c.jsx)(t7,{icon:tN,className:il.close,onClick:e=>{o.current&&(e.stopPropagation(),n?(o.current.value="",r("")):M())}})})]}),(0,c.jsx)("h2",{className:"text-brand ml-2 sm:hidden cursor-pointer",onClick:e=>{e.stopPropagation(),M()},children:"Cancel"})]}),n&&"inited"===b?(0,c.jsx)("div",{className:`${il.searchHits} rspress-scrollbar`,ref:k,children:((e,t,r)=>{if(1===e.length){let t=e[0].result;return 0!==t.length||r?(0,c.jsx)("div",{ref:I,children:$(t,n,r)}):(0,c.jsx)(is,{query:n})}let i=e.map(e=>t&&"remote"===t.mode?n5(t.searchIndexes||[]).find(t=>t.value===e.group).label:e.group);return(0,c.jsx)(ia,{values:i,tabContainerClassName:il.tabClassName,onChange:e=>{m(e),f(0)},ref:I,children:e.map(e=>(0,c.jsxs)(io,{children:[e.renderType===rr.Default&&$(e.result,n,r),e.renderType===rr.Custom&&l.render(e.result)]},e.group))})})(i,T,s)}):null]})}),document.getElementById("search-container"))})}function ix(){let[e,t]=(0,p.useState)(!1),[n,r]=(0,p.useState)(null),{searchPlaceholderText:i="Search Docs"}=tL();return(0,p.useEffect)(()=>{r(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?"⌘":"Ctrl")},[]),(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)("div",{className:`rspress-nav-search-button ${il.navSearchButton}`,onClick:()=>t(!0),children:(0,c.jsxs)("button",{children:[(0,c.jsx)(t7,{icon:tT,width:"18",height:"18"}),(0,c.jsx)("p",{className:il.searchWord,children:i}),(0,c.jsxs)("div",{style:{opacity:+!!n},children:[(0,c.jsx)("span",{children:n}),(0,c.jsx)("span",{children:"K"})]})]})}),(0,c.jsx)("div",{className:il.mobileNavSearchButton,onClick:()=>t(!0),children:(0,c.jsx)(t7,{icon:tT})}),(0,c.jsx)(ip,{focused:e,setFocused:t})]})}let im=({tag:e})=>e?e.trim().startsWith("{let{top:t,bottom:n,beforeDocFooter:r,afterDocFooter:i,beforeDoc:a,afterDoc:o,beforeDocContent:s,afterDocContent:l,beforeSidebar:d,afterSidebar:h,beforeOutline:x,afterOutline:m,beforeNavTitle:g,afterNavTitle:f,navTitle:v,beforeNav:y,beforeHero:b,afterHero:w,beforeFeatures:k,afterFeatures:I,afterNavMenu:D,components:E}=e,F={beforeDocFooter:r,afterDocFooter:i,beforeDocContent:s,afterDocContent:l,beforeDoc:a,afterDoc:o,beforeSidebar:d,afterSidebar:h,beforeOutline:x,afterOutline:m,components:E},A={beforeHero:b,afterHero:w,beforeFeatures:k,afterFeatures:I},{siteData:C,page:j}=(0,u.Vi)(),{pageType:P,lang:S,title:T,frontmatter:N={}}=j,_=tL();tW();let{siteData:B,page:O}=(0,u.Vi)(),R=B.lang||"",q=Object.values(B.themeConfig.locales||{}).map(e=>e.lang)||[],L=O.lang;(0,p.useEffect)(()=>{let e,t=B.themeConfig.localeRedirect??"auto";if("never"===t||!R||/bot|spider|crawl|lighthouse/i.test(window.navigator.userAgent))return;let{pathname:n,search:r}=window.location,i=(0,u.E9)(n),a="rspress-visited";if(localStorage.getItem(a))return;localStorage.setItem(a,"1");let o=window.navigator.language.split("-")[0];q.includes(o)&&o!==L&&(o===R?e=n.replace(`/${L}`,""):L===R?e=(0,u.pJ)(`/${o}${i}`):"auto"===t&&(e=n.replace(`/${L}`,`/${o}`)),e&&window.location.replace(e+r))},[]);let M=N.title??T,z=C.title||_.title||"";M=M&&"doc"===P?nP(M,N.titleSuffix||z):"home"===P?nP(z,N.titleSuffix):"404"===P?nP("404",z):z;let H=N?.description||C.description||_.description,$={...tM(),...e.uiSwitch};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)(V.ql,{htmlAttributes:{lang:S||"en"},children:[M?(0,c.jsx)("title",{children:M}):null,H?(0,c.jsx)("meta",{name:"description",content:H}):null]}),t,"blank"!==P&&$.showNavbar&&(0,c.jsx)(rZ,{beforeNavTitle:g,afterNavTitle:f,navTitle:v,beforeNav:y,afterNavMenu:D}),(0,c.jsx)("section",{children:(()=>{switch(P){case"home":return(0,c.jsx)(ig.HomeLayout,{...A});case"doc":return(0,c.jsx)(nj,{...F,uiSwitch:$,navTitle:v});case"404":return(0,c.jsx)(ig.NotFoundLayout,{});case"custom":case"blank":return(0,c.jsx)(u.VY,{});default:return(0,c.jsx)(nj,{...F})}})()}),n]})},NotFoundLayout:nS,HomeLayout:function(e){let{beforeHero:t,afterHero:n,beforeFeatures:r,afterFeatures:i}=e,{page:{frontmatter:a,routePath:o}}=(0,u.Vi)();return(0,c.jsxs)("div",{className:"relative",style:{minHeight:"calc(100vh - var(--rp-nav-height))",paddingBottom:"80px"},children:[(0,c.jsxs)("div",{className:"pb-12",children:[t,(0,c.jsx)(rb,{frontmatter:a,routePath:o}),n,r,(0,c.jsx)(rf,{frontmatter:a,routePath:o}),i]}),(0,c.jsx)(rv,{})]})},useBindingAsideScroll:t$,useSetup:tW}},7854:function(e){"use strict";e.exports=JSON.parse('{"AElig":"\xc6","AMP":"&","Aacute":"\xc1","Acirc":"\xc2","Agrave":"\xc0","Aring":"\xc5","Atilde":"\xc3","Auml":"\xc4","COPY":"\xa9","Ccedil":"\xc7","ETH":"\xd0","Eacute":"\xc9","Ecirc":"\xca","Egrave":"\xc8","Euml":"\xcb","GT":">","Iacute":"\xcd","Icirc":"\xce","Igrave":"\xcc","Iuml":"\xcf","LT":"<","Ntilde":"\xd1","Oacute":"\xd3","Ocirc":"\xd4","Ograve":"\xd2","Oslash":"\xd8","Otilde":"\xd5","Ouml":"\xd6","QUOT":"\\"","REG":"\xae","THORN":"\xde","Uacute":"\xda","Ucirc":"\xdb","Ugrave":"\xd9","Uuml":"\xdc","Yacute":"\xdd","aacute":"\xe1","acirc":"\xe2","acute":"\xb4","aelig":"\xe6","agrave":"\xe0","amp":"&","aring":"\xe5","atilde":"\xe3","auml":"\xe4","brvbar":"\xa6","ccedil":"\xe7","cedil":"\xb8","cent":"\xa2","copy":"\xa9","curren":"\xa4","deg":"\xb0","divide":"\xf7","eacute":"\xe9","ecirc":"\xea","egrave":"\xe8","eth":"\xf0","euml":"\xeb","frac12":"\xbd","frac14":"\xbc","frac34":"\xbe","gt":">","iacute":"\xed","icirc":"\xee","iexcl":"\xa1","igrave":"\xec","iquest":"\xbf","iuml":"\xef","laquo":"\xab","lt":"<","macr":"\xaf","micro":"\xb5","middot":"\xb7","nbsp":"\xa0","not":"\xac","ntilde":"\xf1","oacute":"\xf3","ocirc":"\xf4","ograve":"\xf2","ordf":"\xaa","ordm":"\xba","oslash":"\xf8","otilde":"\xf5","ouml":"\xf6","para":"\xb6","plusmn":"\xb1","pound":"\xa3","quot":"\\"","raquo":"\xbb","reg":"\xae","sect":"\xa7","shy":"\xad","sup1":"\xb9","sup2":"\xb2","sup3":"\xb3","szlig":"\xdf","thorn":"\xfe","times":"\xd7","uacute":"\xfa","ucirc":"\xfb","ugrave":"\xf9","uml":"\xa8","uuml":"\xfc","yacute":"\xfd","yen":"\xa5","yuml":"\xff"}')},1636:function(e){"use strict";e.exports=JSON.parse('{"0":"οΏ½","128":"€","130":"β€š","131":"Ζ’","132":"β€ž","133":"…","134":"†","135":"‑","136":"Λ†","137":"‰","138":"Ε ","139":"β€Ή","140":"Ε’","142":"Ε½","145":"β€˜","146":"’","147":"β€œ","148":"”","149":"β€’","150":"–","151":"β€”","152":"˜","153":"β„’","154":"Ε‘","155":"β€Ί","156":"Ε“","158":"ΕΎ","159":"ΕΈ"}')}}]); \ No newline at end of file diff --git a/static/js/async/1020.21bafcda.js b/static/js/async/1020.21bafcda.js new file mode 100644 index 00000000..0750e637 --- /dev/null +++ b/static/js/async/1020.21bafcda.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["1020"],{5637:function(e,n,s){s.r(n),s.d(n,{default:()=>c});var i=s(5893),t=s(65);function r(e){let n=Object.assign({h1:"h1",a:"a",h2:"h2",p:"p",strong:"strong",code:"code",pre:"pre",h3:"h3",ul:"ul",li:"li",div:"div"},(0,t.ah)(),e.components);return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.h1,{id:"user-event-interactions",children:["User Event interactions",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#user-event-interactions",children:"#"})]}),"\n",(0,i.jsxs)(n.h2,{id:"comparison-with-fire-event-api",children:["Comparison with Fire Event API",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#comparison-with-fire-event-api",children:"#"})]}),"\n",(0,i.jsxs)(n.p,{children:["Fire Event is our original event simulation API. It can invoke ",(0,i.jsx)(n.strong,{children:"any event handler"})," declared on ",(0,i.jsx)(n.strong,{children:"either host or composite elements"}),". Suppose the element does not have ",(0,i.jsx)(n.code,{children:"onEventName"})," event handler for the passed ",(0,i.jsx)(n.code,{children:"eventName"})," event, or the element is disabled. In that case, Fire Event will traverse up the component tree, looking for an event handler on both host and composite elements along the way. By default, it will ",(0,i.jsx)(n.strong,{children:"not pass any event data"}),", but the user might provide it in the last argument."]}),"\n",(0,i.jsxs)(n.p,{children:["In contrast, User Event provides realistic event simulation for user interactions like ",(0,i.jsx)(n.code,{children:"press"})," or ",(0,i.jsx)(n.code,{children:"type"}),". Each interaction will trigger a ",(0,i.jsx)(n.strong,{children:"sequence of events"})," corresponding to React Native runtime behavior. These events will be invoked ",(0,i.jsx)(n.strong,{children:"only on host elements"}),", and ",(0,i.jsx)(n.strong,{children:"will automatically receive event data"})," corresponding to each event."]}),"\n",(0,i.jsx)(n.p,{children:"If User Event supports a given interaction, you should always prefer it over the Fire Event counterpart, as it will make your tests much more realistic and, hence, reliable. In other cases, e.g., when User Event does not support the given event or when invoking event handlers on composite elements, you have to use Fire Event as the only available option."}),"\n",(0,i.jsxs)(n.h2,{id:"setup",children:[(0,i.jsx)(n.code,{children:"setup()"}),(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#setup",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"userEvent.setup(options?: {\n delay?: number;\n advanceTimers?: (delay: number) => Promise | void;\n})\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"const user = userEvent.setup();\n"})}),"\n",(0,i.jsx)(n.p,{children:"Creates a User Event object instance, which can be used to trigger events."}),"\n",(0,i.jsxs)(n.h3,{id:"setup-options",children:["Options",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#setup-options",children:"#"})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"delay"})," controls the default delay between subsequent events, e.g., keystrokes."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"advanceTimers"})," is a time advancement utility function that should be used for fake timers. The default setup handles both real timers and Jest fake timers."]}),"\n"]}),"\n",(0,i.jsxs)(n.h2,{id:"press",children:[(0,i.jsx)(n.code,{children:"press()"}),(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#press",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"press(\n element: HostElement,\n): Promise\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"const user = userEvent.setup();\nawait user.press(element);\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This helper simulates a press on any pressable element, e.g. ",(0,i.jsx)(n.code,{children:"Pressable"}),", ",(0,i.jsx)(n.code,{children:"TouchableOpacity"}),", ",(0,i.jsx)(n.code,{children:"Text"}),", ",(0,i.jsx)(n.code,{children:"TextInput"}),", etc. Unlike ",(0,i.jsx)(n.code,{children:"fireEvent.press()"}),", a more straightforward API that will only call the ",(0,i.jsx)(n.code,{children:"onPress"})," prop, this function simulates the entire press interaction in a more realistic way by reproducing the event sequence emitted by React Native runtime. This helper will trigger additional events like ",(0,i.jsx)(n.code,{children:"pressIn"})," and ",(0,i.jsx)(n.code,{children:"pressOut"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This event will take a minimum of 130 ms to run due to the internal React Native logic. Consider using fake timers to speed up test execution for tests involving ",(0,i.jsx)(n.code,{children:"press"})," and ",(0,i.jsx)(n.code,{children:"longPress"})," interactions."]}),"\n",(0,i.jsxs)(n.h2,{id:"longpress",children:[(0,i.jsx)(n.code,{children:"longPress()"}),(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#longpress",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"longPress(\n element: HostElement,\n options?: { duration?: number }\n): Promise\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"const user = userEvent.setup();\nawait user.longPress(element);\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Simulates a long press user interaction. In React Native, the ",(0,i.jsx)(n.code,{children:"longPress"})," event is emitted when the press duration exceeds the long press threshold (by default, 500 ms). In other aspects, this action behaves similarly to regular ",(0,i.jsx)(n.code,{children:"press"})," action, e.g., by emitting ",(0,i.jsx)(n.code,{children:"pressIn"})," and ",(0,i.jsx)(n.code,{children:"pressOut"})," events. The press duration is customizable through the options. This should be useful if you use the ",(0,i.jsx)(n.code,{children:"delayLongPress"})," prop."]}),"\n",(0,i.jsxs)(n.p,{children:["This event will, by default, take 500 ms to run. Due to internal React Native logic, it will take at least 130 ms regardless of the duration option passed. Consider using fake timers to speed up test execution for tests involving ",(0,i.jsx)(n.code,{children:"press"})," and ",(0,i.jsx)(n.code,{children:"longPress"})," interactions."]}),"\n",(0,i.jsxs)(n.h3,{id:"longpress-options",children:["Options",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#longpress-options",children:"#"})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"duration"})," - duration of the press in milliseconds. The default value is 500 ms."]}),"\n"]}),"\n",(0,i.jsxs)(n.h2,{id:"type",children:[(0,i.jsx)(n.code,{children:"type()"}),(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#type",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"type(\n element: HostElement,\n text: string,\n options?: {\n skipPress?: boolean;\n skipBlur?: boolean;\n submitEditing?: boolean;\n }\n): Promise\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"const user = userEvent.setup();\nawait user.type(textInput, 'Hello world!');\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This helper simulates the user focusing on a ",(0,i.jsx)(n.code,{children:"TextInput"})," element, typing ",(0,i.jsx)(n.code,{children:"text"})," one character at a time, and leaving the element."]}),"\n",(0,i.jsxs)(n.p,{children:["This function supports only host ",(0,i.jsx)(n.code,{children:"TextInput"})," elements. Passing other element types will result in throwing an error."]}),"\n",(0,i.jsxs)(n.div,{className:"rspress-directive note",children:[(0,i.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,i.jsx)(n.div,{className:"rspress-directive-content",children:(0,i.jsxs)(n.p,{children:["This function will add text to the text already present in the text input (as specified by ",(0,i.jsx)(n.code,{children:"value"})," or ",(0,i.jsx)(n.code,{children:"defaultValue"})," props). To replace existing text, use ",(0,i.jsx)(n.a,{href:"#clear",children:(0,i.jsx)(n.code,{children:"clear()"})})," helper first.\n"]})})]}),"\n",(0,i.jsxs)(n.h3,{id:"type-options",children:["Options",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#type-options",children:"#"})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"skipPress"})," - if true, ",(0,i.jsx)(n.code,{children:"pressIn"})," and ",(0,i.jsx)(n.code,{children:"pressOut"})," events will not be triggered."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"skipBlur"})," - if true, ",(0,i.jsx)(n.code,{children:"endEditing"})," and ",(0,i.jsx)(n.code,{children:"blur"})," events will not be triggered when typing is complete."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"submitEditing"})," - if true, ",(0,i.jsx)(n.code,{children:"submitEditing"})," event will be triggered after typing the text."]}),"\n"]}),"\n",(0,i.jsxs)(n.h3,{id:"type-sequence",children:["Sequence of events",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#type-sequence",children:"#"})]}),"\n",(0,i.jsxs)(n.p,{children:["The sequence of events depends on the ",(0,i.jsx)(n.code,{children:"multiline"})," prop and the passed options."]}),"\n",(0,i.jsxs)(n.p,{children:["Events will not be emitted if the ",(0,i.jsx)(n.code,{children:"editable"})," prop is set to ",(0,i.jsx)(n.code,{children:"false"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Entering the element"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"pressIn"})," (optional)"]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"focus"})}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"pressOut"})," (optional)"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"pressIn"})," and ",(0,i.jsx)(n.code,{children:"pressOut"})," events are sent by default but can be skipped by passing the ",(0,i.jsx)(n.code,{children:"skipPress: true"})," option."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Typing (for each character)"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"keyPress"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"change"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"changeText"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"selectionChange"})}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"contentSizeChange"})," (only multiline)"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Leaving the element"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"submitEditing"})," (optional)"]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"endEditing"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"blur"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"submitEditing"})," event is skipped by default. It can sent by setting the ",(0,i.jsx)(n.code,{children:"submitEditing: true"})," option.\nThe ",(0,i.jsx)(n.code,{children:"endEditing"})," and ",(0,i.jsx)(n.code,{children:"blur"})," events can be skipped by passing the ",(0,i.jsx)(n.code,{children:"skipBlur: true"})," option."]}),"\n",(0,i.jsxs)(n.h2,{id:"clear",children:[(0,i.jsx)(n.code,{children:"clear()"}),(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#clear",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"clear(\n element: HostElement,\n): Promise\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"const user = userEvent.setup();\nawait user.clear(textInput);\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This helper simulates the user clearing the content of a ",(0,i.jsx)(n.code,{children:"TextInput"})," element."]}),"\n",(0,i.jsxs)(n.p,{children:["This function supports only host ",(0,i.jsx)(n.code,{children:"TextInput"})," elements. Passing other element types will result in throwing an error."]}),"\n",(0,i.jsxs)(n.h3,{id:"clear-sequence",children:["Sequence of events",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#clear-sequence",children:"#"})]}),"\n",(0,i.jsxs)(n.p,{children:["Events will not be emitted if the ",(0,i.jsx)(n.code,{children:"editable"})," prop is set to ",(0,i.jsx)(n.code,{children:"false"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Entering the element"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"focus"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Selecting all content"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"selectionChange"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Pressing backspace"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"keyPress"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"change"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"changeText"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"selectionChange"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Leaving the element"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"endEditing"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"blur"})}),"\n"]}),"\n",(0,i.jsxs)(n.h2,{id:"paste",children:[(0,i.jsx)(n.code,{children:"paste()"}),(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#paste",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"paste(\n element: HostElement,\n text: string,\n): Promise\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"const user = userEvent.setup();\nawait user.paste(textInput, 'Text to paste');\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This helper simulates the user pasting given text to a ",(0,i.jsx)(n.code,{children:"TextInput"})," element."]}),"\n",(0,i.jsxs)(n.p,{children:["This function supports only host ",(0,i.jsx)(n.code,{children:"TextInput"})," elements. Passing other element types will result in throwing an error."]}),"\n",(0,i.jsxs)(n.h3,{id:"paste-sequence",children:["Sequence of events",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#paste-sequence",children:"#"})]}),"\n",(0,i.jsxs)(n.p,{children:["Events will not be emitted if the ",(0,i.jsx)(n.code,{children:"editable"})," prop is set to ",(0,i.jsx)(n.code,{children:"false"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Entering the element"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"focus"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Selecting all content"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"selectionChange"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Pasting the text"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"change"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"changeText"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"selectionChange"})}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"contentSizeChange"})," (only multiline)"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Leaving the element"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"endEditing"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"blur"})}),"\n"]}),"\n",(0,i.jsxs)(n.h2,{id:"scroll-to",children:[(0,i.jsx)(n.code,{children:"scrollTo()"}),(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#scroll-to",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"scrollTo(\n element: HostElement,\n options: {\n y: number;\n momentumY?: number;\n contentSize?: { width: number; height: number };\n layoutMeasurement?: { width: number; height: number };\n } | {\n x: number;\n momentumX?: number;\n contentSize?: { width: number; height: number };\n layoutMeasurement?: { width: number; height: number };\n }\n): Promise\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"const user = userEvent.setup();\nawait user.scrollTo(scrollView, { y: 100, momentumY: 200 });\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This helper simulates the user scrolling a host ",(0,i.jsx)(n.code,{children:"ScrollView"})," element."]}),"\n",(0,i.jsxs)(n.p,{children:["This function supports only host ",(0,i.jsx)(n.code,{children:"ScrollView"})," elements, passing other element types will result in an error. Note that ",(0,i.jsx)(n.code,{children:"FlatList"})," is accepted as it renders to a host ",(0,i.jsx)(n.code,{children:"ScrollView"})," element."]}),"\n",(0,i.jsxs)(n.p,{children:["Scroll interaction should match the ",(0,i.jsx)(n.code,{children:"ScrollView"})," element direction:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["for a vertical scroll view (default or ",(0,i.jsx)(n.code,{children:"horizontal={false}"}),"), you should pass only the ",(0,i.jsx)(n.code,{children:"y"})," option (and optionally also ",(0,i.jsx)(n.code,{children:"momentumY"}),")."]}),"\n",(0,i.jsxs)(n.li,{children:["for a horizontal scroll view (",(0,i.jsx)(n.code,{children:"horizontal={true}"}),"), you should pass only the ",(0,i.jsx)(n.code,{children:"x"})," option (and optionally ",(0,i.jsx)(n.code,{children:"momentumX"}),")."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Each scroll interaction consists of a mandatory drag scroll part, which simulates the user dragging the scroll view with his finger (the ",(0,i.jsx)(n.code,{children:"y"})," or ",(0,i.jsx)(n.code,{children:"x"})," option). This may optionally be followed by a momentum scroll movement, which simulates the inertial movement of scroll view content after the user lifts his finger (",(0,i.jsx)(n.code,{children:"momentumY"})," or ",(0,i.jsx)(n.code,{children:"momentumX"})," options)."]}),"\n",(0,i.jsxs)(n.h3,{id:"scroll-to-options",children:["Options",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#scroll-to-options",children:"#"})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"y"})," - target vertical drag scroll offset"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"x"})," - target horizontal drag scroll offset"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"momentumY"})," - target vertical momentum scroll offset"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"momentumX"})," - target horizontal momentum scroll offset"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"contentSize"})," - passed to ",(0,i.jsx)(n.code,{children:"ScrollView"})," events and enabling ",(0,i.jsx)(n.code,{children:"FlatList"})," updates"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"layoutMeasurement"})," - passed to ",(0,i.jsx)(n.code,{children:"ScrollView"})," events and enabling ",(0,i.jsx)(n.code,{children:"FlatList"})," updates"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"User Event will generate several intermediate scroll steps to simulate user scroll interaction. You should not rely on exact number or values of these scrolls steps as they might be change in the future version."}),"\n",(0,i.jsxs)(n.p,{children:["This function will remember where the last scroll ended, so subsequent scroll interaction will starts from that position. The initial scroll position will be assumed to be ",(0,i.jsx)(n.code,{children:"{ y: 0, x: 0 }"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["To simulate a ",(0,i.jsx)(n.code,{children:"FlatList"})," (and other controls based on ",(0,i.jsx)(n.code,{children:"VirtualizedList"}),") scrolling, you should pass the ",(0,i.jsx)(n.code,{children:"contentSize"})," and ",(0,i.jsx)(n.code,{children:"layoutMeasurement"})," options, which enable the underlying logic to update the currently visible window."]}),"\n",(0,i.jsxs)(n.h3,{id:"scroll-sequence",children:["Sequence of events",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#scroll-sequence",children:"#"})]}),"\n",(0,i.jsx)(n.p,{children:"The sequence of events depends on whether the scroll includes an optional momentum scroll component."}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Drag scroll"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"contentSizeChange"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"scrollBeginDrag"})}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"scroll"})," (multiple events)"]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"scrollEndDrag"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Momentum scroll (optional)"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"momentumScrollBegin"})}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"scroll"})," (multiple events)"]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"momentumScrollEnd"})}),"\n"]})]})}function l(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,t.ah)(),e.components);return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(r,{...e})}):r(e)}let c=l;l.__RSPRESS_PAGE_META={},l.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fapi%2Fevents%2Fuser-event.mdx"]={toc:[{text:"Comparison with Fire Event API",id:"comparison-with-fire-event-api",depth:2},{text:"`setup()`",id:"setup",depth:2},{text:"Options",id:"setup-options",depth:3},{text:"`press()`",id:"press",depth:2},{text:"`longPress()`",id:"longpress",depth:2},{text:"Options",id:"longpress-options",depth:3},{text:"`type()`",id:"type",depth:2},{text:"Options",id:"type-options",depth:3},{text:"Sequence of events",id:"type-sequence",depth:3},{text:"`clear()`",id:"clear",depth:2},{text:"Sequence of events",id:"clear-sequence",depth:3},{text:"`paste()`",id:"paste",depth:2},{text:"Sequence of events",id:"paste-sequence",depth:3},{text:"`scrollTo()`",id:"scroll-to",depth:2},{text:"Options",id:"scroll-to-options",depth:3},{text:"Sequence of events",id:"scroll-sequence",depth:3}],title:"User Event interactions",headingTitle:"User Event interactions",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/1020.73a20fe8.js b/static/js/async/1020.73a20fe8.js deleted file mode 100644 index 3013347e..00000000 --- a/static/js/async/1020.73a20fe8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["1020"],{5637:function(e,n,s){s.r(n),s.d(n,{default:()=>c});var i=s(5893),t=s(65);function r(e){let n=Object.assign({h1:"h1",a:"a",h2:"h2",p:"p",strong:"strong",code:"code",pre:"pre",h3:"h3",ul:"ul",li:"li",div:"div"},(0,t.ah)(),e.components);return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.h1,{id:"user-event-interactions",children:["User Event interactions",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#user-event-interactions",children:"#"})]}),"\n",(0,i.jsxs)(n.h2,{id:"comparison-with-fire-event-api",children:["Comparison with Fire Event API",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#comparison-with-fire-event-api",children:"#"})]}),"\n",(0,i.jsxs)(n.p,{children:["Fire Event is our original event simulation API. It can invoke ",(0,i.jsx)(n.strong,{children:"any event handler"})," declared on ",(0,i.jsx)(n.strong,{children:"either host or composite elements"}),". Suppose the element does not have ",(0,i.jsx)(n.code,{children:"onEventName"})," event handler for the passed ",(0,i.jsx)(n.code,{children:"eventName"})," event, or the element is disabled. In that case, Fire Event will traverse up the component tree, looking for an event handler on both host and composite elements along the way. By default, it will ",(0,i.jsx)(n.strong,{children:"not pass any event data"}),", but the user might provide it in the last argument."]}),"\n",(0,i.jsxs)(n.p,{children:["In contrast, User Event provides realistic event simulation for user interactions like ",(0,i.jsx)(n.code,{children:"press"})," or ",(0,i.jsx)(n.code,{children:"type"}),". Each interaction will trigger a ",(0,i.jsx)(n.strong,{children:"sequence of events"})," corresponding to React Native runtime behavior. These events will be invoked ",(0,i.jsx)(n.strong,{children:"only on host elements"}),", and ",(0,i.jsx)(n.strong,{children:"will automatically receive event data"})," corresponding to each event."]}),"\n",(0,i.jsx)(n.p,{children:"If User Event supports a given interaction, you should always prefer it over the Fire Event counterpart, as it will make your tests much more realistic and, hence, reliable. In other cases, e.g., when User Event does not support the given event or when invoking event handlers on composite elements, you have to use Fire Event as the only available option."}),"\n",(0,i.jsxs)(n.h2,{id:"setup",children:[(0,i.jsx)(n.code,{children:"setup()"}),(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#setup",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"userEvent.setup(options?: {\n delay: number;\n advanceTimers: (delay: number) => Promise | void;\n})\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"const user = userEvent.setup();\n"})}),"\n",(0,i.jsx)(n.p,{children:"Creates a User Event object instance, which can be used to trigger events."}),"\n",(0,i.jsxs)(n.h3,{id:"setup-options",children:["Options",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#setup-options",children:"#"})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"delay"})," controls the default delay between subsequent events, e.g., keystrokes."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"advanceTimers"})," is a time advancement utility function that should be used for fake timers. The default setup handles both real timers and Jest fake timers."]}),"\n"]}),"\n",(0,i.jsxs)(n.h2,{id:"press",children:[(0,i.jsx)(n.code,{children:"press()"}),(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#press",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"press(\n element: HostElement,\n): Promise\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"const user = userEvent.setup();\nawait user.press(element);\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This helper simulates a press on any pressable element, e.g. ",(0,i.jsx)(n.code,{children:"Pressable"}),", ",(0,i.jsx)(n.code,{children:"TouchableOpacity"}),", ",(0,i.jsx)(n.code,{children:"Text"}),", ",(0,i.jsx)(n.code,{children:"TextInput"}),", etc. Unlike ",(0,i.jsx)(n.code,{children:"fireEvent.press()"}),", a more straightforward API that will only call the ",(0,i.jsx)(n.code,{children:"onPress"})," prop, this function simulates the entire press interaction in a more realistic way by reproducing the event sequence emitted by React Native runtime. This helper will trigger additional events like ",(0,i.jsx)(n.code,{children:"pressIn"})," and ",(0,i.jsx)(n.code,{children:"pressOut"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This event will take a minimum of 130 ms to run due to the internal React Native logic. Consider using fake timers to speed up test execution for tests involving ",(0,i.jsx)(n.code,{children:"press"})," and ",(0,i.jsx)(n.code,{children:"longPress"})," interactions."]}),"\n",(0,i.jsxs)(n.h2,{id:"longpress",children:[(0,i.jsx)(n.code,{children:"longPress()"}),(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#longpress",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"longPress(\n element: HostElement,\n options: { duration: number } = { duration: 500 }\n): Promise\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"const user = userEvent.setup();\nawait user.longPress(element);\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Simulates a long press user interaction. In React Native, the ",(0,i.jsx)(n.code,{children:"longPress"})," event is emitted when the press duration exceeds the long press threshold (by default, 500 ms). In other aspects, this action behaves similarly to regular ",(0,i.jsx)(n.code,{children:"press"})," action, e.g., by emitting ",(0,i.jsx)(n.code,{children:"pressIn"})," and ",(0,i.jsx)(n.code,{children:"pressOut"})," events. The press duration is customizable through the options. This should be useful if you use the ",(0,i.jsx)(n.code,{children:"delayLongPress"})," prop."]}),"\n",(0,i.jsxs)(n.p,{children:["This event will, by default, take 500 ms to run. Due to internal React Native logic, it will take at least 130 ms regardless of the duration option passed. Consider using fake timers to speed up test execution for tests involving ",(0,i.jsx)(n.code,{children:"press"})," and ",(0,i.jsx)(n.code,{children:"longPress"})," interactions."]}),"\n",(0,i.jsxs)(n.h3,{id:"longpress-options",children:["Options",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#longpress-options",children:"#"})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"duration"})," - duration of the press in milliseconds. The default value is 500 ms."]}),"\n"]}),"\n",(0,i.jsxs)(n.h2,{id:"type",children:[(0,i.jsx)(n.code,{children:"type()"}),(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#type",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"type(\n element: HostElement,\n text: string,\n options?: {\n skipPress?: boolean;\n skipBlur?: boolean;\n submitEditing?: boolean;\n }\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"const user = userEvent.setup();\nawait user.type(textInput, 'Hello world!');\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This helper simulates the user focusing on a ",(0,i.jsx)(n.code,{children:"TextInput"})," element, typing ",(0,i.jsx)(n.code,{children:"text"})," one character at a time, and leaving the element."]}),"\n",(0,i.jsxs)(n.p,{children:["This function supports only host ",(0,i.jsx)(n.code,{children:"TextInput"})," elements. Passing other element types will result in throwing an error."]}),"\n",(0,i.jsxs)(n.div,{className:"rspress-directive note",children:[(0,i.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,i.jsx)(n.div,{className:"rspress-directive-content",children:(0,i.jsxs)(n.p,{children:["This function will add text to the text already present in the text input (as specified by ",(0,i.jsx)(n.code,{children:"value"})," or ",(0,i.jsx)(n.code,{children:"defaultValue"})," props). To replace existing text, use ",(0,i.jsx)(n.a,{href:"#clear",children:(0,i.jsx)(n.code,{children:"clear()"})})," helper first.\n"]})})]}),"\n",(0,i.jsxs)(n.h3,{id:"type-options",children:["Options",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#type-options",children:"#"})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"skipPress"})," - if true, ",(0,i.jsx)(n.code,{children:"pressIn"})," and ",(0,i.jsx)(n.code,{children:"pressOut"})," events will not be triggered."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"skipBlur"})," - if true, ",(0,i.jsx)(n.code,{children:"endEditing"})," and ",(0,i.jsx)(n.code,{children:"blur"})," events will not be triggered when typing is complete."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"submitEditing"})," - if true, ",(0,i.jsx)(n.code,{children:"submitEditing"})," event will be triggered after typing the text."]}),"\n"]}),"\n",(0,i.jsxs)(n.h3,{id:"type-sequence",children:["Sequence of events",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#type-sequence",children:"#"})]}),"\n",(0,i.jsxs)(n.p,{children:["The sequence of events depends on the ",(0,i.jsx)(n.code,{children:"multiline"})," prop and the passed options."]}),"\n",(0,i.jsxs)(n.p,{children:["Events will not be emitted if the ",(0,i.jsx)(n.code,{children:"editable"})," prop is set to ",(0,i.jsx)(n.code,{children:"false"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Entering the element"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"pressIn"})," (optional)"]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"focus"})}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"pressOut"})," (optional)"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"pressIn"})," and ",(0,i.jsx)(n.code,{children:"pressOut"})," events are sent by default but can be skipped by passing the ",(0,i.jsx)(n.code,{children:"skipPress: true"})," option."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Typing (for each character)"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"keyPress"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"change"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"changeText"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"selectionChange"})}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"contentSizeChange"})," (only multiline)"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Leaving the element"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"submitEditing"})," (optional)"]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"endEditing"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"blur"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"submitEditing"})," event is skipped by default. It can sent by setting the ",(0,i.jsx)(n.code,{children:"submitEditing: true"})," option.\nThe ",(0,i.jsx)(n.code,{children:"endEditing"})," and ",(0,i.jsx)(n.code,{children:"blur"})," events can be skipped by passing the ",(0,i.jsx)(n.code,{children:"skipBlur: true"})," option."]}),"\n",(0,i.jsxs)(n.h2,{id:"clear",children:[(0,i.jsx)(n.code,{children:"clear()"}),(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#clear",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"clear(\n element: HostElement,\n)\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"const user = userEvent.setup();\nawait user.clear(textInput);\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This helper simulates the user clearing the content of a ",(0,i.jsx)(n.code,{children:"TextInput"})," element."]}),"\n",(0,i.jsxs)(n.p,{children:["This function supports only host ",(0,i.jsx)(n.code,{children:"TextInput"})," elements. Passing other element types will result in throwing an error."]}),"\n",(0,i.jsxs)(n.h3,{id:"clear-sequence",children:["Sequence of events",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#clear-sequence",children:"#"})]}),"\n",(0,i.jsxs)(n.p,{children:["Events will not be emitted if the ",(0,i.jsx)(n.code,{children:"editable"})," prop is set to ",(0,i.jsx)(n.code,{children:"false"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Entering the element"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"focus"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Selecting all content"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"selectionChange"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Pressing backspace"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"keyPress"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"change"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"changeText"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"selectionChange"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Leaving the element"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"endEditing"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"blur"})}),"\n"]}),"\n",(0,i.jsxs)(n.h2,{id:"paste",children:[(0,i.jsx)(n.code,{children:"paste()"}),(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#paste",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"paste(\n element: HostElement,\n text: string,\n)\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"const user = userEvent.setup();\nawait user.paste(textInput, 'Text to paste');\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This helper simulates the user pasting given text to a ",(0,i.jsx)(n.code,{children:"TextInput"})," element."]}),"\n",(0,i.jsxs)(n.p,{children:["This function supports only host ",(0,i.jsx)(n.code,{children:"TextInput"})," elements. Passing other element types will result in throwing an error."]}),"\n",(0,i.jsxs)(n.h3,{id:"paste-sequence",children:["Sequence of events",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#paste-sequence",children:"#"})]}),"\n",(0,i.jsxs)(n.p,{children:["Events will not be emitted if the ",(0,i.jsx)(n.code,{children:"editable"})," prop is set to ",(0,i.jsx)(n.code,{children:"false"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Entering the element"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"focus"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Selecting all content"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"selectionChange"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Pasting the text"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"change"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"changeText"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"selectionChange"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Leaving the element"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"endEditing"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"blur"})}),"\n"]}),"\n",(0,i.jsxs)(n.h2,{id:"scroll-to",children:[(0,i.jsx)(n.code,{children:"scrollTo()"}),(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#scroll-to",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"scrollTo(\n element: HostElement,\n options: {\n y: number,\n momentumY?: number,\n contentSize?: { width: number, height: number },\n layoutMeasurement?: { width: number, height: number },\n } | {\n x: number,\n momentumX?: number,\n contentSize?: { width: number, height: number },\n layoutMeasurement?: { width: number, height: number },\n }\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"const user = userEvent.setup();\nawait user.scrollTo(scrollView, { y: 100, momentumY: 200 });\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This helper simulates the user scrolling a host ",(0,i.jsx)(n.code,{children:"ScrollView"})," element."]}),"\n",(0,i.jsxs)(n.p,{children:["This function supports only host ",(0,i.jsx)(n.code,{children:"ScrollView"})," elements, passing other element types will result in an error. Note that ",(0,i.jsx)(n.code,{children:"FlatList"})," is accepted as it renders to a host ",(0,i.jsx)(n.code,{children:"ScrollView"})," element."]}),"\n",(0,i.jsxs)(n.p,{children:["Scroll interaction should match the ",(0,i.jsx)(n.code,{children:"ScrollView"})," element direction:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["for a vertical scroll view (default or ",(0,i.jsx)(n.code,{children:"horizontal={false}"}),"), you should pass only the ",(0,i.jsx)(n.code,{children:"y"})," option (and optionally also ",(0,i.jsx)(n.code,{children:"momentumY"}),")."]}),"\n",(0,i.jsxs)(n.li,{children:["for a horizontal scroll view (",(0,i.jsx)(n.code,{children:"horizontal={true}"}),"), you should pass only the ",(0,i.jsx)(n.code,{children:"x"})," option (and optionally ",(0,i.jsx)(n.code,{children:"momentumX"}),")."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Each scroll interaction consists of a mandatory drag scroll part, which simulates the user dragging the scroll view with his finger (the ",(0,i.jsx)(n.code,{children:"y"})," or ",(0,i.jsx)(n.code,{children:"x"})," option). This may optionally be followed by a momentum scroll movement, which simulates the inertial movement of scroll view content after the user lifts his finger (",(0,i.jsx)(n.code,{children:"momentumY"})," or ",(0,i.jsx)(n.code,{children:"momentumX"})," options)."]}),"\n",(0,i.jsxs)(n.h3,{id:"scroll-to-options",children:["Options",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#scroll-to-options",children:"#"})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"y"})," - target vertical drag scroll offset"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"x"})," - target horizontal drag scroll offset"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"momentumY"})," - target vertical momentum scroll offset"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"momentumX"})," - target horizontal momentum scroll offset"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"contentSize"})," - passed to ",(0,i.jsx)(n.code,{children:"ScrollView"})," events and enabling ",(0,i.jsx)(n.code,{children:"FlatList"})," updates"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"layoutMeasurement"})," - passed to ",(0,i.jsx)(n.code,{children:"ScrollView"})," events and enabling ",(0,i.jsx)(n.code,{children:"FlatList"})," updates"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"User Event will generate several intermediate scroll steps to simulate user scroll interaction. You should not rely on exact number or values of these scrolls steps as they might be change in the future version."}),"\n",(0,i.jsxs)(n.p,{children:["This function will remember where the last scroll ended, so subsequent scroll interaction will starts from that position. The initial scroll position will be assumed to be ",(0,i.jsx)(n.code,{children:"{ y: 0, x: 0 }"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["To simulate a ",(0,i.jsx)(n.code,{children:"FlatList"})," (and other controls based on ",(0,i.jsx)(n.code,{children:"VirtualizedList"}),") scrolling, you should pass the ",(0,i.jsx)(n.code,{children:"contentSize"})," and ",(0,i.jsx)(n.code,{children:"layoutMeasurement"})," options, which enable the underlying logic to update the currently visible window."]}),"\n",(0,i.jsxs)(n.h3,{id:"scroll-sequence",children:["Sequence of events",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#scroll-sequence",children:"#"})]}),"\n",(0,i.jsx)(n.p,{children:"The sequence of events depends on whether the scroll includes an optional momentum scroll component."}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Drag scroll"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"contentSizeChange"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"scrollBeginDrag"})}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"scroll"})," (multiple events)"]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"scrollEndDrag"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Momentum scroll (optional)"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"momentumScrollBegin"})}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"scroll"})," (multiple events)"]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"momentumScrollEnd"})}),"\n"]})]})}function l(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,t.ah)(),e.components);return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(r,{...e})}):r(e)}let c=l;l.__RSPRESS_PAGE_META={},l.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fapi%2Fevents%2Fuser-event.mdx"]={toc:[{text:"Comparison with Fire Event API",id:"comparison-with-fire-event-api",depth:2},{text:"`setup()`",id:"setup",depth:2},{text:"Options",id:"setup-options",depth:3},{text:"`press()`",id:"press",depth:2},{text:"`longPress()`",id:"longpress",depth:2},{text:"Options",id:"longpress-options",depth:3},{text:"`type()`",id:"type",depth:2},{text:"Options",id:"type-options",depth:3},{text:"Sequence of events",id:"type-sequence",depth:3},{text:"`clear()`",id:"clear",depth:2},{text:"Sequence of events",id:"clear-sequence",depth:3},{text:"`paste()`",id:"paste",depth:2},{text:"Sequence of events",id:"paste-sequence",depth:3},{text:"`scrollTo()`",id:"scroll-to",depth:2},{text:"Options",id:"scroll-to-options",depth:3},{text:"Sequence of events",id:"scroll-sequence",depth:3}],title:"User Event interactions",headingTitle:"User Event interactions",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/1290.46b49369.js b/static/js/async/1290.0ea47608.js similarity index 56% rename from static/js/async/1290.46b49369.js rename to static/js/async/1290.0ea47608.js index 2b6171bb..8cb64ede 100644 --- a/static/js/async/1290.46b49369.js +++ b/static/js/async/1290.0ea47608.js @@ -1 +1 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["1290"],{6147:function(e,t,n){n.r(t),n.d(t,{default:()=>o});var s=n(5893),r=n(65);function a(e){let t=Object.assign({h1:"h1",a:"a",h2:"h2",p:"p",div:"div",code:"code",pre:"pre",ul:"ul",li:"li"},(0,r.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(t.h1,{id:"network-requests",children:["Network Requests",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#network-requests",children:"#"})]}),"\n",(0,s.jsxs)(t.h2,{id:"introduction",children:["Introduction",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#introduction",children:"#"})]}),"\n",(0,s.jsx)(t.p,{children:"Mocking network requests is an essential part of testing React Native applications. By mocking\nnetwork\nrequests, you can control the data that is returned from the server and test how your application\nbehaves in different scenarios, such as when the request is successful or when it fails."}),"\n",(0,s.jsx)(t.p,{children:"In this guide, we will show you how to mock network requests and guard your test suits from unwanted\nand unmocked/unhandled network requests"}),"\n",(0,s.jsxs)(t.div,{className:"rspress-directive info",children:[(0,s.jsx)(t.div,{className:"rspress-directive-title",children:"INFO"}),(0,s.jsx)(t.div,{className:"rspress-directive-content",children:(0,s.jsxs)(t.p,{children:["To simulate a real-world scenario, we will use the ",(0,s.jsx)(t.a,{href:"https://randomuser.me/",target:"_blank",rel:"noopener noreferrer",children:"Random User Generator API"})," that provides random user data.\n"]})})]}),"\n",(0,s.jsxs)(t.h2,{id:"phonebook-example",children:["Phonebook Example",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#phonebook-example",children:"#"})]}),"\n",(0,s.jsxs)(t.p,{children:["Let's assume we have a simple phonebook application that\nuses ",(0,s.jsx)(t.a,{href:"https://reactnative.dev/docs/network#using-fetch",target:"_blank",rel:"noopener noreferrer",children:(0,s.jsx)(t.code,{children:"fetch"})})," for fetching Data from a server.\nIn our case, we have a list of contacts and favorites that we want to display in our application."]}),"\n",(0,s.jsx)(t.p,{children:"This is how the root of the application looks like:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=network-requests/Phonebook.tsx",children:"import React, { useEffect, useState } from 'react';\nimport { Text } from 'react-native';\nimport { User } from './types';\nimport ContactsList from './components/ContactsList';\nimport FavoritesList from './components/FavoritesList';\nimport getAllContacts from './api/getAllContacts';\nimport getAllFavorites from './api/getAllFavorites';\n\nexport default () => {\n const [usersData, setUsersData] = useState([]);\n const [favoritesData, setFavoritesData] = useState([]);\n const [error, setError] = useState(null);\n\n useEffect(() => {\n const _getAllContacts = async () => {\n const _data = await getAllContacts();\n setUsersData(_data);\n };\n const _getAllFavorites = async () => {\n const _data = await getAllFavorites();\n setFavoritesData(_data);\n };\n\n const run = async () => {\n try {\n await Promise.all([_getAllContacts(), _getAllFavorites()]);\n } catch (e) {\n const message = isErrorWithMessage(e) ? e.message : 'Something went wrong';\n setError(message);\n }\n };\n\n void run();\n }, []);\n\n if (error) {\n return An error occurred: {error};\n }\n\n return (\n <>\n \n \n \n );\n};\n"})}),"\n",(0,s.jsxs)(t.p,{children:["We fetch the contacts from the server using the ",(0,s.jsx)(t.code,{children:"getAllFavorites"})," function that utilizes ",(0,s.jsx)(t.code,{children:"fetch"}),"."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=network-requests/api/getAllContacts.ts",children:"import { User } from '../types';\n\nexport default async (): Promise => {\n const res = await fetch('https://randomuser.me/api/?results=25');\n if (!res.ok) {\n throw new Error(`Error fetching contacts`);\n }\n const json = await res.json();\n return json.results;\n};\n"})}),"\n",(0,s.jsx)(t.p,{children:"We have similar function for fetching the favorites, but this time limiting the results to 10."}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=network-requests/api/getAllFavorites.ts",children:"import { User } from '../types';\n\nexport default async (): Promise => {\n const res = await fetch('https://randomuser.me/api/?results=10');\n if (!res.ok) {\n throw new Error(`Error fetching favorites`);\n }\n const json = await res.json();\n return json.results;\n};\n"})}),"\n",(0,s.jsxs)(t.p,{children:["Our ",(0,s.jsx)(t.code,{children:"FavoritesList"})," component is a simple component that displays the list of favorite contacts and\ntheir avatars horizontally."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=network-requests/components/FavoritesList.tsx",children:"import {FlatList, Image, StyleSheet, Text, View} from 'react-native';\nimport React, {useCallback} from 'react';\nimport type {ListRenderItem} from '@react-native/virtualized-lists';\nimport {User} from '../types';\n\nexport default ({users}: { users: User[] }) => {\n const renderItem: ListRenderItem = useCallback(({item: {picture}}) => {\n return (\n \n \n \n );\n }, []);\n\n if (users.length === 0) return (\n \n Figuring out your favorites...\n \n );\n\n return (\n \n ⭐My Favorites\n \n horizontal\n showsHorizontalScrollIndicator={false}\n data={users}\n renderItem={renderItem}\n keyExtractor={(item, index) => `${index}-${item.id.value}`}\n />\n \n );\n};\n\n// Looking for styles?\n// Check examples/cookbook/app/advanced/components/FavoritesList.tsx\nconst styles =\n...\n"})}),"\n",(0,s.jsxs)(t.p,{children:["Our ",(0,s.jsx)(t.code,{children:"ContactsList"})," component is similar to the ",(0,s.jsx)(t.code,{children:"FavoritesList"})," component, but it displays the list\nof\nall contacts vertically."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=network-requests/components/ContactsList.tsx",children:"import { FlatList, Image, StyleSheet, Text, View } from 'react-native';\nimport React, { useCallback } from 'react';\nimport type { ListRenderItem } from '@react-native/virtualized-lists';\nimport { User } from '../types';\n\nexport default ({ users }: { users: User[] }) => {\n const renderItem: ListRenderItem = useCallback(\n ({ item: { name, email, picture, cell }, index }) => {\n const { title, first, last } = name;\n const backgroundColor = index % 2 === 0 ? '#f9f9f9' : '#fff';\n return (\n \n \n \n \n Name: {title} {first} {last}\n \n Email: {email}\n Mobile: {cell}\n \n \n );\n },\n [],\n );\n\n if (users.length === 0) return ;\n\n return (\n \n \n data={users}\n renderItem={renderItem}\n keyExtractor={(item, index) => `${index}-${item.id.value}`}\n />\n \n );\n};\n\n// Looking for styles or FullScreenLoader component?\n// Check examples/cookbook/app/advanced/components/ContactsList.tsx\nconst FullScreenLoader = () => ...\nconst styles = ...\n"})}),"\n",(0,s.jsxs)(t.h2,{id:"start-testing-with-a-simple-test",children:["Start testing with a simple test",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#start-testing-with-a-simple-test",children:"#"})]}),"\n",(0,s.jsxs)(t.p,{children:["In our initial test we would like to test if the ",(0,s.jsx)(t.code,{children:"PhoneBook"})," component renders the ",(0,s.jsx)(t.code,{children:"FavoritesList"}),"\nand ",(0,s.jsx)(t.code,{children:"ContactsList"})," components correctly.\nWe will need to mock the network requests and their corresponding responses to ensure that the component behaves as\nexpected. To mock the network requests we will use ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/getting-started",target:"_blank",rel:"noopener noreferrer",children:"MSW (Mock Service Worker)"}),"."]}),"\n",(0,s.jsxs)(t.div,{className:"rspress-directive note",children:[(0,s.jsx)(t.div,{className:"rspress-directive-title",children:"NOTE"}),(0,s.jsx)(t.div,{className:"rspress-directive-content",children:(0,s.jsxs)(t.p,{children:["We recommend using the Mock Service Worker (MSW) library to declaratively mock API communication in your tests instead of stubbing ",(0,s.jsx)(t.code,{children:"fetch"}),", or relying on third-party adapters.\n"]})})]}),"\n",(0,s.jsxs)(t.div,{className:"rspress-directive info",children:[(0,s.jsx)(t.div,{className:"rspress-directive-title",children:"INFO"}),(0,s.jsxs)(t.div,{className:"rspress-directive-content",children:[(0,s.jsxs)(t.p,{children:["You can install MSW by running ",(0,s.jsx)(t.code,{children:"npm install msw --save-dev"})," or ",(0,s.jsx)(t.code,{children:"yarn add msw --dev"}),".\nMore info regarding installation can be found in ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/getting-started#step-1-install",target:"_blank",rel:"noopener noreferrer",children:"MSW's getting started guide"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["Please make sure you're also aware of ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/integrations/react-native",target:"_blank",rel:"noopener noreferrer",children:"MSW's setup guide"}),".\nPlease be minded that the MSW's setup guide is potentially incomplete and might contain discrepancies/missing pieces.\n"]})]})]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=network-requests/Phonebook.test.tsx",children:"import { render, screen, waitForElementToBeRemoved } from '@testing-library/react-native';\nimport React from 'react';\nimport PhoneBook from '../PhoneBook';\nimport { User } from '../types';\nimport {http, HttpResponse} from \"msw\";\nimport {setupServer} from \"msw/node\";\n\n// Define request handlers and response resolvers for random user API.\n// By default, we always return the happy path response.\nconst handlers = [\n http.get('https://randomuser.me/api/*', () => {\n return HttpResponse.json(DATA);\n }),\n];\n\n// Setup a request interception server with the given request handlers.\nconst server = setupServer(...handlers);\n\n// Enable API mocking via Mock Service Worker (MSW)\nbeforeAll(() => server.listen());\n// Reset any runtime request handlers we may add during the tests\nafterEach(() => server.resetHandlers());\n// Disable API mocking after the tests are done\nafterAll(() => server.close());\n\ndescribe('PhoneBook', () => {\n it('fetches all contacts and favorites successfully and renders lists in sections correctly', async () => {\n render();\n\n await waitForElementToBeRemoved(() => screen.getByText(/users data not quite there yet/i));\n expect(await screen.findByText('Name: Mrs Ida Kristensen')).toBeOnTheScreen();\n expect(await screen.findByText('Email: ida.kristensen@example.com')).toBeOnTheScreen();\n expect(await screen.findAllByText(/name/i)).toHaveLength(3);\n expect(await screen.findByText(/my favorites/i)).toBeOnTheScreen();\n expect(await screen.findAllByLabelText('favorite-contact-avatar')).toHaveLength(3);\n });\n});\n\nconst DATA: { results: User[] } = {\n results: [\n {\n name: {\n title: 'Mrs',\n first: 'Ida',\n last: 'Kristensen',\n },\n email: 'ida.kristensen@example.com',\n id: {\n name: 'CPR',\n value: '250562-5730',\n },\n picture: {\n large: 'https://randomuser.me/api/portraits/women/26.jpg',\n medium: 'https://randomuser.me/api/portraits/med/women/26.jpg',\n thumbnail: 'https://randomuser.me/api/portraits/thumb/women/26.jpg',\n },\n cell: '123-4567-890',\n },\n // For brevity, we have omitted the rest of the users, you can still find them in\n // examples/cookbook/app/network-requests/__tests__/test-utils.ts\n ...\n ],\n};\n"})}),"\n",(0,s.jsxs)(t.div,{className:"rspress-directive info",children:[(0,s.jsx)(t.div,{className:"rspress-directive-title",children:"INFO"}),(0,s.jsx)(t.div,{className:"rspress-directive-content",children:(0,s.jsxs)(t.p,{children:["More info regarding how to describe the network using request handlers, intercepting a request and handling its response can be found in the ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/getting-started#step-2-describe",target:"_blank",rel:"noopener noreferrer",children:"MSW's documentation"}),".\n"]})})]}),"\n",(0,s.jsxs)(t.h2,{id:"testing-error-handling",children:["Testing error handling",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#testing-error-handling",children:"#"})]}),"\n",(0,s.jsx)(t.p,{children:"As we are dealing with network requests, and things can go wrong, we should also cover the case when\nthe API request fails. In this case, we would like to test how our application behaves when the API request fails."}),"\n",(0,s.jsxs)(t.div,{className:"rspress-directive info",children:[(0,s.jsx)(t.div,{className:"rspress-directive-title",children:"INFO"}),(0,s.jsxs)(t.div,{className:"rspress-directive-content",children:[(0,s.jsxs)(t.p,{children:["The nature of the network can be highly dynamic, which makes it challenging to describe it completely in a fixed list of request handlers.",(0,s.jsx)(t.code,{children:".use()"})," API.\nMore info can be found in ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/best-practices/network-behavior-overrides",target:"_blank",rel:"noopener noreferrer",children:"MSW's Network behavior overrides documentation"}),"\n"]}),(0,s.jsx)(t.p,{children:"MSW provides us the means to override any particular network behavior using the designated "})]})]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=network-requests/Phonebook.test.tsx",children:"...\n\nconst mockServerFailureForGetAllContacts = () => {\n server.use(\n http.get('https://randomuser.me/api/', ({ request }) => {\n // Construct a URL instance out of the intercepted request.\n const url = new URL(request.url);\n // Read the \"results\" URL query parameter using the \"URLSearchParams\" API.\n const resultsLength = url.searchParams.get('results');\n // Simulate a server error for the get all contacts request.\n // We check if the \"results\" query parameter is set to \"25\"\n // to know it's the correct request to mock, in our case get all contacts.\n if (resultsLength === '25') {\n return new HttpResponse(null, { status: 500 });\n }\n // Return the default response for all other requests that match URL and verb. (in our case get favorites)\n return HttpResponse.json(DATA);\n }),\n );\n};\n\ndescribe('PhoneBook', () => {\n...\n it('fails to fetch all contacts and renders error message', async () => {\n mockServerFailureForGetAllContacts();\n render();\n\n await waitForElementToBeRemoved(() => screen.getByText(/users data not quite there yet/i));\n expect(\n await screen.findByText(/an error occurred: error fetching contacts/i),\n ).toBeOnTheScreen();\n });\n});\n\n"})}),"\n",(0,s.jsxs)(t.h2,{id:"global-guarding-against-unwanted-api-requests",children:["Global guarding against unwanted API requests",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#global-guarding-against-unwanted-api-requests",children:"#"})]}),"\n",(0,s.jsxs)(t.p,{children:["As mistakes may happen, we might forget to mock a network request in one of our tests in the future.\nTo prevent us from happening, and alert when a certain network request is left unhandled, you may choose to\nmove MSW's server management from ",(0,s.jsx)(t.code,{children:"PhoneBook.test.tsx"})," to Jest's setup file via ",(0,s.jsx)(t.a,{href:"https://jestjs.io/docs/configuration#setupfilesafterenv-array",target:"_blank",rel:"noopener noreferrer",children:(0,s.jsx)(t.code,{children:"setupFilesAfterEnv"})}),"."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=examples/cookbook/jest-setup.ts",children:"// Enable API mocking via Mock Service Worker (MSW)\nbeforeAll(() => server.listen());\n// Reset any runtime request handlers we may add during the tests\nafterEach(() => server.resetHandlers());\n// Disable API mocking after the tests are done\nafterAll(() => server.close());\n\n// ... rest of your setup file\n"})}),"\n",(0,s.jsx)(t.p,{children:"This setup will ensure you have the MSW server running before any test suite starts and stops it after all tests are done.\nWhich will result in a warning in the console if you forget to mock an API request in your test suite."}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"[MSW] Warning: intercepted a request without a matching request handler:\n β€’ GET https://randomuser.me/api/?results=25?results=25\n"})}),"\n",(0,s.jsxs)(t.h2,{id:"conclusion",children:["Conclusion",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#conclusion",children:"#"})]}),"\n",(0,s.jsx)(t.p,{children:"Testing a component that makes network requests in combination with MSW takes some initial preparation to configure and describe the overridden networks.\nWe can achieve that by using MSW's request handlers and intercepting APIs."}),"\n",(0,s.jsx)(t.p,{children:"Once up and running we gain full grip over the network requests, their responses, statuses.\nDoing so is crucial to be able to test how our application behaves in different\nscenarios, such as when the request is successful or when it fails."}),"\n",(0,s.jsx)(t.p,{children:"When global configuration is in place, MSW's will also warn us when an unhandled network requests has occurred throughout a test suite."}),"\n",(0,s.jsxs)(t.h2,{id:"further-reading-and-alternatives",children:["Further Reading and Alternatives",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#further-reading-and-alternatives",children:"#"})]}),"\n",(0,s.jsx)(t.p,{children:"Explore more advanced scenarios for mocking network requests with MSW:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["MSW's Basics - ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/basics/intercepting-requests",target:"_blank",rel:"noopener noreferrer",children:"Intercepting requests"})," and/or ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/basics/mocking-responses",target:"_blank",rel:"noopener noreferrer",children:"Mocking responses"})]}),"\n",(0,s.jsxs)(t.li,{children:["MSW's Network behavior - how to describe ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/network-behavior/rest",target:"_blank",rel:"noopener noreferrer",children:"REST"})," and/or ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/network-behavior/graphql",target:"_blank",rel:"noopener noreferrer",children:"GraphQL"})," APIs"]}),"\n"]})]})}function i(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:t}=Object.assign({},(0,r.ah)(),e.components);return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}let o=i;i.__RSPRESS_PAGE_META={},i.__RSPRESS_PAGE_META["14.x%2Fcookbook%2Fadvanced%2Fnetwork-requests.md"]={toc:[{text:"Introduction",id:"introduction",depth:2},{text:"Phonebook Example",id:"phonebook-example",depth:2},{text:"Start testing with a simple test",id:"start-testing-with-a-simple-test",depth:2},{text:"Testing error handling",id:"testing-error-handling",depth:2},{text:"Global guarding against unwanted API requests",id:"global-guarding-against-unwanted-api-requests",depth:2},{text:"Conclusion",id:"conclusion",depth:2},{text:"Further Reading and Alternatives",id:"further-reading-and-alternatives",depth:2}],title:"Network Requests",headingTitle:"Network Requests",frontmatter:{}}}}]); \ No newline at end of file +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["1290"],{6147:function(e,t,n){n.r(t),n.d(t,{default:()=>o});var s=n(5893),r=n(65);function a(e){let t=Object.assign({h1:"h1",a:"a",h2:"h2",p:"p",div:"div",code:"code",pre:"pre",ul:"ul",li:"li"},(0,r.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(t.h1,{id:"network-requests",children:["Network Requests",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#network-requests",children:"#"})]}),"\n",(0,s.jsxs)(t.h2,{id:"introduction",children:["Introduction",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#introduction",children:"#"})]}),"\n",(0,s.jsx)(t.p,{children:"Mocking network requests is an essential part of testing React Native applications. By mocking\nnetwork\nrequests, you can control the data that is returned from the server and test how your application\nbehaves in different scenarios, such as when the request is successful or when it fails."}),"\n",(0,s.jsx)(t.p,{children:"In this guide, we will show you how to mock network requests and guard your test suits from unwanted\nand unmocked/unhandled network requests"}),"\n",(0,s.jsxs)(t.div,{className:"rspress-directive info",children:[(0,s.jsx)(t.div,{className:"rspress-directive-title",children:"INFO"}),(0,s.jsx)(t.div,{className:"rspress-directive-content",children:(0,s.jsxs)(t.p,{children:["To simulate a real-world scenario, we will use the ",(0,s.jsx)(t.a,{href:"https://randomuser.me/",target:"_blank",rel:"noopener noreferrer",children:"Random User Generator API"})," that provides random user data.\n"]})})]}),"\n",(0,s.jsxs)(t.h2,{id:"phonebook-example",children:["Phonebook Example",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#phonebook-example",children:"#"})]}),"\n",(0,s.jsxs)(t.p,{children:["Let's assume we have a simple phonebook application that\nuses ",(0,s.jsx)(t.a,{href:"https://reactnative.dev/docs/network#using-fetch",target:"_blank",rel:"noopener noreferrer",children:(0,s.jsx)(t.code,{children:"fetch"})})," for fetching Data from a server.\nIn our case, we have a list of contacts and favorites that we want to display in our application."]}),"\n",(0,s.jsx)(t.p,{children:"This is how the root of the application looks like:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=network-requests/Phonebook.tsx",children:"import React, { useEffect, useState } from 'react';\nimport { Text } from 'react-native';\nimport { User } from './types';\nimport ContactsList from './components/ContactsList';\nimport FavoritesList from './components/FavoritesList';\nimport getAllContacts from './api/getAllContacts';\nimport getAllFavorites from './api/getAllFavorites';\n\nexport default () => {\n const [usersData, setUsersData] = useState([]);\n const [favoritesData, setFavoritesData] = useState([]);\n const [error, setError] = useState(null);\n\n useEffect(() => {\n const _getAllContacts = async () => {\n const _data = await getAllContacts();\n setUsersData(_data);\n };\n const _getAllFavorites = async () => {\n const _data = await getAllFavorites();\n setFavoritesData(_data);\n };\n\n const run = async () => {\n try {\n await Promise.all([_getAllContacts(), _getAllFavorites()]);\n } catch (e) {\n const message = isErrorWithMessage(e) ? e.message : 'Something went wrong';\n setError(message);\n }\n };\n\n void run();\n }, []);\n\n if (error) {\n return An error occurred: {error};\n }\n\n return (\n <>\n \n \n \n );\n};\n"})}),"\n",(0,s.jsxs)(t.p,{children:["We fetch the contacts from the server using the ",(0,s.jsx)(t.code,{children:"getAllFavorites"})," function that utilizes ",(0,s.jsx)(t.code,{children:"fetch"}),"."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=network-requests/api/getAllContacts.ts",children:"import { User } from '../types';\n\nexport default async (): Promise => {\n const res = await fetch('https://randomuser.me/api/?results=25');\n if (!res.ok) {\n throw new Error(`Error fetching contacts`);\n }\n const json = await res.json();\n return json.results;\n};\n"})}),"\n",(0,s.jsx)(t.p,{children:"We have similar function for fetching the favorites, but this time limiting the results to 10."}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=network-requests/api/getAllFavorites.ts",children:"import { User } from '../types';\n\nexport default async (): Promise => {\n const res = await fetch('https://randomuser.me/api/?results=10');\n if (!res.ok) {\n throw new Error(`Error fetching favorites`);\n }\n const json = await res.json();\n return json.results;\n};\n"})}),"\n",(0,s.jsxs)(t.p,{children:["Our ",(0,s.jsx)(t.code,{children:"FavoritesList"})," component is a simple component that displays the list of favorite contacts and\ntheir avatars horizontally."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=network-requests/components/FavoritesList.tsx",children:"import {FlatList, Image, StyleSheet, Text, View} from 'react-native';\nimport React, {useCallback} from 'react';\nimport type {ListRenderItem} from '@react-native/virtualized-lists';\nimport {User} from '../types';\n\nexport default ({users}: { users: User[] }) => {\n const renderItem: ListRenderItem = useCallback(({item: {picture}}) => {\n return (\n \n \n \n );\n }, []);\n\n if (users.length === 0) return (\n \n Figuring out your favorites...\n \n );\n\n return (\n \n ⭐My Favorites\n \n horizontal\n showsHorizontalScrollIndicator={false}\n data={users}\n renderItem={renderItem}\n keyExtractor={(item, index) => `${index}-${item.id.value}`}\n />\n \n );\n};\n\n// Looking for styles?\n// Check examples/cookbook/app/advanced/components/FavoritesList.tsx\nconst styles =\n...\n"})}),"\n",(0,s.jsxs)(t.p,{children:["Our ",(0,s.jsx)(t.code,{children:"ContactsList"})," component is similar to the ",(0,s.jsx)(t.code,{children:"FavoritesList"})," component, but it displays the list\nof\nall contacts vertically."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=network-requests/components/ContactsList.tsx",children:"import { FlatList, Image, StyleSheet, Text, View } from 'react-native';\nimport React, { useCallback } from 'react';\nimport type { ListRenderItem } from '@react-native/virtualized-lists';\nimport { User } from '../types';\n\nexport default ({ users }: { users: User[] }) => {\n const renderItem: ListRenderItem = useCallback(\n ({ item: { name, email, picture, cell }, index }) => {\n const { title, first, last } = name;\n const backgroundColor = index % 2 === 0 ? '#f9f9f9' : '#fff';\n return (\n \n \n \n \n Name: {title} {first} {last}\n \n Email: {email}\n Mobile: {cell}\n \n \n );\n },\n [],\n );\n\n if (users.length === 0) return ;\n\n return (\n \n \n data={users}\n renderItem={renderItem}\n keyExtractor={(item, index) => `${index}-${item.id.value}`}\n />\n \n );\n};\n\n// Looking for styles or FullScreenLoader component?\n// Check examples/cookbook/app/advanced/components/ContactsList.tsx\nconst FullScreenLoader = () => ...\nconst styles = ...\n"})}),"\n",(0,s.jsxs)(t.h2,{id:"start-testing-with-a-simple-test",children:["Start testing with a simple test",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#start-testing-with-a-simple-test",children:"#"})]}),"\n",(0,s.jsxs)(t.p,{children:["In our initial test we would like to test if the ",(0,s.jsx)(t.code,{children:"PhoneBook"})," component renders the ",(0,s.jsx)(t.code,{children:"FavoritesList"}),"\nand ",(0,s.jsx)(t.code,{children:"ContactsList"})," components correctly.\nWe will need to mock the network requests and their corresponding responses to ensure that the component behaves as\nexpected. To mock the network requests we will use ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/getting-started",target:"_blank",rel:"noopener noreferrer",children:"MSW (Mock Service Worker)"}),"."]}),"\n",(0,s.jsxs)(t.div,{className:"rspress-directive note",children:[(0,s.jsx)(t.div,{className:"rspress-directive-title",children:"NOTE"}),(0,s.jsx)(t.div,{className:"rspress-directive-content",children:(0,s.jsxs)(t.p,{children:["We recommend using the Mock Service Worker (MSW) library to declaratively mock API communication in your tests instead of stubbing ",(0,s.jsx)(t.code,{children:"fetch"}),", or relying on third-party adapters.\n"]})})]}),"\n",(0,s.jsxs)(t.div,{className:"rspress-directive info",children:[(0,s.jsx)(t.div,{className:"rspress-directive-title",children:"INFO"}),(0,s.jsxs)(t.div,{className:"rspress-directive-content",children:[(0,s.jsxs)(t.p,{children:["You can install MSW by running ",(0,s.jsx)(t.code,{children:"npm install msw --save-dev"})," or ",(0,s.jsx)(t.code,{children:"yarn add msw --dev"}),".\nMore info regarding installation can be found in ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/getting-started#step-1-install",target:"_blank",rel:"noopener noreferrer",children:"MSW's getting started guide"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["Please make sure you're also aware of ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/integrations/react-native",target:"_blank",rel:"noopener noreferrer",children:"MSW's setup guide"}),".\nPlease be minded that the MSW's setup guide is potentially incomplete and might contain discrepancies/missing pieces.\n"]})]})]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=network-requests/Phonebook.test.tsx",children:"import { render, screen, waitForElementToBeRemoved } from '@testing-library/react-native';\nimport React from 'react';\nimport PhoneBook from '../PhoneBook';\nimport { User } from '../types';\nimport {http, HttpResponse} from \"msw\";\nimport {setupServer} from \"msw/node\";\n\n// Define request handlers and response resolvers for random user API.\n// By default, we always return the happy path response.\nconst handlers = [\n http.get('https://randomuser.me/api/*', () => {\n return HttpResponse.json(DATA);\n }),\n];\n\n// Setup a request interception server with the given request handlers.\nconst server = setupServer(...handlers);\n\n// Enable API mocking via Mock Service Worker (MSW)\nbeforeAll(() => server.listen());\n// Reset any runtime request handlers we may add during the tests\nafterEach(() => server.resetHandlers());\n// Disable API mocking after the tests are done\nafterAll(() => server.close());\n\ndescribe('PhoneBook', () => {\n it('fetches all contacts and favorites successfully and renders lists in sections correctly', async () => {\n await render();\n\n await waitForElementToBeRemoved(() => screen.getByText(/users data not quite there yet/i));\n expect(await screen.findByText('Name: Mrs Ida Kristensen')).toBeOnTheScreen();\n expect(await screen.findByText('Email: ida.kristensen@example.com')).toBeOnTheScreen();\n expect(await screen.findAllByText(/name/i)).toHaveLength(3);\n expect(await screen.findByText(/my favorites/i)).toBeOnTheScreen();\n expect(await screen.findAllByLabelText('favorite-contact-avatar')).toHaveLength(3);\n });\n});\n\nconst DATA: { results: User[] } = {\n results: [\n {\n name: {\n title: 'Mrs',\n first: 'Ida',\n last: 'Kristensen',\n },\n email: 'ida.kristensen@example.com',\n id: {\n name: 'CPR',\n value: '250562-5730',\n },\n picture: {\n large: 'https://randomuser.me/api/portraits/women/26.jpg',\n medium: 'https://randomuser.me/api/portraits/med/women/26.jpg',\n thumbnail: 'https://randomuser.me/api/portraits/thumb/women/26.jpg',\n },\n cell: '123-4567-890',\n },\n // For brevity, we have omitted the rest of the users, you can still find them in\n // examples/cookbook/app/network-requests/__tests__/test-utils.ts\n ...\n ],\n};\n"})}),"\n",(0,s.jsxs)(t.div,{className:"rspress-directive info",children:[(0,s.jsx)(t.div,{className:"rspress-directive-title",children:"INFO"}),(0,s.jsx)(t.div,{className:"rspress-directive-content",children:(0,s.jsxs)(t.p,{children:["More info regarding how to describe the network using request handlers, intercepting a request and handling its response can be found in the ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/getting-started#step-2-describe",target:"_blank",rel:"noopener noreferrer",children:"MSW's documentation"}),".\n"]})})]}),"\n",(0,s.jsxs)(t.h2,{id:"testing-error-handling",children:["Testing error handling",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#testing-error-handling",children:"#"})]}),"\n",(0,s.jsx)(t.p,{children:"As we are dealing with network requests, and things can go wrong, we should also cover the case when\nthe API request fails. In this case, we would like to test how our application behaves when the API request fails."}),"\n",(0,s.jsxs)(t.div,{className:"rspress-directive info",children:[(0,s.jsx)(t.div,{className:"rspress-directive-title",children:"INFO"}),(0,s.jsxs)(t.div,{className:"rspress-directive-content",children:[(0,s.jsxs)(t.p,{children:["The nature of the network can be highly dynamic, which makes it challenging to describe it completely in a fixed list of request handlers.",(0,s.jsx)(t.code,{children:".use()"})," API.\nMore info can be found in ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/best-practices/network-behavior-overrides",target:"_blank",rel:"noopener noreferrer",children:"MSW's Network behavior overrides documentation"}),"\n"]}),(0,s.jsx)(t.p,{children:"MSW provides us the means to override any particular network behavior using the designated "})]})]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=network-requests/Phonebook.test.tsx",children:"...\n\nconst mockServerFailureForGetAllContacts = () => {\n server.use(\n http.get('https://randomuser.me/api/', ({ request }) => {\n // Construct a URL instance out of the intercepted request.\n const url = new URL(request.url);\n // Read the \"results\" URL query parameter using the \"URLSearchParams\" API.\n const resultsLength = url.searchParams.get('results');\n // Simulate a server error for the get all contacts request.\n // We check if the \"results\" query parameter is set to \"25\"\n // to know it's the correct request to mock, in our case get all contacts.\n if (resultsLength === '25') {\n return new HttpResponse(null, { status: 500 });\n }\n // Return the default response for all other requests that match URL and verb. (in our case get favorites)\n return HttpResponse.json(DATA);\n }),\n );\n};\n\ndescribe('PhoneBook', () => {\n...\n it('fails to fetch all contacts and renders error message', async () => {\n mockServerFailureForGetAllContacts();\n await render();\n\n await waitForElementToBeRemoved(() => screen.getByText(/users data not quite there yet/i));\n expect(\n await screen.findByText(/an error occurred: error fetching contacts/i),\n ).toBeOnTheScreen();\n });\n});\n\n"})}),"\n",(0,s.jsxs)(t.h2,{id:"global-guarding-against-unwanted-api-requests",children:["Global guarding against unwanted API requests",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#global-guarding-against-unwanted-api-requests",children:"#"})]}),"\n",(0,s.jsxs)(t.p,{children:["As mistakes may happen, we might forget to mock a network request in one of our tests in the future.\nTo prevent us from happening, and alert when a certain network request is left unhandled, you may choose to\nmove MSW's server management from ",(0,s.jsx)(t.code,{children:"PhoneBook.test.tsx"})," to Jest's setup file via ",(0,s.jsx)(t.a,{href:"https://jestjs.io/docs/configuration#setupfilesafterenv-array",target:"_blank",rel:"noopener noreferrer",children:(0,s.jsx)(t.code,{children:"setupFilesAfterEnv"})}),"."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tsx",meta:"title=examples/cookbook/jest-setup.ts",children:"// Enable API mocking via Mock Service Worker (MSW)\nbeforeAll(() => server.listen());\n// Reset any runtime request handlers we may add during the tests\nafterEach(() => server.resetHandlers());\n// Disable API mocking after the tests are done\nafterAll(() => server.close());\n\n// ... rest of your setup file\n"})}),"\n",(0,s.jsx)(t.p,{children:"This setup will ensure you have the MSW server running before any test suite starts and stops it after all tests are done.\nWhich will result in a warning in the console if you forget to mock an API request in your test suite."}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"[MSW] Warning: intercepted a request without a matching request handler:\n β€’ GET https://randomuser.me/api/?results=25?results=25\n"})}),"\n",(0,s.jsxs)(t.h2,{id:"conclusion",children:["Conclusion",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#conclusion",children:"#"})]}),"\n",(0,s.jsx)(t.p,{children:"Testing a component that makes network requests in combination with MSW takes some initial preparation to configure and describe the overridden networks.\nWe can achieve that by using MSW's request handlers and intercepting APIs."}),"\n",(0,s.jsx)(t.p,{children:"Once up and running we gain full grip over the network requests, their responses, statuses.\nDoing so is crucial to be able to test how our application behaves in different\nscenarios, such as when the request is successful or when it fails."}),"\n",(0,s.jsx)(t.p,{children:"When global configuration is in place, MSW's will also warn us when an unhandled network requests has occurred throughout a test suite."}),"\n",(0,s.jsxs)(t.h2,{id:"further-reading-and-alternatives",children:["Further Reading and Alternatives",(0,s.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#further-reading-and-alternatives",children:"#"})]}),"\n",(0,s.jsx)(t.p,{children:"Explore more advanced scenarios for mocking network requests with MSW:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["MSW's Basics - ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/basics/intercepting-requests",target:"_blank",rel:"noopener noreferrer",children:"Intercepting requests"})," and/or ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/basics/mocking-responses",target:"_blank",rel:"noopener noreferrer",children:"Mocking responses"})]}),"\n",(0,s.jsxs)(t.li,{children:["MSW's Network behavior - how to describe ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/network-behavior/rest",target:"_blank",rel:"noopener noreferrer",children:"REST"})," and/or ",(0,s.jsx)(t.a,{href:"https://mswjs.io/docs/network-behavior/graphql",target:"_blank",rel:"noopener noreferrer",children:"GraphQL"})," APIs"]}),"\n"]})]})}function i(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:t}=Object.assign({},(0,r.ah)(),e.components);return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}let o=i;i.__RSPRESS_PAGE_META={},i.__RSPRESS_PAGE_META["14.x%2Fcookbook%2Fadvanced%2Fnetwork-requests.md"]={toc:[{text:"Introduction",id:"introduction",depth:2},{text:"Phonebook Example",id:"phonebook-example",depth:2},{text:"Start testing with a simple test",id:"start-testing-with-a-simple-test",depth:2},{text:"Testing error handling",id:"testing-error-handling",depth:2},{text:"Global guarding against unwanted API requests",id:"global-guarding-against-unwanted-api-requests",depth:2},{text:"Conclusion",id:"conclusion",depth:2},{text:"Further Reading and Alternatives",id:"further-reading-and-alternatives",depth:2}],title:"Network Requests",headingTitle:"Network Requests",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/2473.225dd9ca.js b/static/js/async/2473.225dd9ca.js deleted file mode 100644 index 5b7b83c0..00000000 --- a/static/js/async/2473.225dd9ca.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["2473"],{7321:function(e,i,s){s.r(i),s.d(i,{default:()=>l});var n=s(5893),r=s(65);function c(e){let i=Object.assign({h1:"h1",a:"a",h2:"h2",code:"code",pre:"pre",p:"p",div:"div",ul:"ul",li:"li"},(0,r.ah)(),e.components);return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(i.h1,{id:"accessibility",children:["Accessibility",(0,n.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#accessibility",children:"#"})]}),"\n",(0,n.jsxs)(i.h2,{id:"ishiddenfromaccessibility",children:[(0,n.jsx)(i.code,{children:"isHiddenFromAccessibility"}),(0,n.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#ishiddenfromaccessibility",children:"#"})]}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{className:"language-ts",children:"function isHiddenFromAccessibility(element: HostElement | null): boolean {}\n"})}),"\n",(0,n.jsxs)(i.p,{children:["Also available as ",(0,n.jsx)(i.code,{children:"isInaccessible()"})," alias for React Testing Library compatibility."]}),"\n",(0,n.jsx)(i.p,{children:"Checks if given element is hidden from assistive technology, e.g. screen readers."}),"\n",(0,n.jsxs)(i.div,{className:"rspress-directive note",children:[(0,n.jsx)(i.div,{className:"rspress-directive-title",children:"NOTE"}),(0,n.jsxs)(i.div,{className:"rspress-directive-content",children:[(0,n.jsxs)(i.p,{children:["Like ",(0,n.jsx)(i.a,{href:"https://testing-library.com/docs/dom-testing-library/api-accessibility/#isinaccessible",target:"_blank",rel:"noopener noreferrer",children:(0,n.jsx)(i.code,{children:"isInaccessible"})})," function from DOM Testing Library this function considers both accessibility elements and presentational elements (regular ",(0,n.jsx)(i.code,{children:"View"}),"s) to be accessible, unless they are hidden in terms of host platform."]}),"\n",(0,n.jsxs)(i.p,{children:["This covers only part of ",(0,n.jsx)(i.a,{href:"https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion",target:"_blank",rel:"noopener noreferrer",children:"ARIA notion of Accessiblity Tree"}),", as ARIA excludes both hidden and presentational elements from the Accessibility Tree.\n"]})]})]}),"\n",(0,n.jsx)(i.p,{children:"For the scope of this function, element is inaccessible when it, or any of its ancestors, meets any of the following conditions:"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["it has ",(0,n.jsx)(i.code,{children:"display: none"})," style"]}),"\n",(0,n.jsxs)(i.li,{children:["it has ",(0,n.jsx)(i.a,{href:"https://reactnative.dev/docs/accessibility#aria-hidden",target:"_blank",rel:"noopener noreferrer",children:(0,n.jsx)(i.code,{children:"aria-hidden"})})," prop set to ",(0,n.jsx)(i.code,{children:"true"})]}),"\n",(0,n.jsxs)(i.li,{children:["it has ",(0,n.jsx)(i.a,{href:"https://reactnative.dev/docs/accessibility#accessibilityelementshidden-ios",target:"_blank",rel:"noopener noreferrer",children:(0,n.jsx)(i.code,{children:"accessibilityElementsHidden"})})," prop set to ",(0,n.jsx)(i.code,{children:"true"})]}),"\n",(0,n.jsxs)(i.li,{children:["it has ",(0,n.jsx)(i.a,{href:"https://reactnative.dev/docs/accessibility#importantforaccessibility-android",target:"_blank",rel:"noopener noreferrer",children:(0,n.jsx)(i.code,{children:"importantForAccessibility"})})," prop set to ",(0,n.jsx)(i.code,{children:"no-hide-descendants"})]}),"\n",(0,n.jsxs)(i.li,{children:["it has sibling host element with either ",(0,n.jsx)(i.a,{href:"https://reactnative.dev/docs/accessibility#aria-modal-ios",target:"_blank",rel:"noopener noreferrer",children:(0,n.jsx)(i.code,{children:"aria-modal"})})," or ",(0,n.jsx)(i.a,{href:"https://reactnative.dev/docs/accessibility#accessibilityviewismodal-ios",target:"_blank",rel:"noopener noreferrer",children:(0,n.jsx)(i.code,{children:"accessibilityViewIsModal"})})," prop set to ",(0,n.jsx)(i.code,{children:"true"})]}),"\n"]}),"\n",(0,n.jsxs)(i.p,{children:["Specifying ",(0,n.jsx)(i.code,{children:"accessible={false}"}),", ",(0,n.jsx)(i.code,{children:'accessiblityRole="none"'}),", or ",(0,n.jsx)(i.code,{children:'importantForAccessibility="no"'})," props does not cause the element to become inaccessible."]})]})}function t(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:i}=Object.assign({},(0,r.ah)(),e.components);return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}let l=t;t.__RSPRESS_PAGE_META={},t.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fapi%2Fmisc%2Faccessibility.mdx"]={toc:[{text:"`isHiddenFromAccessibility`",id:"ishiddenfromaccessibility",depth:2}],title:"Accessibility",headingTitle:"Accessibility",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/2473.f2ef5a90.js b/static/js/async/2473.f2ef5a90.js new file mode 100644 index 00000000..58f30c76 --- /dev/null +++ b/static/js/async/2473.f2ef5a90.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["2473"],{7321:function(e,i,s){s.r(i),s.d(i,{default:()=>l});var n=s(5893),r=s(65);function c(e){let i=Object.assign({h1:"h1",a:"a",h2:"h2",code:"code",pre:"pre",p:"p",div:"div",ul:"ul",li:"li"},(0,r.ah)(),e.components);return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(i.h1,{id:"accessibility",children:["Accessibility",(0,n.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#accessibility",children:"#"})]}),"\n",(0,n.jsxs)(i.h2,{id:"ishiddenfromaccessibility",children:[(0,n.jsx)(i.code,{children:"isHiddenFromAccessibility"}),(0,n.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#ishiddenfromaccessibility",children:"#"})]}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{className:"language-ts",children:"function isHiddenFromAccessibility(element: HostElement | null): boolean {}\n"})}),"\n",(0,n.jsxs)(i.p,{children:["Also available as ",(0,n.jsx)(i.code,{children:"isInaccessible()"})," alias for React Testing Library compatibility."]}),"\n",(0,n.jsx)(i.p,{children:"Checks if given element is hidden from assistive technology, e.g. screen readers."}),"\n",(0,n.jsxs)(i.div,{className:"rspress-directive note",children:[(0,n.jsx)(i.div,{className:"rspress-directive-title",children:"NOTE"}),(0,n.jsxs)(i.div,{className:"rspress-directive-content",children:[(0,n.jsxs)(i.p,{children:["Like ",(0,n.jsx)(i.a,{href:"https://testing-library.com/docs/dom-testing-library/api-accessibility/#isinaccessible",target:"_blank",rel:"noopener noreferrer",children:(0,n.jsx)(i.code,{children:"isInaccessible"})})," function from DOM Testing Library this function considers both accessibility elements and presentational elements (regular ",(0,n.jsx)(i.code,{children:"View"}),"s) to be accessible, unless they are hidden in terms of host platform."]}),"\n",(0,n.jsxs)(i.p,{children:["This covers only part of ",(0,n.jsx)(i.a,{href:"https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion",target:"_blank",rel:"noopener noreferrer",children:"ARIA notion of Accessibility Tree"}),", as ARIA excludes both hidden and presentational elements from the Accessibility Tree.\n"]})]})]}),"\n",(0,n.jsx)(i.p,{children:"For the scope of this function, element is inaccessible when it, or any of its ancestors, meets any of the following conditions:"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["it has ",(0,n.jsx)(i.code,{children:"display: none"})," style"]}),"\n",(0,n.jsxs)(i.li,{children:["it has ",(0,n.jsx)(i.a,{href:"https://reactnative.dev/docs/accessibility#aria-hidden",target:"_blank",rel:"noopener noreferrer",children:(0,n.jsx)(i.code,{children:"aria-hidden"})})," prop set to ",(0,n.jsx)(i.code,{children:"true"})]}),"\n",(0,n.jsxs)(i.li,{children:["it has ",(0,n.jsx)(i.a,{href:"https://reactnative.dev/docs/accessibility#accessibilityelementshidden-ios",target:"_blank",rel:"noopener noreferrer",children:(0,n.jsx)(i.code,{children:"accessibilityElementsHidden"})})," prop set to ",(0,n.jsx)(i.code,{children:"true"})]}),"\n",(0,n.jsxs)(i.li,{children:["it has ",(0,n.jsx)(i.a,{href:"https://reactnative.dev/docs/accessibility#importantforaccessibility-android",target:"_blank",rel:"noopener noreferrer",children:(0,n.jsx)(i.code,{children:"importantForAccessibility"})})," prop set to ",(0,n.jsx)(i.code,{children:"no-hide-descendants"})]}),"\n",(0,n.jsxs)(i.li,{children:["it has sibling host element with either ",(0,n.jsx)(i.a,{href:"https://reactnative.dev/docs/accessibility#aria-modal-ios",target:"_blank",rel:"noopener noreferrer",children:(0,n.jsx)(i.code,{children:"aria-modal"})})," or ",(0,n.jsx)(i.a,{href:"https://reactnative.dev/docs/accessibility#accessibilityviewismodal-ios",target:"_blank",rel:"noopener noreferrer",children:(0,n.jsx)(i.code,{children:"accessibilityViewIsModal"})})," prop set to ",(0,n.jsx)(i.code,{children:"true"})]}),"\n"]}),"\n",(0,n.jsxs)(i.p,{children:["Specifying ",(0,n.jsx)(i.code,{children:"accessible={false}"}),", ",(0,n.jsx)(i.code,{children:'role="none"'}),", ",(0,n.jsx)(i.code,{children:'accessibilityRole="none"'}),", or ",(0,n.jsx)(i.code,{children:'importantForAccessibility="no"'})," props does not cause the element to become inaccessible."]})]})}function t(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:i}=Object.assign({},(0,r.ah)(),e.components);return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}let l=t;t.__RSPRESS_PAGE_META={},t.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fapi%2Fmisc%2Faccessibility.mdx"]={toc:[{text:"`isHiddenFromAccessibility`",id:"ishiddenfromaccessibility",depth:2}],title:"Accessibility",headingTitle:"Accessibility",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/3012.5460a8c5.js b/static/js/async/3012.5460a8c5.js new file mode 100644 index 00000000..661a0a3e --- /dev/null +++ b/static/js/async/3012.5460a8c5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["3012"],{2931:function(e,n,t){t.r(n),t.d(n,{default:()=>a});var r=t(5893),s=t(65);function i(e){let n=Object.assign({h1:"h1",a:"a",h2:"h2",code:"code",div:"div",p:"p",pre:"pre",h3:"h3",h4:"h4"},(0,s.ah)(),e.components);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.h1,{id:"fire-event-api",children:["Fire Event API",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#fire-event-api",children:"#"})]}),"\n",(0,r.jsxs)(n.h2,{id:"fire-event",children:[(0,r.jsx)(n.code,{children:"fireEvent"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#fire-event",children:"#"})]}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive note",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,r.jsxs)(n.div,{className:"rspress-directive-content",children:[(0,r.jsxs)(n.p,{children:["For common events like ",(0,r.jsx)(n.code,{children:"press"})," or ",(0,r.jsx)(n.code,{children:"type"})," it's recommended to use ",(0,r.jsx)(n.a,{href:"/docs/api/events/user-event",children:"User Event API"})," as it offers\nmore realistic event simulation by emitting a sequence of events with proper event objects that mimic React Native runtime behavior."]}),"\n",(0,r.jsx)(n.p,{children:"Use Fire Event for cases not supported by User Event and for triggering event handlers on composite components.\n"})]})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"function fireEvent(element: HostElement, eventName: string, ...data: unknown[]): Promise;\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"fireEvent"})," API allows you to trigger all kinds of event handlers on both host and composite components. It will try to invoke a single event handler traversing the component tree bottom-up from passed element and trying to find enabled event handler named ",(0,r.jsx)(n.code,{children:"onXxx"})," when ",(0,r.jsx)(n.code,{children:"xxx"})," is the name of the event passed."]}),"\n",(0,r.jsx)(n.p,{children:"Unlike User Event, this API does not automatically pass event object to event handler, this is responsibility of the user to construct such object."}),"\n",(0,r.jsxs)(n.p,{children:["This function uses async ",(0,r.jsx)(n.code,{children:"act"})," function internally to ensure all pending React updates are executed during event handling."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:"import { render, screen, fireEvent } from '@testing-library/react-native';\n\ntest('fire changeText event', async () => {\n const onEventMock = jest.fn();\n await render(\n // MyComponent renders TextInput which has a placeholder 'Enter details'\n // and with `onChangeText` bound to handleChangeText\n \n );\n\n await fireEvent(screen.getByPlaceholderText('change'), 'onChangeText', 'ab');\n expect(onEventMock).toHaveBeenCalledWith('ab');\n});\n"})}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive note",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,r.jsx)(n.div,{className:"rspress-directive-content",children:(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"fireEvent"})," performs checks that should prevent events firing on disabled elements.\n"]})})]}),"\n",(0,r.jsxs)(n.p,{children:["An example using ",(0,r.jsx)(n.code,{children:"fireEvent"})," with native events that aren't already aliased by the ",(0,r.jsx)(n.code,{children:"fireEvent"})," api."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:"import { TextInput, View } from 'react-native';\nimport { fireEvent, render, screen } from '@testing-library/react-native';\n\nconst onBlurMock = jest.fn();\n\nawait render(\n \n \n \n);\n\n// you can omit the `on` prefix\nawait fireEvent(screen.getByPlaceholderText('my placeholder'), 'blur');\n"})}),"\n",(0,r.jsxs)(n.p,{children:["FireEvent exposes convenience methods for common events like: ",(0,r.jsx)(n.code,{children:"press"}),", ",(0,r.jsx)(n.code,{children:"changeText"}),", ",(0,r.jsx)(n.code,{children:"scroll"}),"."]}),"\n",(0,r.jsxs)(n.h3,{id:"press",children:[(0,r.jsx)(n.code,{children:"fireEvent.press"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#press",children:"#"})]}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive note",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,r.jsx)(n.div,{className:"rspress-directive-content",children:(0,r.jsxs)(n.p,{children:["It is recommended to use the User Event ",(0,r.jsx)(n.a,{href:"/docs/api/events/user-event#press",children:(0,r.jsx)(n.code,{children:"press()"})})," helper instead as it offers more realistic simulation of press interaction, including pressable support.\n"]})})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-tsx",children:"fireEvent.press: (\n element: HostElement,\n ...data: Array,\n) => Promise\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Invokes ",(0,r.jsx)(n.code,{children:"press"})," event handler on the element or parent element in the tree."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:"import { View, Text, TouchableOpacity } from 'react-native';\nimport { render, screen, fireEvent } from '@testing-library/react-native';\n\nconst onPressMock = jest.fn();\nconst eventData = {\n nativeEvent: {\n pageX: 20,\n pageY: 30,\n },\n};\n\nawait render(\n \n \n Press me\n \n \n);\n\nawait fireEvent.press(screen.getByText('Press me'), eventData);\nexpect(onPressMock).toHaveBeenCalledWith(eventData);\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"change-text",children:[(0,r.jsx)(n.code,{children:"fireEvent.changeText"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#change-text",children:"#"})]}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive note",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,r.jsx)(n.div,{className:"rspress-directive-content",children:(0,r.jsxs)(n.p,{children:["It is recommended to use the User Event ",(0,r.jsx)(n.a,{href:"/docs/api/events/user-event#type",children:(0,r.jsx)(n.code,{children:"type()"})})," helper instead as it offers more realistic simulation of text change interaction, including key-by-key typing, element focus, and other editing events.\n"]})})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-tsx",children:"fireEvent.changeText: (\n element: HostElement,\n ...data: Array,\n) => Promise\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Invokes ",(0,r.jsx)(n.code,{children:"changeText"})," event handler on the element or parent element in the tree."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:"import { View, TextInput } from 'react-native';\nimport { render, screen, fireEvent } from '@testing-library/react-native';\n\nconst onChangeTextMock = jest.fn();\nconst CHANGE_TEXT = 'content';\n\nawait render(\n \n \n \n);\n\nawait fireEvent.changeText(screen.getByPlaceholderText('Enter data'), CHANGE_TEXT);\n"})}),"\n",(0,r.jsxs)(n.h3,{id:"scroll",children:[(0,r.jsx)(n.code,{children:"fireEvent.scroll"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#scroll",children:"#"})]}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive note",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,r.jsx)(n.div,{className:"rspress-directive-content",children:(0,r.jsxs)(n.p,{children:["Prefer using ",(0,r.jsx)(n.a,{href:"/docs/api/events/user-event#scrollto",children:(0,r.jsx)(n.code,{children:"user.scrollTo"})})," over ",(0,r.jsx)(n.code,{children:"fireEvent.scroll"})," for ",(0,r.jsx)(n.code,{children:"ScrollView"}),", ",(0,r.jsx)(n.code,{children:"FlatList"}),", and ",(0,r.jsx)(n.code,{children:"SectionList"})," components. User Event provides a more realistic event simulation based on React Native runtime behavior.\n"]})})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-tsx",children:"fireEvent.scroll: (\n element: HostElement,\n ...data: Array,\n) => Promise\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Invokes ",(0,r.jsx)(n.code,{children:"scroll"})," event handler on the element or parent element in the tree."]}),"\n",(0,r.jsxs)(n.h4,{id:"on-a-scrollview",children:["On a ",(0,r.jsx)(n.code,{children:"ScrollView"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#on-a-scrollview",children:"#"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:"import { ScrollView, Text } from 'react-native';\nimport { render, screen, fireEvent } from '@testing-library/react-native';\n\nconst onScrollMock = jest.fn();\nconst eventData = {\n nativeEvent: {\n contentOffset: {\n y: 200,\n },\n },\n};\n\nawait render(\n \n Content\n \n);\n\nawait fireEvent.scroll(screen.getByTestId('scroll-view'), eventData);\n"})})]})}function c(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,s.ah)(),e.components);return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(i,{...e})}):i(e)}let a=c;c.__RSPRESS_PAGE_META={},c.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fapi%2Fevents%2Ffire-event.mdx"]={toc:[{text:"`fireEvent`",id:"fire-event",depth:2},{text:"`fireEvent.press`",id:"press",depth:3},{text:"`fireEvent.changeText`",id:"change-text",depth:3},{text:"`fireEvent.scroll`",id:"scroll",depth:3},{text:"On a `ScrollView`",id:"on-a-scrollview",depth:4}],title:"Fire Event API",headingTitle:"Fire Event API",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/3012.ef6a5af6.js b/static/js/async/3012.ef6a5af6.js deleted file mode 100644 index d0b71591..00000000 --- a/static/js/async/3012.ef6a5af6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["3012"],{2931:function(e,n,r){r.r(n),r.d(n,{default:()=>a});var t=r(5893),s=r(65);function i(e){let n=Object.assign({h1:"h1",a:"a",h2:"h2",code:"code",div:"div",p:"p",pre:"pre",h3:"h3",h4:"h4"},(0,s.ah)(),e.components);return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.h1,{id:"fire-event-api",children:["Fire Event API",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#fire-event-api",children:"#"})]}),"\n",(0,t.jsxs)(n.h2,{id:"fire-event",children:[(0,t.jsx)(n.code,{children:"fireEvent"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#fire-event",children:"#"})]}),"\n",(0,t.jsxs)(n.div,{className:"rspress-directive note",children:[(0,t.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,t.jsxs)(n.div,{className:"rspress-directive-content",children:[(0,t.jsxs)(n.p,{children:["For common events like ",(0,t.jsx)(n.code,{children:"press"})," or ",(0,t.jsx)(n.code,{children:"type"})," it's recommended to use ",(0,t.jsx)(n.a,{href:"/docs/api/events/user-event",children:"User Event API"})," as it offers\nmore realistic event simulation by emitting a sequence of events with proper event objects that mimic React Native runtime behavior."]}),"\n",(0,t.jsx)(n.p,{children:"Use Fire Event for cases not supported by User Event and for triggering event handlers on composite components.\n"})]})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"function fireEvent(element: HostElement, eventName: string, ...data: unknown[]): Promise;\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"fireEvent"})," API allows you to trigger all kinds of event handlers on both host and composite components. It will try to invoke a single event handler traversing the component tree bottom-up from passed element and trying to find enabled event handler named ",(0,t.jsx)(n.code,{children:"onXxx"})," when ",(0,t.jsx)(n.code,{children:"xxx"})," is the name of the event passed."]}),"\n",(0,t.jsx)(n.p,{children:"Unlike User Event, this API does not automatically pass event object to event handler, this is responsibility of the user to construct such object."}),"\n",(0,t.jsxs)(n.p,{children:["This function uses async ",(0,t.jsx)(n.code,{children:"act"})," function internally to ensure all pending React updates are executed during event handling."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-jsx",children:"import { render, screen, fireEvent } from '@testing-library/react-native';\n\ntest('fire changeText event', async () => {\n const onEventMock = jest.fn();\n render(\n // MyComponent renders TextInput which has a placeholder 'Enter details'\n // and with `onChangeText` bound to handleChangeText\n \n );\n\n await fireEvent(screen.getByPlaceholderText('change'), 'onChangeText', 'ab');\n expect(onEventMock).toHaveBeenCalledWith('ab');\n});\n"})}),"\n",(0,t.jsxs)(n.div,{className:"rspress-directive note",children:[(0,t.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,t.jsx)(n.div,{className:"rspress-directive-content",children:(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"fireEvent"})," performs checks that should prevent events firing on disabled elements.\n"]})})]}),"\n",(0,t.jsxs)(n.p,{children:["An example using ",(0,t.jsx)(n.code,{children:"fireEvent"})," with native events that aren't already aliased by the ",(0,t.jsx)(n.code,{children:"fireEvent"})," api."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-jsx",children:"import { TextInput, View } from 'react-native';\nimport { fireEvent, render } from '@testing-library/react-native';\n\nconst onBlurMock = jest.fn();\n\nrender(\n \n \n \n);\n\n// you can omit the `on` prefix\nawait fireEvent(screen.getByPlaceholderText('my placeholder'), 'blur');\n"})}),"\n",(0,t.jsxs)(n.p,{children:["FireEvent exposes convenience methods for common events like: ",(0,t.jsx)(n.code,{children:"press"}),", ",(0,t.jsx)(n.code,{children:"changeText"}),", ",(0,t.jsx)(n.code,{children:"scroll"}),"."]}),"\n",(0,t.jsxs)(n.h3,{id:"press",children:[(0,t.jsx)(n.code,{children:"fireEvent.press"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#press",children:"#"})]}),"\n",(0,t.jsxs)(n.div,{className:"rspress-directive note",children:[(0,t.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,t.jsx)(n.div,{className:"rspress-directive-content",children:(0,t.jsxs)(n.p,{children:["It is recommended to use the User Event ",(0,t.jsx)(n.a,{href:"/docs/api/events/user-event#press",children:(0,t.jsx)(n.code,{children:"press()"})})," helper instead as it offers more realistic simulation of press interaction, including pressable support.\n"]})})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",children:"fireEvent.press: (\n element: HostElement,\n ...data: Array,\n) => Promise\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Invokes ",(0,t.jsx)(n.code,{children:"press"})," event handler on the element or parent element in the tree."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-jsx",children:"import { View, Text, TouchableOpacity } from 'react-native';\nimport { render, screen, fireEvent } from '@testing-library/react-native';\n\nconst onPressMock = jest.fn();\nconst eventData = {\n nativeEvent: {\n pageX: 20,\n pageY: 30,\n },\n};\n\nrender(\n \n \n Press me\n \n \n);\n\nawait fireEvent.press(screen.getByText('Press me'), eventData);\nexpect(onPressMock).toHaveBeenCalledWith(eventData);\n"})}),"\n",(0,t.jsxs)(n.h3,{id:"change-text",children:[(0,t.jsx)(n.code,{children:"fireEvent.changeText"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#change-text",children:"#"})]}),"\n",(0,t.jsxs)(n.div,{className:"rspress-directive note",children:[(0,t.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,t.jsx)(n.div,{className:"rspress-directive-content",children:(0,t.jsxs)(n.p,{children:["It is recommended to use the User Event ",(0,t.jsx)(n.a,{href:"/docs/api/events/user-event#type",children:(0,t.jsx)(n.code,{children:"type()"})})," helper instead as it offers more realistic simulation of text change interaction, including key-by-key typing, element focus, and other editing events.\n"]})})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",children:"fireEvent.changeText: (\n element: HostElement,\n ...data: Array,\n) => Promise\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Invokes ",(0,t.jsx)(n.code,{children:"changeText"})," event handler on the element or parent element in the tree."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-jsx",children:"import { View, TextInput } from 'react-native';\nimport { render, screen, fireEvent } from '@testing-library/react-native';\n\nconst onChangeTextMock = jest.fn();\nconst CHANGE_TEXT = 'content';\n\nrender(\n \n \n \n);\n\nawait fireEvent.changeText(screen.getByPlaceholderText('Enter data'), CHANGE_TEXT);\n"})}),"\n",(0,t.jsxs)(n.h3,{id:"scroll",children:[(0,t.jsx)(n.code,{children:"fireEvent.scroll"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#scroll",children:"#"})]}),"\n",(0,t.jsxs)(n.div,{className:"rspress-directive note",children:[(0,t.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,t.jsx)(n.div,{className:"rspress-directive-content",children:(0,t.jsxs)(n.p,{children:["Prefer using ",(0,t.jsx)(n.a,{href:"/docs/api/events/user-event#scrollto",children:(0,t.jsx)(n.code,{children:"user.scrollTo"})})," over ",(0,t.jsx)(n.code,{children:"fireEvent.scroll"})," for ",(0,t.jsx)(n.code,{children:"ScrollView"}),", ",(0,t.jsx)(n.code,{children:"FlatList"}),", and ",(0,t.jsx)(n.code,{children:"SectionList"})," components. User Event provides a more realistic event simulation based on React Native runtime behavior.\n"]})})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",children:"fireEvent.scroll: (\n element: HostElement,\n ...data: Array,\n) => Promise\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Invokes ",(0,t.jsx)(n.code,{children:"scroll"})," event handler on the element or parent element in the tree."]}),"\n",(0,t.jsxs)(n.h4,{id:"on-a-scrollview",children:["On a ",(0,t.jsx)(n.code,{children:"ScrollView"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#on-a-scrollview",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-jsx",children:"import { ScrollView, Text } from 'react-native';\nimport { render, screen, fireEvent } from '@testing-library/react-native';\n\nconst onScrollMock = jest.fn();\nconst eventData = {\n nativeEvent: {\n contentOffset: {\n y: 200,\n },\n },\n};\n\nrender(\n \n XD\n \n);\n\nawait fireEvent.scroll(screen.getByText('scroll-view'), eventData);\n"})})]})}function c(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,s.ah)(),e.components);return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(i,{...e})}):i(e)}let a=c;c.__RSPRESS_PAGE_META={},c.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fapi%2Fevents%2Ffire-event.mdx"]={toc:[{text:"`fireEvent`",id:"fire-event",depth:2},{text:"`fireEvent.press`",id:"press",depth:3},{text:"`fireEvent.changeText`",id:"change-text",depth:3},{text:"`fireEvent.scroll`",id:"scroll",depth:3},{text:"On a `ScrollView`",id:"on-a-scrollview",depth:4}],title:"Fire Event API",headingTitle:"Fire Event API",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/3014.29020a96.js b/static/js/async/3014.29020a96.js new file mode 100644 index 00000000..9d3299f7 --- /dev/null +++ b/static/js/async/3014.29020a96.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["3014"],{6415:function(e,r,n){n.r(r),n.d(r,{default:()=>c});var t=n(5893),s=n(65);function i(e){let r=Object.assign({h1:"h1",code:"code",a:"a",h2:"h2",pre:"pre",p:"p",blockquote:"blockquote",h3:"h3",h4:"h4",div:"div"},(0,s.ah)(),e.components);return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(r.h1,{id:"render-api",children:[(0,t.jsx)(r.code,{children:"render"})," API",(0,t.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#render-api",children:"#"})]}),"\n",(0,t.jsxs)(r.h2,{id:"render",children:[(0,t.jsx)(r.code,{children:"render"})," function",(0,t.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#render",children:"#"})]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ts",children:"async function render(\n element: React.ReactElement,\n options?: RenderOptions\n): Promise;\n"})}),"\n",(0,t.jsxs)(r.p,{children:["The ",(0,t.jsx)(r.code,{children:"render"})," function is the entry point for writing React Native Testing Library tests. It deeply renders the given React element and returns helpers to query the output components' structure. This function is async by default and uses async ",(0,t.jsx)(r.code,{children:"act"})," internally to ensure all pending React updates are executed during rendering, making it compatible with async React features like ",(0,t.jsx)(r.code,{children:"Suspense"})," boundary or ",(0,t.jsx)(r.code,{children:"use()"})," hook."]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-jsx",children:"import { render, screen } from '@testing-library/react-native';\n\ntest('basic test', async () => {\n await render();\n expect(screen.getAllByRole('button', { name: 'start' })).toBeOnTheScreen();\n});\n"})}),"\n",(0,t.jsxs)(r.blockquote,{children:["\n",(0,t.jsxs)(r.p,{children:["When using React context providers, like Redux Provider, you'll likely want to wrap rendered component with them. In such cases, it's convenient to create your own custom\xa0",(0,t.jsx)(r.code,{children:"render"}),"\xa0method. ",(0,t.jsx)(r.a,{href:"https://testing-library.com/docs/react-testing-library/setup#custom-render",target:"_blank",rel:"noopener noreferrer",children:"Follow this great guide on how to set this up"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(r.h3,{id:"options",children:["Options",(0,t.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#options",children:"#"})]}),"\n",(0,t.jsxs)(r.p,{children:["The behavior of the ",(0,t.jsx)(r.code,{children:"render"})," method can be customized by passing various options as a second argument of the ",(0,t.jsx)(r.code,{children:"RenderOptions"})," type:"]}),"\n",(0,t.jsxs)(r.h4,{id:"wrapper",children:[(0,t.jsx)(r.code,{children:"wrapper"}),(0,t.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#wrapper",children:"#"})]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ts",children:"wrapper?: React.ComponentType,\n"})}),"\n",(0,t.jsxs)(r.p,{children:["This option allows you to wrap the tested component, passed as the first option to the\xa0",(0,t.jsx)(r.code,{children:"render()"}),"\xa0function, in an additional wrapper component. This is useful for creating reusable custom render functions for common React Context providers."]}),"\n",(0,t.jsxs)(r.h4,{id:"create-node-mock",children:[(0,t.jsx)(r.code,{children:"createNodeMock"}),(0,t.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#create-node-mock",children:"#"})]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ts",children:"createNodeMock?: (element: React.ReactElement) => object,\n"})}),"\n",(0,t.jsxs)(r.p,{children:["This option allows you to pass ",(0,t.jsx)(r.code,{children:"createNodeMock"})," option to the renderer's ",(0,t.jsx)(r.code,{children:"create()"})," method in order to allow for custom mock refs. This option is passed through to ",(0,t.jsx)(r.a,{href:"https://github.com/mdjastrzebski/test-renderer",target:"_blank",rel:"noopener noreferrer",children:"Test Renderer"}),"."]}),"\n",(0,t.jsxs)(r.div,{className:"rspress-directive note",children:[(0,t.jsx)(r.div,{className:"rspress-directive-title",children:"Text string validation"}),(0,t.jsxs)(r.div,{className:"rspress-directive-content",children:["\n",(0,t.jsxs)(r.p,{children:["Test Renderer automatically enforces React Native's requirement that text strings must be rendered within a ",(0,t.jsx)(r.code,{children:""})," component. If you try to render a ",(0,t.jsx)(r.code,{children:"string"})," value under components other than ",(0,t.jsx)(r.code,{children:""})," (e.g., under ",(0,t.jsx)(r.code,{children:""}),"), it will throw an ",(0,t.jsx)(r.code,{children:"Invariant Violation: Text strings must be rendered within a component"})," error, matching React Native's runtime behavior."]}),"\n",(0,t.jsx)(r.p,{children:"This validation is always enabled and cannot be disabled, ensuring your tests accurately reflect how your code will behave in production."}),"\n"]})]}),"\n",(0,t.jsxs)(r.h3,{id:"result",children:["Result",(0,t.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#result",children:"#"})]}),"\n",(0,t.jsxs)(r.p,{children:["The ",(0,t.jsx)(r.code,{children:"render"})," function returns a promise that resolves to the same queries and utilities as the ",(0,t.jsx)(r.a,{href:"/docs/api/screen",children:(0,t.jsx)(r.code,{children:"screen"})})," object. We recommend using the ",(0,t.jsx)(r.code,{children:"screen"})," object for queries and the lifecycle methods from the render result when needed."]}),"\n",(0,t.jsxs)(r.p,{children:["See ",(0,t.jsx)(r.a,{href:"https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#not-using-screen",target:"_blank",rel:"noopener noreferrer",children:"this article"})," from Kent C. Dodds for more details."]}),"\n",(0,t.jsxs)(r.div,{className:"rspress-directive note",children:[(0,t.jsx)(r.div,{className:"rspress-directive-title",children:"Type information"}),(0,t.jsxs)(r.div,{className:"rspress-directive-content",children:["\n",(0,t.jsxs)(r.p,{children:["Query results and element references use the ",(0,t.jsx)(r.code,{children:"HostElement"})," type from ",(0,t.jsx)(r.a,{href:"https://github.com/mdjastrzebski/test-renderer",target:"_blank",rel:"noopener noreferrer",children:"Test Renderer"}),". If you need to type element variables, you can import this type directly from ",(0,t.jsx)(r.code,{children:"test-renderer"}),"."]}),"\n"]})]})]})}function d(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:r}=Object.assign({},(0,s.ah)(),e.components);return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(i,{...e})}):i(e)}let c=d;d.__RSPRESS_PAGE_META={},d.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fapi%2Frender.mdx"]={toc:[{text:"`render` function",id:"render",depth:2},{text:"Options",id:"options",depth:3},{text:"`wrapper`",id:"wrapper",depth:4},{text:"`createNodeMock`",id:"create-node-mock",depth:4},{text:"Result",id:"result",depth:3}],title:"`render` API",headingTitle:"`render` API",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/3014.b9747eed.js b/static/js/async/3014.b9747eed.js deleted file mode 100644 index c2625643..00000000 --- a/static/js/async/3014.b9747eed.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["3014"],{6415:function(e,r,n){n.r(r),n.d(r,{default:()=>d});var t=n(5893),s=n(65);function i(e){let r=Object.assign({h1:"h1",code:"code",a:"a",h2:"h2",pre:"pre",p:"p",blockquote:"blockquote",h3:"h3",h4:"h4",div:"div"},(0,s.ah)(),e.components);return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(r.h1,{id:"render-api",children:[(0,t.jsx)(r.code,{children:"render"})," API",(0,t.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#render-api",children:"#"})]}),"\n",(0,t.jsxs)(r.h2,{id:"render",children:[(0,t.jsx)(r.code,{children:"render"})," function",(0,t.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#render",children:"#"})]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-jsx",children:"async function render(\n component: React.Element,\n options?: RenderOptions\n): Promise\n"})}),"\n",(0,t.jsxs)(r.p,{children:["The ",(0,t.jsx)(r.code,{children:"render"})," function is the entry point for writing React Native Testing Library tests. It deeply renders the given React element and returns helpers to query the output components' structure. This function is async by default and uses async ",(0,t.jsx)(r.code,{children:"act"})," internally to ensure all pending React updates are executed during rendering, making it compatible with React 19, React Suspense, and ",(0,t.jsx)(r.code,{children:"React.use()"}),"."]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-jsx",children:"import { render, screen } from '@testing-library/react-native';\n\ntest('basic test', async () => {\n await render();\n expect(screen.getAllByRole('button', { name: 'start' })).toBeOnTheScreen();\n});\n"})}),"\n",(0,t.jsxs)(r.blockquote,{children:["\n",(0,t.jsxs)(r.p,{children:["When using React context providers, like Redux Provider, you'll likely want to wrap rendered component with them. In such cases, it's convenient to create your own custom\xa0",(0,t.jsx)(r.code,{children:"render"}),"\xa0method. ",(0,t.jsx)(r.a,{href:"https://testing-library.com/docs/react-testing-library/setup#custom-render",target:"_blank",rel:"noopener noreferrer",children:"Follow this great guide on how to set this up"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(r.h3,{id:"options",children:["Options",(0,t.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#options",children:"#"})]}),"\n",(0,t.jsxs)(r.p,{children:["The behavior of the ",(0,t.jsx)(r.code,{children:"render"})," method can be customized by passing various options as a second argument of the ",(0,t.jsx)(r.code,{children:"RenderOptions"})," type:"]}),"\n",(0,t.jsxs)(r.h4,{id:"wrapper",children:[(0,t.jsx)(r.code,{children:"wrapper"}),(0,t.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#wrapper",children:"#"})]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ts",children:"wrapper?: React.ComponentType,\n"})}),"\n",(0,t.jsxs)(r.p,{children:["This option allows you to wrap the tested component, passed as the first option to the\xa0",(0,t.jsx)(r.code,{children:"render()"}),"\xa0function, in an additional wrapper component. This is useful for creating reusable custom render functions for common React Context providers."]}),"\n",(0,t.jsxs)(r.h4,{id:"concurrent-root",children:[(0,t.jsx)(r.code,{children:"concurrentRoot"}),(0,t.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#concurrent-root",children:"#"})]}),"\n",(0,t.jsxs)(r.p,{children:["Set to ",(0,t.jsx)(r.code,{children:"false"})," to disable concurrent rendering.\nOtherwise, ",(0,t.jsx)(r.code,{children:"render"})," will default to using concurrent rendering used in the React Native New Architecture."]}),"\n",(0,t.jsxs)(r.h4,{id:"create-node-mock",children:[(0,t.jsx)(r.code,{children:"createNodeMock"}),(0,t.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#create-node-mock",children:"#"})]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ts",children:"createNodeMock?: (element: React.Element) => unknown,\n"})}),"\n",(0,t.jsxs)(r.p,{children:["This option allows you to pass ",(0,t.jsx)(r.code,{children:"createNodeMock"})," option to the renderer's ",(0,t.jsx)(r.code,{children:"create()"})," method in order to allow for custom mock refs. This option is passed through to ",(0,t.jsx)(r.a,{href:"https://github.com/mdjastrzebski/test-renderer",target:"_blank",rel:"noopener noreferrer",children:"Test Renderer"}),"."]}),"\n",(0,t.jsxs)(r.div,{className:"rspress-directive note",children:[(0,t.jsx)(r.div,{className:"rspress-directive-title",children:"Text string validation"}),(0,t.jsxs)(r.div,{className:"rspress-directive-content",children:["\n",(0,t.jsxs)(r.p,{children:["Test Renderer automatically enforces React Native's requirement that text strings must be rendered within a ",(0,t.jsx)(r.code,{children:""})," component. If you try to render a ",(0,t.jsx)(r.code,{children:"string"})," value under components other than ",(0,t.jsx)(r.code,{children:""})," (e.g., under ",(0,t.jsx)(r.code,{children:""}),"), it will throw an ",(0,t.jsx)(r.code,{children:"Invariant Violation: Text strings must be rendered within a component"})," error, matching React Native's runtime behavior."]}),"\n",(0,t.jsx)(r.p,{children:"This validation is always enabled and cannot be disabled, ensuring your tests accurately reflect how your code will behave in production."}),"\n"]})]}),"\n",(0,t.jsxs)(r.h3,{id:"result",children:["Result",(0,t.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#result",children:"#"})]}),"\n",(0,t.jsxs)(r.p,{children:["The ",(0,t.jsx)(r.code,{children:"render"})," function returns a promise that resolves to the same queries and utilities as the ",(0,t.jsx)(r.a,{href:"/docs/api/screen",children:(0,t.jsx)(r.code,{children:"screen"})})," object. We recommend using the ",(0,t.jsx)(r.code,{children:"screen"})," object for queries and the lifecycle methods from the render result when needed."]}),"\n",(0,t.jsxs)(r.p,{children:["See ",(0,t.jsx)(r.a,{href:"https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#not-using-screen",target:"_blank",rel:"noopener noreferrer",children:"this article"})," from Kent C. Dodds for more details."]}),"\n",(0,t.jsxs)(r.div,{className:"rspress-directive warning",children:[(0,t.jsx)(r.div,{className:"rspress-directive-title",children:"Async lifecycle methods"}),(0,t.jsxs)(r.div,{className:"rspress-directive-content",children:["\n",(0,t.jsxs)(r.p,{children:["When using ",(0,t.jsx)(r.code,{children:"render"}),", the lifecycle methods ",(0,t.jsx)(r.code,{children:"rerender"})," and ",(0,t.jsx)(r.code,{children:"unmount"})," are async and must be awaited."]}),"\n"]})]})]})}function c(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:r}=Object.assign({},(0,s.ah)(),e.components);return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(i,{...e})}):i(e)}let d=c;c.__RSPRESS_PAGE_META={},c.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fapi%2Frender.mdx"]={toc:[{text:"`render` function",id:"render",depth:2},{text:"Options",id:"options",depth:3},{text:"`wrapper`",id:"wrapper",depth:4},{text:"`concurrentRoot`",id:"concurrent-root",depth:4},{text:"`createNodeMock`",id:"create-node-mock",depth:4},{text:"Result",id:"result",depth:3}],title:"`render` API",headingTitle:"`render` API",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/3241.a9f68d86.js b/static/js/async/3241.a9f68d86.js new file mode 100644 index 00000000..8a50b5b3 --- /dev/null +++ b/static/js/async/3241.a9f68d86.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["3241"],{9546:function(e,n,r){r.r(n),r.d(n,{default:()=>c});var s=r(5893),t=r(65),d=r(5552);function i(e){let n=Object.assign({h1:"h1",a:"a",p:"p",h2:"h2",strong:"strong",ul:"ul",li:"li",code:"code",div:"div",h3:"h3",table:"table",thead:"thead",tr:"tr",th:"th",tbody:"tbody",td:"td",h4:"h4",h5:"h5",pre:"pre"},(0,t.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.h1,{id:"migration-to-14x",children:["Migration to 14.x",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#migration-to-14x",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"This guide describes the migration to React Native Testing Library version 14 from version 13.x."}),"\n",(0,s.jsxs)(n.h2,{id:"overview",children:["Overview",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#overview",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["RNTL v14 is a major release that ",(0,s.jsx)(n.strong,{children:"drops support for React 18"})," and fully embraces React 19's async-first paradigm. Key changes include:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"React 19+ required"}),": Minimum supported versions are React 19.0.0 and React Native 0.78+"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Async APIs by default"}),": ",(0,s.jsx)(n.code,{children:"render"}),", ",(0,s.jsx)(n.code,{children:"renderHook"}),", ",(0,s.jsx)(n.code,{children:"fireEvent"}),", and ",(0,s.jsx)(n.code,{children:"act"})," are now async"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"New renderer"}),": Switched from deprecated ",(0,s.jsx)(n.a,{href:"https://reactjs.org/docs/test-renderer.html",target:"_blank",rel:"noopener noreferrer",children:"React Test Renderer"})," to ",(0,s.jsx)(n.a,{href:"https://github.com/mdjastrzebski/test-renderer",target:"_blank",rel:"noopener noreferrer",children:"Test Renderer"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"API cleanup"}),": Removed deprecated APIs (",(0,s.jsx)(n.code,{children:"update"}),", ",(0,s.jsx)(n.code,{children:"getQueriesForElement"}),", ",(0,s.jsx)(n.code,{children:"UNSAFE_root"}),", ",(0,s.jsx)(n.code,{children:"concurrentRoot"})," option)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsxs)(n.strong,{children:["Safe ",(0,s.jsx)(n.code,{children:"container"})," API"]}),": Reintroduced ",(0,s.jsx)(n.code,{children:"container"})," which is now safe to use"]}),"\n"]}),"\n",(0,s.jsxs)(n.div,{className:"rspress-directive info",children:[(0,s.jsx)(n.div,{className:"rspress-directive-title",children:"React 18 Users"}),(0,s.jsxs)(n.div,{className:"rspress-directive-content",children:["\n",(0,s.jsx)(n.p,{children:"If you need to support React 18, please continue using RNTL v13.x."}),"\n"]})]}),"\n",(0,s.jsxs)(n.h2,{id:"quick-migration",children:["Quick Migration",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#quick-migration",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"We provide codemods to automate most of the migration:"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Step 1: Update dependencies"})}),"\n",(0,s.jsx)(d.SU,{command:{npm:"npx codemod@latest rntl-v14-update-deps --target .\nnpm install",yarn:"yarn dlx codemod@latest rntl-v14-update-deps --target .\nyarn install",pnpm:"pnpm dlx codemod@latest rntl-v14-update-deps --target .\npnpm install",bun:"bunx codemod@latest rntl-v14-update-deps --target .\nbun install"}}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Step 2: Update test code to async"})}),"\n",(0,s.jsx)(d.SU,{command:{npm:"npx codemod@latest rntl-v14-async-functions --target ./src",yarn:"yarn dlx codemod@latest rntl-v14-async-functions --target ./src",pnpm:"pnpm dlx codemod@latest rntl-v14-async-functions --target ./src",bun:"bunx codemod@latest rntl-v14-async-functions --target ./src"}}),"\n",(0,s.jsx)(n.p,{children:"After running the codemods, review the changes and run your tests."}),"\n",(0,s.jsxs)(n.h2,{id:"breaking-changes",children:["Breaking Changes",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#breaking-changes",children:"#"})]}),"\n",(0,s.jsxs)(n.h3,{id:"supported-react-and-react-native-versions",children:["Supported React and React Native versions",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#supported-react-and-react-native-versions",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"This version requires React 19+ and React Native 0.78+."})," If you need to support React 18, please use the latest v13.x version."]}),"\n",(0,s.jsxs)(n.table,{children:["\n",(0,s.jsxs)(n.thead,{children:["\n",(0,s.jsxs)(n.tr,{children:["\n",(0,s.jsx)(n.th,{children:"RNTL Version"}),"\n",(0,s.jsx)(n.th,{children:"React Version"}),"\n",(0,s.jsx)(n.th,{children:"React Native Version"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.tbody,{children:["\n",(0,s.jsxs)(n.tr,{children:["\n",(0,s.jsx)(n.td,{children:"v14.x"}),"\n",(0,s.jsx)(n.td,{children:">= 19.0.0"}),"\n",(0,s.jsx)(n.td,{children:">= 0.78"}),"\n"]}),"\n",(0,s.jsxs)(n.tr,{children:["\n",(0,s.jsx)(n.td,{children:"v13.x"}),"\n",(0,s.jsx)(n.td,{children:">= 18.0.0"}),"\n",(0,s.jsx)(n.td,{children:">= 0.71"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.h3,{id:"test-renderer-replaces-react-test-renderer",children:["Test Renderer replaces React Test Renderer",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#test-renderer-replaces-react-test-renderer",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["In v14, React Native Testing Library now uses ",(0,s.jsx)(n.a,{href:"https://github.com/mdjastrzebski/test-renderer",target:"_blank",rel:"noopener noreferrer",children:"Test Renderer"})," instead of the deprecated ",(0,s.jsx)(n.a,{href:"https://reactjs.org/docs/test-renderer.html",target:"_blank",rel:"noopener noreferrer",children:"React Test Renderer"}),". Test Renderer is a modern, actively maintained alternative that provides better compatibility with React 19 and improved type safety."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"What changed:"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"The underlying renderer has been switched from React Test Renderer to Test Renderer"}),"\n",(0,s.jsx)(n.li,{children:"This change is mostly internal and should not require code changes in most cases"}),"\n",(0,s.jsxs)(n.li,{children:["Type definitions have been updated to use ",(0,s.jsx)(n.a,{href:"https://github.com/mdjastrzebski/test-renderer#hostelement",target:"_blank",rel:"noopener noreferrer",children:(0,s.jsx)(n.code,{children:"HostElement"})})," from Test Renderer instead of ",(0,s.jsx)(n.code,{children:"ReactTestInstance"})]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Migration:"})}),"\n",(0,s.jsxs)(n.h4,{id:"1-update-dependencies",children:["1. Update dependencies",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#1-update-dependencies",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"Run codemod for updating dependencies:"}),"\n",(0,s.jsx)(d.SU,{command:{npm:"npx codemod@latest rntl-v14-update-deps\nnpm install",yarn:"yarn dlx codemod@latest rntl-v14-update-deps\nyarn install",pnpm:"pnpm dlx codemod@latest rntl-v14-update-deps\npnpm install",bun:"bunx codemod@latest rntl-v14-update-deps\nbun install"}}),"\n",(0,s.jsxs)(n.h5,{id:"manual-changes",children:["Manual changes",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#manual-changes",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"Remove React Test Renderer and its type definitions from your dev dependencies, and add Test Renderer:"}),"\n",(0,s.jsx)(d.SU,{command:{npm:"npm uninstall react-test-renderer @types/react-test-renderer\nnpm install -D test-renderer@^0.14.0",yarn:"yarn remove react-test-renderer @types/react-test-renderer\nyarn add -D test-renderer@^0.14.0",pnpm:"pnpm remove react-test-renderer @types/react-test-renderer\npnpm add -D test-renderer@^0.14.0",bun:"bun remove react-test-renderer @types/react-test-renderer\nbun add -D test-renderer@^0.14.0"}}),"\n",(0,s.jsxs)(n.h4,{id:"2-update-type-imports-if-needed",children:["2. Update type imports (if needed)",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#2-update-type-imports-if-needed",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"If you were directly importing types from React Test Renderer, you may need to update your imports:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"// Before (v13)\nimport type { ReactTestInstance } from 'react-test-renderer';\n\n// After (v14)\nimport type { HostElement } from 'test-renderer';\n"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Note:"})," Most users won't need to update type imports, as React Native Testing Library now exports the necessary types directly."]}),"\n",(0,s.jsxs)(n.p,{children:["For more details, see the ",(0,s.jsx)(n.a,{href:"https://github.com/mdjastrzebski/test-renderer",target:"_blank",rel:"noopener noreferrer",children:"Test Renderer documentation"}),"."]}),"\n",(0,s.jsxs)(n.h3,{id:"async-apis-by-default",children:["Async APIs by Default",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#async-apis-by-default",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"With React 18 support dropped, RNTL v14 fully embraces React 19's async rendering model. The following functions are now async by default:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"render()"})," β†’ returns ",(0,s.jsx)(n.code,{children:"Promise"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"rerender()"})," and ",(0,s.jsx)(n.code,{children:"unmount()"})," β†’ return ",(0,s.jsx)(n.code,{children:"Promise"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"renderHook()"})," β†’ returns ",(0,s.jsx)(n.code,{children:"Promise"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"fireEvent()"})," and helpers (",(0,s.jsx)(n.code,{children:"press"}),", ",(0,s.jsx)(n.code,{children:"changeText"}),", ",(0,s.jsx)(n.code,{children:"scroll"}),") β†’ return ",(0,s.jsx)(n.code,{children:"Promise"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"act()"})," β†’ always returns ",(0,s.jsx)(n.code,{children:"Promise"})]}),"\n"]}),"\n",(0,s.jsxs)(n.div,{className:"rspress-directive tip",children:[(0,s.jsx)(n.div,{className:"rspress-directive-title",children:"Already using async APIs?"}),(0,s.jsxs)(n.div,{className:"rspress-directive-content",children:["\n",(0,s.jsxs)(n.p,{children:["If you adopted the async APIs introduced in RNTL v13.3 (",(0,s.jsx)(n.code,{children:"renderAsync"}),", ",(0,s.jsx)(n.code,{children:"fireEventAsync"}),", ",(0,s.jsx)(n.code,{children:"renderHookAsync"}),"), simply rename them to their non-async counterparts (",(0,s.jsx)(n.code,{children:"render"}),", ",(0,s.jsx)(n.code,{children:"fireEvent"}),", ",(0,s.jsx)(n.code,{children:"renderHook"}),"). The async versions have been removed as the standard APIs are now async by default."]}),"\n"]})]}),"\n",(0,s.jsxs)(n.h4,{id:"render-async-default",children:[(0,s.jsx)(n.code,{children:"render"})," is now async",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#render-async-default",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["In v14, ",(0,s.jsx)(n.code,{children:"render"})," is now async by default and returns a Promise. This change enables proper support for async React features like ",(0,s.jsx)(n.code,{children:"Suspense"})," boundary or ",(0,s.jsx)(n.code,{children:"use()"})," hook."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Before (v13):"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { render, screen } from '@testing-library/react-native';\n\nit('should render component', () => {\n render();\n expect(screen.getByText('Hello')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"After (v14):"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { render, screen } from '@testing-library/react-native';\n\nit('should render component', async () => {\n await render();\n expect(screen.getByText('Hello')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:["For more details, see the ",(0,s.jsxs)(n.a,{href:"/docs/api/render",children:[(0,s.jsx)(n.code,{children:"render"})," API documentation"]}),"."]}),"\n",(0,s.jsxs)(n.h4,{id:"renderhook-is-now-async",children:[(0,s.jsx)(n.code,{children:"renderHook"})," is now async",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#renderhook-is-now-async",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["In v14, ",(0,s.jsx)(n.code,{children:"renderHook"})," is now async by default and returns a Promise."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Before (v13):"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { renderHook } from '@testing-library/react-native';\n\nit('should test hook', () => {\n const { result, rerender } = renderHook(() => useMyHook());\n\n rerender(newProps);\n unmount();\n});\n"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"After (v14):"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { renderHook } from '@testing-library/react-native';\n\nit('should test hook', async () => {\n const { result, rerender } = await renderHook(() => useMyHook());\n\n await rerender(newProps);\n await unmount();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:["For more details, see the ",(0,s.jsxs)(n.a,{href:"/docs/api/misc/render-hook",children:[(0,s.jsx)(n.code,{children:"renderHook"})," API documentation"]}),"."]}),"\n",(0,s.jsxs)(n.h4,{id:"fireevent-is-now-async",children:[(0,s.jsx)(n.code,{children:"fireEvent"})," is now async",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#fireevent-is-now-async",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["In v14, ",(0,s.jsx)(n.code,{children:"fireEvent"})," and its helpers (",(0,s.jsx)(n.code,{children:"press"}),", ",(0,s.jsx)(n.code,{children:"changeText"}),", ",(0,s.jsx)(n.code,{children:"scroll"}),") are now async by default and return a Promise."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Before (v13):"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { fireEvent, screen } from '@testing-library/react-native';\n\nit('should press button', () => {\n render();\n fireEvent.press(screen.getByText('Press me'));\n expect(onPress).toHaveBeenCalled();\n});\n"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"After (v14):"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { fireEvent, screen } from '@testing-library/react-native';\n\nit('should press button', async () => {\n await render();\n await fireEvent.press(screen.getByText('Press me'));\n expect(onPress).toHaveBeenCalled();\n});\n"})}),"\n",(0,s.jsxs)(n.h4,{id:"act-is-now-async",children:[(0,s.jsx)(n.code,{children:"act"})," is now async",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#act-is-now-async",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["In v14, ",(0,s.jsx)(n.code,{children:"act"})," is now async by default and always returns a Promise. You should always ",(0,s.jsx)(n.code,{children:"await"})," the result of ",(0,s.jsx)(n.code,{children:"act()"}),"."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"What changed:"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"act"})," now always returns a ",(0,s.jsx)(n.code,{children:"Promise"})," instead of ",(0,s.jsx)(n.code,{children:"T | Thenable"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"act"})," should always be awaited"]}),"\n",(0,s.jsx)(n.li,{children:"The API is more consistent and predictable"}),"\n"]}),"\n",(0,s.jsxs)(n.div,{className:"rspress-directive note",children:[(0,s.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,s.jsxs)(n.div,{className:"rspress-directive-content",children:["\n",(0,s.jsxs)(n.p,{children:["The transition to async ",(0,s.jsx)(n.code,{children:"act"})," may prevent testing very short transient states, as awaiting ",(0,s.jsx)(n.code,{children:"act"})," will flush all pending updates before returning."]}),"\n"]})]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Before (v13):"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { act } from '@testing-library/react-native';\n\nit('should update state', () => {\n act(() => {\n setState('new value');\n });\n expect(state).toBe('new value');\n});\n"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"After (v14):"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { act } from '@testing-library/react-native';\n\nit('should update state', async () => {\n await act(() => {\n setState('new value');\n });\n expect(state).toBe('new value');\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Note"}),": Even if your callback is synchronous, you should still use ",(0,s.jsx)(n.code,{children:"await act(...)"})," as ",(0,s.jsx)(n.code,{children:"act"})," now always returns a Promise."]}),"\n",(0,s.jsxs)(n.p,{children:["For more details, see the ",(0,s.jsxs)(n.a,{href:"/docs/api/misc/other#act",children:[(0,s.jsx)(n.code,{children:"act"})," API documentation"]}),"."]}),"\n",(0,s.jsxs)(n.h4,{id:"benefits-of-async-apis",children:["Benefits of Async APIs",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#benefits-of-async-apis",children:"#"})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Suspense support"}),": Properly handles ",(0,s.jsx)(n.code,{children:"Suspense"})," boundaries and ",(0,s.jsx)(n.code,{children:"use()"})," hook"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Better timing"}),": Ensures all pending React updates are executed before assertions"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Simpler mental model"}),": All rendering operations are consistently async"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Future-proof"}),": Aligns with React's direction toward async rendering"]}),"\n"]}),"\n",(0,s.jsxs)(n.h3,{id:"removed-apis",children:["Removed APIs",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#removed-apis",children:"#"})]}),"\n",(0,s.jsxs)(n.h4,{id:"update-alias-removed",children:[(0,s.jsx)(n.code,{children:"update"})," alias removed",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#update-alias-removed",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"update"})," alias for ",(0,s.jsx)(n.code,{children:"rerender"})," has been removed. Use ",(0,s.jsx)(n.code,{children:"rerender"})," instead:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"// Before (v13)\nscreen.update();\nconst { update } = render();\nupdate();\n\n// After (v14)\nawait screen.rerender();\nconst { rerender } = await render();\nawait rerender();\n"})}),"\n",(0,s.jsxs)(n.h4,{id:"getqueriesforelement-export-removed",children:[(0,s.jsx)(n.code,{children:"getQueriesForElement"})," export removed",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#getqueriesforelement-export-removed",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"getQueriesForElement"})," export alias for ",(0,s.jsx)(n.code,{children:"within"})," has been removed. Use ",(0,s.jsx)(n.code,{children:"within"})," instead:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"// Before (v13)\nimport { getQueriesForElement } from '@testing-library/react-native';\n\nconst queries = getQueriesForElement(element);\n\n// After (v14)\nimport { within } from '@testing-library/react-native';\n\nconst queries = within(element);\n"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Note:"})," ",(0,s.jsx)(n.code,{children:"getQueriesForElement"})," was just an alias for ",(0,s.jsx)(n.code,{children:"within"}),", so the functionality is identical - only the import needs to change."]}),"\n",(0,s.jsxs)(n.h4,{id:"unsafe_root-removed",children:[(0,s.jsx)(n.code,{children:"UNSAFE_root"})," removed",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#unsafe_root-removed",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"UNSAFE_root"})," has been removed. Use ",(0,s.jsx)(n.code,{children:"container"})," to access the pseudo-element container, or ",(0,s.jsx)(n.code,{children:"root"})," to access the first rendered host element:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"// Before (v13)\nconst unsafeRoot = screen.UNSAFE_root;\n\n// After (v14)\nconst container = screen.container; // pseudo-element container\nconst root = screen.root; // first rendered host element\n"})}),"\n",(0,s.jsxs)(n.h4,{id:"legacy-unsafe_-queries-removed",children:["Legacy ",(0,s.jsx)(n.code,{children:"UNSAFE_*"})," queries removed",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#legacy-unsafe_-queries-removed",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["The legacy ",(0,s.jsx)(n.code,{children:"UNSAFE_getAllByType"}),", ",(0,s.jsx)(n.code,{children:"UNSAFE_getByType"}),", ",(0,s.jsx)(n.code,{children:"UNSAFE_getAllByProps"}),", and ",(0,s.jsx)(n.code,{children:"UNSAFE_getByProps"})," queries have been removed. These queries could return composite (user-defined) components, which is no longer supported with ",(0,s.jsx)(n.a,{href:"https://github.com/mdjastrzebski/test-renderer",target:"_blank",rel:"noopener noreferrer",children:"Test Renderer"})," as it only renders host elements."]}),"\n",(0,s.jsxs)(n.p,{children:["If you were using these legacy queries, you should refactor your tests to use the standard queries (",(0,s.jsx)(n.code,{children:"getByRole"}),", ",(0,s.jsx)(n.code,{children:"getByText"}),", ",(0,s.jsx)(n.code,{children:"getByTestId"}),", etc.) which target host elements."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"// Before (v13)\nconst buttons = screen.UNSAFE_getAllByType(Button);\nconst input = screen.UNSAFE_getByProps({ placeholder: 'Enter text' });\n\n// After (v14)\nconst buttons = screen.getAllByRole('button');\nconst input = screen.getByPlaceholderText('Enter text');\n"})}),"\n",(0,s.jsxs)(n.h4,{id:"concurrentroot-option-removed",children:[(0,s.jsx)(n.code,{children:"concurrentRoot"})," option removed",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#concurrentroot-option-removed",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"concurrentRoot"})," option has been removed from both ",(0,s.jsx)(n.code,{children:"render"})," options and ",(0,s.jsx)(n.code,{children:"configure"})," function. In v14, concurrent rendering is always enabled by default, as it is the standard rendering mode for React 19 and React Native's New Architecture."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"// Before (v13)\nrender(, { concurrentRoot: true }); // Enable concurrent mode\nrender(, { concurrentRoot: false }); // Disable concurrent mode\nconfigure({ concurrentRoot: false }); // Disable globally\n\n// After (v14)\nawait render(); // Always uses concurrent rendering\n"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Migration:"})," Simply remove any ",(0,s.jsx)(n.code,{children:"concurrentRoot"})," options from your ",(0,s.jsx)(n.code,{children:"render"})," calls and ",(0,s.jsx)(n.code,{children:"configure"})," function. If you were explicitly setting ",(0,s.jsx)(n.code,{children:"concurrentRoot: true"}),", no changes are needed beyond removing the option. If you were setting ",(0,s.jsx)(n.code,{children:"concurrentRoot: false"})," to disable concurrent rendering, this is no longer supported in v14."]}),"\n",(0,s.jsxs)(n.h3,{id:"container-api-reintroduced",children:[(0,s.jsx)(n.code,{children:"container"})," API reintroduced",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#container-api-reintroduced",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["In v14, the ",(0,s.jsx)(n.code,{children:"container"})," API has been reintroduced and is now safe to use. Previously, ",(0,s.jsx)(n.code,{children:"container"})," was renamed to ",(0,s.jsx)(n.code,{children:"UNSAFE_root"})," in v12 due to behavioral differences from React Testing Library's ",(0,s.jsx)(n.code,{children:"container"}),". In v14, ",(0,s.jsx)(n.code,{children:"container"})," now returns a pseudo-element container whose children are the elements you asked to render, making it safe and consistent with React Testing Library's behavior."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"What changed:"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"screen.container"})," is now available and safe to use"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"container"})," returns a pseudo-element container from Test Renderer"]}),"\n",(0,s.jsx)(n.li,{children:"The container's children are the elements you rendered"}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"UNSAFE_root"})," has been removed"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Before (v13):"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { render, screen } from '@testing-library/react-native';\n\nit('should access root', () => {\n render();\n // UNSAFE_root was the only way to access the container\n const root = screen.UNSAFE_root;\n});\n"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"After (v14):"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { render, screen } from '@testing-library/react-native';\n\nit('should access container', async () => {\n await render();\n // container is now safe and available\n const container = screen.container;\n // root is the first child of container\n const root = screen.root;\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:["For more details, see the ",(0,s.jsxs)(n.a,{href:"/docs/api/screen#container",children:[(0,s.jsx)(n.code,{children:"screen"})," API documentation"]}),"."]}),"\n",(0,s.jsxs)(n.h3,{id:"text-string-validation-enforced-by-default",children:["Text string validation enforced by default",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#text-string-validation-enforced-by-default",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["In v14, Test Renderer automatically enforces React Native's requirement that text strings must be rendered within a ",(0,s.jsx)(n.code,{children:""})," component. This means the ",(0,s.jsx)(n.code,{children:"unstable_validateStringsRenderedWithinText"})," option has been removed from ",(0,s.jsx)(n.code,{children:"RenderOptions"}),", as this validation is now always enabled."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"What changed:"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Text string validation is now always enabled and cannot be disabled"}),"\n",(0,s.jsxs)(n.li,{children:["The ",(0,s.jsx)(n.code,{children:"unstable_validateStringsRenderedWithinText"})," option has been removed"]}),"\n",(0,s.jsxs)(n.li,{children:["Tests will now throw ",(0,s.jsx)(n.code,{children:"Invariant Violation: Text strings must be rendered within a component"})," errors when attempting to render strings outside of ",(0,s.jsx)(n.code,{children:""})," components, matching React Native's runtime behavior"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Migration:"})}),"\n",(0,s.jsxs)(n.p,{children:["If you were using ",(0,s.jsx)(n.code,{children:"unstable_validateStringsRenderedWithinText: true"})," in your render options, you can simply remove this option as the validation is now always enabled:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"// Before (v13)\nrender(, {\n unstable_validateStringsRenderedWithinText: true,\n});\n\n// After (v14)\nawait render();\n// Validation is now always enabled\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If you were relying on the previous behavior where strings could be rendered outside of ",(0,s.jsx)(n.code,{children:""})," components, you'll need to fix your components to wrap strings in ",(0,s.jsx)(n.code,{children:""})," components, as this matches React Native's actual runtime behavior."]}),"\n",(0,s.jsxs)(n.h2,{id:"codemods",children:["Codemods",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#codemods",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["We provide two codemods to automate the migration. Both codemods are ",(0,s.jsx)(n.strong,{children:"safe to run multiple times"})," - they will only transform code that hasn't been migrated yet."]}),"\n",(0,s.jsxs)(n.h3,{id:"rntl-v14-update-deps",children:[(0,s.jsx)(n.code,{children:"rntl-v14-update-deps"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#rntl-v14-update-deps",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["Updates your ",(0,s.jsx)(n.code,{children:"package.json"}),":"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Removes React Test Renderer (",(0,s.jsx)(n.code,{children:"react-test-renderer"})," and ",(0,s.jsx)(n.code,{children:"@types/react-test-renderer"}),")"]}),"\n",(0,s.jsxs)(n.li,{children:["Adds Test Renderer (",(0,s.jsx)(n.code,{children:"test-renderer"}),")"]}),"\n",(0,s.jsxs)(n.li,{children:["Updates ",(0,s.jsx)(n.code,{children:"@testing-library/react-native"})," to ",(0,s.jsx)(n.code,{children:"^14.0.0"})]}),"\n"]}),"\n",(0,s.jsx)(d.SU,{command:{npm:"npx codemod@latest rntl-v14-update-deps --target .\nnpm install",yarn:"yarn dlx codemod@latest rntl-v14-update-deps --target .\nyarn install",pnpm:"pnpm dlx codemod@latest rntl-v14-update-deps --target .\npnpm install",bun:"bunx codemod@latest rntl-v14-update-deps --target .\nbun install"}}),"\n",(0,s.jsxs)(n.h3,{id:"rntl-v14-async-functions",children:[(0,s.jsx)(n.code,{children:"rntl-v14-async-functions"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#rntl-v14-async-functions",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"Transforms test files:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Adds ",(0,s.jsx)(n.code,{children:"await"})," to ",(0,s.jsx)(n.code,{children:"render()"}),", ",(0,s.jsx)(n.code,{children:"act()"}),", ",(0,s.jsx)(n.code,{children:"renderHook()"}),", ",(0,s.jsx)(n.code,{children:"fireEvent()"})," calls"]}),"\n",(0,s.jsx)(n.li,{children:"Makes test functions async when needed"}),"\n",(0,s.jsxs)(n.li,{children:["Handles ",(0,s.jsx)(n.code,{children:"screen.rerender()"}),", ",(0,s.jsx)(n.code,{children:"screen.unmount()"}),", and renderer methods"]}),"\n"]}),"\n",(0,s.jsx)(d.SU,{command:{npm:"npx codemod@latest rntl-v14-async-functions --target ./src",yarn:"yarn dlx codemod@latest rntl-v14-async-functions --target ./src",pnpm:"pnpm dlx codemod@latest rntl-v14-async-functions --target ./src",bun:"bunx codemod@latest rntl-v14-async-functions --target ./src"}}),"\n",(0,s.jsxs)(n.h4,{id:"custom-render-functions",children:["Custom render functions",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#custom-render-functions",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["If you have custom render helpers (like ",(0,s.jsx)(n.code,{children:"renderWithProviders"}),"), you can specify them using the ",(0,s.jsx)(n.code,{children:"customRenderFunctions"})," parameter. The codemod will then also transform calls to these functions:"]}),"\n",(0,s.jsx)(d.SU,{command:{npm:'npx codemod@latest rntl-v14-async-functions \\\n --target ./src \\\n --param customRenderFunctions="renderWithProviders,renderWithTheme"',yarn:'yarn dlx codemod@latest rntl-v14-async-functions \\\n --target ./src \\\n --param customRenderFunctions="renderWithProviders,renderWithTheme"',pnpm:'pnpm dlx codemod@latest rntl-v14-async-functions \\\n --target ./src \\\n --param customRenderFunctions="renderWithProviders,renderWithTheme"',bun:'bunx codemod@latest rntl-v14-async-functions \\\n --target ./src \\\n --param customRenderFunctions="renderWithProviders,renderWithTheme"'}}),"\n",(0,s.jsxs)(n.p,{children:["This will add ",(0,s.jsx)(n.code,{children:"await"})," to your custom render calls and make the containing test functions async, just like it does for the standard ",(0,s.jsx)(n.code,{children:"render"})," function."]}),"\n",(0,s.jsxs)(n.h4,{id:"limitations",children:["Limitations",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#limitations",children:"#"})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Helper functions defined in test files are not transformed by default"}),"\n",(0,s.jsxs)(n.li,{children:["Namespace imports (",(0,s.jsx)(n.code,{children:"import * as RNTL"}),") are not handled"]}),"\n"]}),"\n",(0,s.jsxs)(n.h2,{id:"full-changelog",children:["Full Changelog",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#full-changelog",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.a,{href:"https://github.com/callstack/react-native-testing-library/compare/v13.3.3...v14.0.0",target:"_blank",rel:"noopener noreferrer",children:"https://github.com/callstack/react-native-testing-library/compare/v13.3.3...v14.0.0"})})]})}function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,t.ah)(),e.components);return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(i,{...e})}):i(e)}let c=a;a.__RSPRESS_PAGE_META={},a.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fmigration%2Fv14.mdx"]={toc:[{text:"Overview",id:"overview",depth:2},{text:"Quick Migration",id:"quick-migration",depth:2},{text:"Breaking Changes",id:"breaking-changes",depth:2},{text:"Supported React and React Native versions",id:"supported-react-and-react-native-versions",depth:3},{text:"Test Renderer replaces React Test Renderer",id:"test-renderer-replaces-react-test-renderer",depth:3},{text:"1. Update dependencies",id:"1-update-dependencies",depth:4},{text:"2. Update type imports (if needed)",id:"2-update-type-imports-if-needed",depth:4},{text:"Async APIs by Default",id:"async-apis-by-default",depth:3},{text:"`render` is now async",id:"render-async-default",depth:4},{text:"`renderHook` is now async",id:"renderhook-is-now-async",depth:4},{text:"`fireEvent` is now async",id:"fireevent-is-now-async",depth:4},{text:"`act` is now async",id:"act-is-now-async",depth:4},{text:"Benefits of Async APIs",id:"benefits-of-async-apis",depth:4},{text:"Removed APIs",id:"removed-apis",depth:3},{text:"`update` alias removed",id:"update-alias-removed",depth:4},{text:"`getQueriesForElement` export removed",id:"getqueriesforelement-export-removed",depth:4},{text:"`UNSAFE_root` removed",id:"unsafe_root-removed",depth:4},{text:"Legacy `UNSAFE_*` queries removed",id:"legacy-unsafe_-queries-removed",depth:4},{text:"`concurrentRoot` option removed",id:"concurrentroot-option-removed",depth:4},{text:"`container` API reintroduced",id:"container-api-reintroduced",depth:3},{text:"Text string validation enforced by default",id:"text-string-validation-enforced-by-default",depth:3},{text:"Codemods",id:"codemods",depth:2},{text:"`rntl-v14-update-deps`",id:"rntl-v14-update-deps",depth:3},{text:"`rntl-v14-async-functions`",id:"rntl-v14-async-functions",depth:3},{text:"Custom render functions",id:"custom-render-functions",depth:4},{text:"Limitations",id:"limitations",depth:4},{text:"Full Changelog",id:"full-changelog",depth:2}],title:"Migration to 14.x",headingTitle:"Migration to 14.x",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/3241.c2e74d2b.js b/static/js/async/3241.c2e74d2b.js deleted file mode 100644 index 0da2aa88..00000000 --- a/static/js/async/3241.c2e74d2b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["3241"],{9546:function(e,n,r){r.r(n),r.d(n,{default:()=>d});var t=r(5893),s=r(65);function a(e){let n=Object.assign({h1:"h1",a:"a",p:"p",h2:"h2",h3:"h3",code:"code",strong:"strong",ul:"ul",li:"li",h4:"h4",pre:"pre",h5:"h5"},(0,s.ah)(),e.components);return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.h1,{id:"migration-to-14x",children:["Migration to 14.x",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#migration-to-14x",children:"#"})]}),"\n",(0,t.jsx)(n.p,{children:"This guide describes the migration to React Native Testing Library version 14 from version 13.x."}),"\n",(0,t.jsxs)(n.h2,{id:"breaking-changes",children:["Breaking changes",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#breaking-changes",children:"#"})]}),"\n",(0,t.jsxs)(n.h3,{id:"test-renderer-replaces-react-test-renderer",children:["Test Renderer replaces React Test Renderer",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#test-renderer-replaces-react-test-renderer",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["In v14, React Native Testing Library now uses ",(0,t.jsx)(n.a,{href:"https://github.com/mdjastrzebski/test-renderer",target:"_blank",rel:"noopener noreferrer",children:"Test Renderer"})," instead of the deprecated ",(0,t.jsx)(n.code,{children:"react-test-renderer"})," package. Test Renderer is a modern, actively maintained alternative that provides better compatibility with React 19 and improved type safety."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"What changed:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["The underlying rendering engine has been switched from ",(0,t.jsx)(n.code,{children:"react-test-renderer"})," to ",(0,t.jsx)(n.code,{children:"test-renderer"})]}),"\n",(0,t.jsx)(n.li,{children:"This change is mostly internal and should not require code changes in most cases"}),"\n",(0,t.jsxs)(n.li,{children:["Type definitions have been updated to use ",(0,t.jsx)(n.code,{children:"HostElement"})," from Test Renderer instead of ",(0,t.jsx)(n.code,{children:"ReactTestInstance"})]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Migration:"})}),"\n",(0,t.jsxs)(n.h4,{id:"1-update-dependencies",children:["1. Update dependencies",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#1-update-dependencies",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["Remove ",(0,t.jsx)(n.code,{children:"react-test-renderer"})," and its type definitions from your dev dependencies, and add ",(0,t.jsx)(n.code,{children:"test-renderer"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"# Using npm\nnpm uninstall react-test-renderer @types/react-test-renderer\nnpm install -D test-renderer@^0.10.0\n\n# Using yarn\nyarn remove react-test-renderer @types/react-test-renderer\nyarn add -D test-renderer@^0.10.0\n\n# Using pnpm\npnpm remove react-test-renderer @types/react-test-renderer\npnpm add -D test-renderer@^0.10.0\n"})}),"\n",(0,t.jsxs)(n.h4,{id:"2-update-type-imports-if-needed",children:["2. Update type imports (if needed)",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#2-update-type-imports-if-needed",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["If you were directly importing types from ",(0,t.jsx)(n.code,{children:"react-test-renderer"}),", you may need to update your imports:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before (v13)\nimport type { ReactTestInstance } from 'react-test-renderer';\n\n// After (v14)\nimport type { HostElement } from 'test-renderer';\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Note:"})," Most users won't need to update type imports, as React Native Testing Library now exports the necessary types directly."]}),"\n",(0,t.jsxs)(n.p,{children:["For more details, see the ",(0,t.jsx)(n.a,{href:"https://github.com/mdjastrzebski/test-renderer",target:"_blank",rel:"noopener noreferrer",children:"Test Renderer documentation"}),"."]}),"\n",(0,t.jsxs)(n.h3,{id:"container-api-reintroduced",children:[(0,t.jsx)(n.code,{children:"container"})," API reintroduced",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#container-api-reintroduced",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["In v14, the ",(0,t.jsx)(n.code,{children:"container"})," API has been reintroduced and is now safe to use. Previously, ",(0,t.jsx)(n.code,{children:"container"})," was renamed to ",(0,t.jsx)(n.code,{children:"UNSAFE_root"})," in v12 due to behavioral differences from React Testing Library's ",(0,t.jsx)(n.code,{children:"container"}),". In v14, ",(0,t.jsx)(n.code,{children:"container"})," now returns a pseudo-element container whose children are the elements you asked to render, making it safe and consistent with React Testing Library's behavior."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"What changed:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"screen.container"})," is now available and safe to use"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"container"})," returns a pseudo-element container from Test Renderer"]}),"\n",(0,t.jsx)(n.li,{children:"The container's children are the elements you rendered"}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"UNSAFE_root"})," has been removed"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Before (v13):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import { render, screen } from '@testing-library/react-native';\n\nit('should access root', () => {\n render();\n // UNSAFE_root was the only way to access the container\n const root = screen.UNSAFE_root;\n});\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"After (v14):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import { render, screen } from '@testing-library/react-native';\n\nit('should access container', async () => {\n await render();\n // container is now safe and available\n const container = screen.container;\n // root is the first child of container\n const root = screen.root;\n});\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Migration:"})}),"\n",(0,t.jsxs)(n.p,{children:["If you were using ",(0,t.jsx)(n.code,{children:"UNSAFE_root"}),", replace it with ",(0,t.jsx)(n.code,{children:"container"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before\nconst root = screen.UNSAFE_root;\n\n// After\nconst container = screen.container;\n// Or use screen.root if you need the actual root element\nconst root = screen.root;\n"})}),"\n",(0,t.jsxs)(n.p,{children:["For more details, see the ",(0,t.jsxs)(n.a,{href:"/docs/api/screen#container",children:[(0,t.jsx)(n.code,{children:"screen"})," API documentation"]}),"."]}),"\n",(0,t.jsxs)(n.h3,{id:"render-async-default",children:[(0,t.jsx)(n.code,{children:"render"})," is now async by default",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#render-async-default",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["In v14, ",(0,t.jsx)(n.code,{children:"render"})," is now async by default and returns a Promise. This change makes it compatible with React 19, React Suspense, and ",(0,t.jsx)(n.code,{children:"React.use()"}),"."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Before (v13):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import { render, screen } from '@testing-library/react-native';\n\nit('should render component', () => {\n render();\n expect(screen.getByText('Hello')).toBeOnTheScreen();\n});\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"After (v14):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import { render, screen } from '@testing-library/react-native';\n\nit('should render component', async () => {\n await render();\n expect(screen.getByText('Hello')).toBeOnTheScreen();\n});\n"})}),"\n",(0,t.jsxs)(n.h4,{id:"step-by-step-migration-guide",children:["Step-by-step migration guide",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#step-by-step-migration-guide",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["To migrate from v13 ",(0,t.jsx)(n.code,{children:"render"})," to v14 ",(0,t.jsx)(n.code,{children:"render"}),":"]}),"\n",(0,t.jsxs)(n.h5,{id:"1-add-async-to-your-test-function",children:["1. Add ",(0,t.jsx)(n.code,{children:"async"})," to your test function",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#1-add-async-to-your-test-function",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before (v13)\nit('should render component', () => {\n\n// After (v14)\nit('should render component', async () => {\n"})}),"\n",(0,t.jsxs)(n.h5,{id:"2-await-render",children:["2. Await ",(0,t.jsx)(n.code,{children:"render"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#2-await-render",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before\nrender();\n\n// After\nawait render();\n"})}),"\n",(0,t.jsxs)(n.h5,{id:"3-update-rerender-calls-to-await",children:["3. Update ",(0,t.jsx)(n.code,{children:"rerender"})," calls to await",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#3-update-rerender-calls-to-await",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before\nscreen.rerender();\n\n// After\nawait screen.rerender();\n"})}),"\n",(0,t.jsxs)(n.h5,{id:"4-replace-update-alias-with-rerender",children:["4. Replace ",(0,t.jsx)(n.code,{children:"update"})," alias with ",(0,t.jsx)(n.code,{children:"rerender"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#4-replace-update-alias-with-rerender",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"update"})," alias for ",(0,t.jsx)(n.code,{children:"rerender"})," has been removed in v14. If you were using ",(0,t.jsx)(n.code,{children:"screen.update()"})," or ",(0,t.jsx)(n.code,{children:"renderer.update()"}),", replace it with ",(0,t.jsx)(n.code,{children:"rerender()"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before (v13)\nscreen.update();\n// or\nconst { update } = render();\nupdate();\n\n// After (v14)\nawait screen.rerender();\n// or\nconst { rerender } = await render();\nawait rerender();\n"})}),"\n",(0,t.jsxs)(n.h5,{id:"5-update-unmount-calls-to-await",children:["5. Update ",(0,t.jsx)(n.code,{children:"unmount"})," calls to await",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#5-update-unmount-calls-to-await",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before\nscreen.unmount();\n\n// After\nawait screen.unmount();\n"})}),"\n",(0,t.jsxs)(n.h4,{id:"complete-example",children:["Complete example",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#complete-example",children:"#"})]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Before (v13):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import { render, screen } from '@testing-library/react-native';\n\nit('should update component', () => {\n render();\n expect(screen.getByText('Count: 0')).toBeOnTheScreen();\n\n screen.rerender();\n expect(screen.getByText('Count: 5')).toBeOnTheScreen();\n\n screen.unmount();\n});\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"After (v14):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import { render, screen } from '@testing-library/react-native';\n\nit('should update component', async () => {\n await render();\n expect(screen.getByText('Count: 0')).toBeOnTheScreen();\n\n await screen.rerender();\n expect(screen.getByText('Count: 5')).toBeOnTheScreen();\n\n await screen.unmount();\n});\n"})}),"\n",(0,t.jsxs)(n.h4,{id:"benefits-of-async-render",children:["Benefits of async ",(0,t.jsx)(n.code,{children:"render"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#benefits-of-async-render",children:"#"})]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"React 19 compatibility"}),": Works seamlessly with React 19's async features"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Suspense support"}),": Properly handles React Suspense boundaries and ",(0,t.jsx)(n.code,{children:"React.use()"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Better timing"}),": Ensures all pending React updates are executed before assertions"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Future-proof"}),": Aligns with React's direction toward async rendering"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["For more details, see the ",(0,t.jsxs)(n.a,{href:"/docs/api/render",children:[(0,t.jsx)(n.code,{children:"render"})," API documentation"]}),"."]}),"\n",(0,t.jsxs)(n.h3,{id:"update-alias-removed",children:[(0,t.jsx)(n.code,{children:"update"})," alias removed",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#update-alias-removed",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["In v14, the ",(0,t.jsx)(n.code,{children:"update"})," alias for ",(0,t.jsx)(n.code,{children:"rerender"})," has been removed. You must use ",(0,t.jsx)(n.code,{children:"rerender"})," instead."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"What changed:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"screen.update()"})," has been removed"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"renderer.update()"})," has been removed"]}),"\n",(0,t.jsxs)(n.li,{children:["Only ",(0,t.jsx)(n.code,{children:"rerender"})," is now available"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Migration:"})}),"\n",(0,t.jsxs)(n.p,{children:["Replace all ",(0,t.jsx)(n.code,{children:"update"})," calls with ",(0,t.jsx)(n.code,{children:"rerender"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before (v13)\nscreen.update();\n// or\nconst { update } = render();\nupdate();\n\n// After (v14)\nawait screen.rerender();\n// or\nconst { rerender } = await render();\nawait rerender();\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Note:"})," This change is included in the step-by-step migration guide for async ",(0,t.jsx)(n.code,{children:"render"})," above."]}),"\n",(0,t.jsxs)(n.h3,{id:"getqueriesforelement-export-removed",children:[(0,t.jsx)(n.code,{children:"getQueriesForElement"})," export removed",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#getqueriesforelement-export-removed",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["In v14, the ",(0,t.jsx)(n.code,{children:"getQueriesForElement"})," export alias for ",(0,t.jsx)(n.code,{children:"within"})," has been removed. You must use ",(0,t.jsx)(n.code,{children:"within"})," instead."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"What changed:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"getQueriesForElement"})," is no longer exported from the main package"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"within"})," is the only exported function for scoped queries"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"getQueriesForElement"})," remains available internally but is not part of the public API"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Migration:"})}),"\n",(0,t.jsxs)(n.p,{children:["Replace all ",(0,t.jsx)(n.code,{children:"getQueriesForElement"})," imports and usage with ",(0,t.jsx)(n.code,{children:"within"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before (v13)\nimport { getQueriesForElement } from '@testing-library/react-native';\n\nconst queries = getQueriesForElement(element);\n\n// After (v14)\nimport { within } from '@testing-library/react-native';\n\nconst queries = within(element);\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Note:"})," ",(0,t.jsx)(n.code,{children:"getQueriesForElement"})," was just an alias for ",(0,t.jsx)(n.code,{children:"within"}),", so the functionality is identical - only the import needs to change."]}),"\n",(0,t.jsxs)(n.h3,{id:"renderhook-is-now-async-by-default",children:[(0,t.jsx)(n.code,{children:"renderHook"})," is now async by default",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#renderhook-is-now-async-by-default",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["In v14, ",(0,t.jsx)(n.code,{children:"renderHook"})," is now async by default and returns a Promise. This change makes it compatible with React 19, React Suspense, and ",(0,t.jsx)(n.code,{children:"React.use()"}),"."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Before (v13):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import { renderHook } from '@testing-library/react-native';\n\nit('should test hook', () => {\n const { result, rerender } = renderHook(() => useMyHook());\n\n rerender(newProps);\n unmount();\n});\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"After (v14):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import { renderHook } from '@testing-library/react-native';\n\nit('should test hook', async () => {\n const { result, rerender } = await renderHook(() => useMyHook());\n\n await rerender(newProps);\n await unmount();\n});\n"})}),"\n",(0,t.jsxs)(n.h4,{id:"step-by-step-migration-guide-1",children:["Step-by-step migration guide",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#step-by-step-migration-guide-1",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["To migrate from v13 ",(0,t.jsx)(n.code,{children:"renderHook"})," to v14 ",(0,t.jsx)(n.code,{children:"renderHook"}),":"]}),"\n",(0,t.jsxs)(n.h5,{id:"1-add-async-to-your-test-function-1",children:["1. Add ",(0,t.jsx)(n.code,{children:"async"})," to your test function",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#1-add-async-to-your-test-function-1",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before\nit('should test hook', () => {\n\n// After\nit('should test hook', async () => {\n"})}),"\n",(0,t.jsxs)(n.h5,{id:"2-await-renderhook",children:["2. Await ",(0,t.jsx)(n.code,{children:"renderHook"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#2-await-renderhook",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before (v13)\nconst { result } = renderHook(() => useMyHook());\n\n// After (v14)\nconst { result } = await renderHook(() => useMyHook());\n"})}),"\n",(0,t.jsxs)(n.h5,{id:"3-update-rerender-calls-to-await-1",children:["3. Update ",(0,t.jsx)(n.code,{children:"rerender"})," calls to await",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#3-update-rerender-calls-to-await-1",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before\nrerender(newProps);\n\n// After\nawait rerender(newProps);\n"})}),"\n",(0,t.jsxs)(n.h5,{id:"4-update-unmount-calls-to-await",children:["4. Update ",(0,t.jsx)(n.code,{children:"unmount"})," calls to await",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#4-update-unmount-calls-to-await",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before\nunmount();\n\n// After\nawait unmount();\n"})}),"\n",(0,t.jsxs)(n.h5,{id:"6-update-act-calls-to-use-async-act",children:["6. Update ",(0,t.jsx)(n.code,{children:"act"})," calls to use async ",(0,t.jsx)(n.code,{children:"act"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#6-update-act-calls-to-use-async-act",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before\nact(() => {\n result.current.doSomething();\n});\n\n// After\nawait act(async () => {\n result.current.doSomething();\n});\n"})}),"\n",(0,t.jsxs)(n.h4,{id:"complete-example-1",children:["Complete example",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#complete-example-1",children:"#"})]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Before (v13):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import { renderHook, act } from '@testing-library/react-native';\n\nit('should increment count', () => {\n const { result, rerender } = renderHook((initialCount: number) => useCount(initialCount), {\n initialProps: 1,\n });\n\n expect(result.current.count).toBe(1);\n\n act(() => {\n result.current.increment();\n });\n\n expect(result.current.count).toBe(2);\n rerender(5);\n expect(result.current.count).toBe(5);\n});\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"After (v14):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import { renderHook, act } from '@testing-library/react-native';\n\nit('should increment count', async () => {\n const { result, rerender } = await renderHook((initialCount: number) => useCount(initialCount), {\n initialProps: 1,\n });\n\n expect(result.current.count).toBe(1);\n\n await act(async () => {\n result.current.increment();\n });\n\n expect(result.current.count).toBe(2);\n await rerender(5);\n expect(result.current.count).toBe(5);\n});\n"})}),"\n",(0,t.jsxs)(n.h4,{id:"benefits-of-async-renderhook",children:["Benefits of async ",(0,t.jsx)(n.code,{children:"renderHook"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#benefits-of-async-renderhook",children:"#"})]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"React 19 compatibility"}),": Works seamlessly with React 19's async features"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Suspense support"}),": Properly handles React Suspense boundaries and ",(0,t.jsx)(n.code,{children:"React.use()"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Better timing"}),": Ensures all pending React updates are executed before assertions"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Future-proof"}),": Aligns with React's direction toward async rendering"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["For more details, see the ",(0,t.jsxs)(n.a,{href:"/docs/api/misc/render-hook",children:[(0,t.jsx)(n.code,{children:"renderHook"})," API documentation"]}),"."]}),"\n",(0,t.jsxs)(n.h3,{id:"fireevent-is-now-async-by-default",children:[(0,t.jsx)(n.code,{children:"fireEvent"})," is now async by default",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#fireevent-is-now-async-by-default",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["In v14, ",(0,t.jsx)(n.code,{children:"fireEvent"})," and its helpers (",(0,t.jsx)(n.code,{children:"press"}),", ",(0,t.jsx)(n.code,{children:"changeText"}),", ",(0,t.jsx)(n.code,{children:"scroll"}),") are now async by default and return a Promise. This change makes it compatible with React 19, React Suspense, and ",(0,t.jsx)(n.code,{children:"React.use()"}),"."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Before (v13):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import { fireEvent, screen } from '@testing-library/react-native';\n\nit('should press button', () => {\n render();\n fireEvent.press(screen.getByText('Press me'));\n expect(onPress).toHaveBeenCalled();\n});\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"After (v14):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import { fireEvent, screen } from '@testing-library/react-native';\n\nit('should press button', async () => {\n render();\n await fireEvent.press(screen.getByText('Press me'));\n expect(onPress).toHaveBeenCalled();\n});\n"})}),"\n",(0,t.jsxs)(n.h3,{id:"text-string-validation-now-enforced-by-default",children:["Text string validation now enforced by default",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#text-string-validation-now-enforced-by-default",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["In v14, Test Renderer automatically enforces React Native's requirement that text strings must be rendered within a ",(0,t.jsx)(n.code,{children:""})," component. This means the ",(0,t.jsx)(n.code,{children:"unstable_validateStringsRenderedWithinText"})," option has been removed from ",(0,t.jsx)(n.code,{children:"RenderOptions"}),", as this validation is now always enabled."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"What changed:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Text string validation is now always enabled and cannot be disabled"}),"\n",(0,t.jsxs)(n.li,{children:["The ",(0,t.jsx)(n.code,{children:"unstable_validateStringsRenderedWithinText"})," option has been removed"]}),"\n",(0,t.jsxs)(n.li,{children:["Tests will now throw ",(0,t.jsx)(n.code,{children:"Invariant Violation: Text strings must be rendered within a component"})," errors when attempting to render strings outside of ",(0,t.jsx)(n.code,{children:""})," components, matching React Native's runtime behavior"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Migration:"})}),"\n",(0,t.jsxs)(n.p,{children:["If you were using ",(0,t.jsx)(n.code,{children:"unstable_validateStringsRenderedWithinText: true"})," in your render options, you can simply remove this option as the validation is now always enabled:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before (v13)\nawait render(, {\n unstable_validateStringsRenderedWithinText: true,\n});\n\n// After (v14)\nawait render();\n// Validation is now always enabled\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If you were relying on the previous behavior where strings could be rendered outside of ",(0,t.jsx)(n.code,{children:""})," components, you'll need to fix your components to wrap strings in ",(0,t.jsx)(n.code,{children:""})," components, as this matches React Native's actual runtime behavior."]}),"\n",(0,t.jsxs)(n.h3,{id:"act-is-now-async-by-default",children:[(0,t.jsx)(n.code,{children:"act"})," is now async by default",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#act-is-now-async-by-default",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["In v14, ",(0,t.jsx)(n.code,{children:"act"})," is now async by default and always returns a Promise. This change makes it compatible with React 19, React Suspense, and ",(0,t.jsx)(n.code,{children:"React.use()"}),"."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"What changed:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"act"})," now always returns a ",(0,t.jsx)(n.code,{children:"Promise"})," instead of ",(0,t.jsx)(n.code,{children:"T | Thenable"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"act"})," is now a named export (no default export)"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Before (v13):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import act from '@testing-library/react-native';\n\nit('should update state', () => {\n act(() => {\n // Synchronous callback\n setState('new value');\n });\n // act could return synchronously or a thenable\n expect(state).toBe('new value');\n});\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"After (v14):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import { act } from '@testing-library/react-native';\n\nit('should update state', async () => {\n await act(async () => {\n // Callback can be sync or async\n setState('new value');\n });\n // act always returns a Promise\n expect(state).toBe('new value');\n});\n"})}),"\n",(0,t.jsxs)(n.h4,{id:"step-by-step-migration-guide-2",children:["Step-by-step migration guide",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#step-by-step-migration-guide-2",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["To migrate from v13 ",(0,t.jsx)(n.code,{children:"act"})," to v14 ",(0,t.jsx)(n.code,{children:"act"}),":"]}),"\n",(0,t.jsxs)(n.h5,{id:"1-update-import-statement",children:["1. Update import statement",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#1-update-import-statement",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before\nimport act from '@testing-library/react-native';\n\n// After\nimport { act } from '@testing-library/react-native';\n"})}),"\n",(0,t.jsxs)(n.h5,{id:"2-add-async-to-your-test-function",children:["2. Add ",(0,t.jsx)(n.code,{children:"async"})," to your test function",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#2-add-async-to-your-test-function",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before\nit('should update state', () => {\n\n// After\nit('should update state', async () => {\n"})}),"\n",(0,t.jsxs)(n.h5,{id:"3-await-act-calls",children:["3. Await ",(0,t.jsx)(n.code,{children:"act"})," calls",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#3-await-act-calls",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"// Before\nact(() => {\n setState('new value');\n});\n\n// After\nawait act(async () => {\n setState('new value');\n});\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Note"}),": Even if your callback is synchronous, you should still use ",(0,t.jsx)(n.code,{children:"await act(async () => ...)"})," as ",(0,t.jsx)(n.code,{children:"act"})," now always returns a Promise."]}),"\n",(0,t.jsxs)(n.h4,{id:"complete-example-2",children:["Complete example",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#complete-example-2",children:"#"})]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Before (v13):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import act from '@testing-library/react-native';\n\nit('should update state synchronously', () => {\n act(() => {\n setState('new value');\n });\n expect(state).toBe('new value');\n});\n\nit('should update state asynchronously', () => {\n act(async () => {\n await Promise.resolve();\n setState('new value');\n }).then(() => {\n expect(state).toBe('new value');\n });\n});\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"After (v14):"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"import { act } from '@testing-library/react-native';\n\nit('should update state synchronously', async () => {\n await act(async () => {\n setState('new value');\n });\n expect(state).toBe('new value');\n});\n\nit('should update state asynchronously', async () => {\n await act(async () => {\n await Promise.resolve();\n setState('new value');\n });\n expect(state).toBe('new value');\n});\n"})}),"\n",(0,t.jsxs)(n.h4,{id:"benefits-of-async-act",children:["Benefits of async ",(0,t.jsx)(n.code,{children:"act"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#benefits-of-async-act",children:"#"})]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"React 19 compatibility"}),": Works seamlessly with React 19's async features"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Suspense support"}),": Properly handles React Suspense boundaries and ",(0,t.jsx)(n.code,{children:"React.use()"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Consistent API"}),": Always returns a Promise, making the API more predictable"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Future-proof"}),": Aligns with React's direction toward async rendering"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["For more details, see the ",(0,t.jsxs)(n.a,{href:"/docs/api/misc/other#act",children:[(0,t.jsx)(n.code,{children:"act"})," API documentation"]}),"."]})]})}function i(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,s.ah)(),e.components);return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(a,{...e})}):a(e)}let d=i;i.__RSPRESS_PAGE_META={},i.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fmigration%2Fv14.mdx"]={toc:[{text:"Breaking changes",id:"breaking-changes",depth:2},{text:"Test Renderer replaces React Test Renderer",id:"test-renderer-replaces-react-test-renderer",depth:3},{text:"1. Update dependencies",id:"1-update-dependencies",depth:4},{text:"2. Update type imports (if needed)",id:"2-update-type-imports-if-needed",depth:4},{text:"`container` API reintroduced",id:"container-api-reintroduced",depth:3},{text:"`render` is now async by default",id:"render-async-default",depth:3},{text:"Step-by-step migration guide",id:"step-by-step-migration-guide",depth:4},{text:"Complete example",id:"complete-example",depth:4},{text:"Benefits of async `render`",id:"benefits-of-async-render",depth:4},{text:"`update` alias removed",id:"update-alias-removed",depth:3},{text:"`getQueriesForElement` export removed",id:"getqueriesforelement-export-removed",depth:3},{text:"`renderHook` is now async by default",id:"renderhook-is-now-async-by-default",depth:3},{text:"Step-by-step migration guide",id:"step-by-step-migration-guide-1",depth:4},{text:"Complete example",id:"complete-example-1",depth:4},{text:"Benefits of async `renderHook`",id:"benefits-of-async-renderhook",depth:4},{text:"`fireEvent` is now async by default",id:"fireevent-is-now-async-by-default",depth:3},{text:"Text string validation now enforced by default",id:"text-string-validation-now-enforced-by-default",depth:3},{text:"`act` is now async by default",id:"act-is-now-async-by-default",depth:3},{text:"Step-by-step migration guide",id:"step-by-step-migration-guide-2",depth:4},{text:"Complete example",id:"complete-example-2",depth:4},{text:"Benefits of async `act`",id:"benefits-of-async-act",depth:4}],title:"Migration to 14.x",headingTitle:"Migration to 14.x",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/6409.f3bad53c.js b/static/js/async/3655.55ec9075.js similarity index 93% rename from static/js/async/6409.f3bad53c.js rename to static/js/async/3655.55ec9075.js index 08e16e2c..32e0ec43 100644 --- a/static/js/async/6409.f3bad53c.js +++ b/static/js/async/3655.55ec9075.js @@ -1 +1 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["6409"],{3242:function(e,n,r){r.r(n),r.d(n,{default:()=>o});var s=r(5893),i=r(65);function d(e){let n=Object.assign({h1:"h1",a:"a",p:"p",code:"code",h2:"h2",ul:"ul",li:"li",pre:"pre",div:"div"},(0,i.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.h1,{id:"migration-to-2x",children:["Migration to 2.x",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#migration-to-2x",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["This guide describes steps necessary to migrate from React Native Testing Library ",(0,s.jsx)(n.code,{children:"v1.x"})," to ",(0,s.jsx)(n.code,{children:"v2.x"}),"."]}),"\n",(0,s.jsxs)(n.h2,{id:"dropping-node-8",children:["Dropping Node 8",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#dropping-node-8",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"Node 8 reached its EOL more than 5 months ago, so it's about time to target the library to Node 10. If you used lower version, you'll have to upgrade to v10, but we recommend using the latest LTS version."}),"\n",(0,s.jsxs)(n.h2,{id:"auto-cleanup",children:["Auto Cleanup",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#auto-cleanup",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"cleanup()"})," function is now called automatically after every test if your testing framework supports ",(0,s.jsx)(n.code,{children:"afterEach"})," hook (like Jest, Mocha, and Jasmine)."]}),"\n",(0,s.jsxs)(n.p,{children:["You should be able to remove all ",(0,s.jsx)(n.code,{children:"afterEach(cleanup)"})," calls in your code."]}),"\n",(0,s.jsxs)(n.p,{children:["This change might break your code, if you tests are not isolated, i.e. you call ",(0,s.jsx)(n.code,{children:"render"})," outside ",(0,s.jsx)(n.code,{children:"test"})," block. Generally, you should ",(0,s.jsx)(n.a,{href:"https://kentcdodds.com/blog/test-isolation-with-react",target:"_blank",rel:"noopener noreferrer",children:"keep your tests isolated"}),". But if you can't or don't want to do this right away you can prevent this behavior using any of the following ways:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["by importing ",(0,s.jsx)(n.code,{children:"'react-native-testing-library/pure'"})," instead of ",(0,s.jsx)(n.code,{children:"'react-native-testing-library'"})]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["by importing ",(0,s.jsx)(n.code,{children:"'react-native-testing-library/dont-cleanup-after-each'"})," before importing ",(0,s.jsx)(n.code,{children:"'react-native-testing-library'"}),". You can do it in a global way by using Jest's ",(0,s.jsx)(n.code,{children:"setupFiles"})," like this:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "setupFiles": ["react-native-testing-library/dont-cleanup-after-each"];\n}\n'})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["by setting ",(0,s.jsx)(n.code,{children:"RNTL_SKIP_AUTO_CLEANUP"})," env variable to ",(0,s.jsx)(n.code,{children:"true"}),". You can do this with ",(0,s.jsx)(n.code,{children:"cross-evn"})," like this:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh",children:"cross-env RNTL_SKIP_AUTO_CLEANUP=true jest\n"})}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.h2,{id:"waitfor-api-changes",children:["WaitFor API changes",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#waitfor-api-changes",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["We renamed ",(0,s.jsx)(n.code,{children:"waitForElement"})," function to ",(0,s.jsx)(n.code,{children:"waitFor"})," for consistency with React Testing Library. Additionally, the signature has slightly changed from:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"export default function waitForElement(\n expectation: () => T,\n timeout?: number,\n interval?: number\n): Promise {}\n"})}),"\n",(0,s.jsx)(n.p,{children:"to:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"export default function waitFor(\n expectation: () => T,\n options: {\n timeout?: number,\n interval?: number,\n }\n): Promise {}\n"})}),"\n",(0,s.jsx)(n.p,{children:"Both changes should improve code readibility."}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"waitFor"})," calls (and hence also ",(0,s.jsx)(n.code,{children:"findBy"})," queries) are now wrapped in ",(0,s.jsx)(n.code,{children:"act"})," by default, so that you should no longer need to use ",(0,s.jsx)(n.code,{children:"act"})," directly in your tests."]}),"\n",(0,s.jsxs)(n.div,{className:"rspress-directive tip",children:[(0,s.jsx)(n.div,{className:"rspress-directive-title",children:"TIP"}),(0,s.jsx)(n.div,{className:"rspress-directive-content",children:(0,s.jsxs)(n.p,{children:["You can usually avoid ",(0,s.jsx)(n.code,{children:"waitFor"})," by a proper use of ",(0,s.jsx)(n.code,{children:"findBy"})," asynchronous queries. It will result in more streamlined testing experience.\n"]})})]}),"\n",(0,s.jsxs)(n.h2,{id:"removed-global-debug-function",children:["Removed global ",(0,s.jsx)(n.code,{children:"debug"})," function",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#removed-global-debug-function",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"debug()"})," method returned from ",(0,s.jsx)(n.code,{children:"render()"})," function is all you need. We removed the global export to avoid confusion."]}),"\n",(0,s.jsxs)(n.h2,{id:"removed-global-shallow-function",children:["Removed global ",(0,s.jsx)(n.code,{children:"shallow"})," function",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#removed-global-shallow-function",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"Shallow rendering React component is usually not a good idea, so we decided to remove the API. But, if you find it useful or need to support legacy tests, feel free to use this implementation:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"import ShallowRenderer from 'react-test-renderer/shallow';\n\nexport function shallow(instance: HostElement | React.Element) {\n const renderer = new ShallowRenderer();\n renderer.render(React.createElement(instance.type, instance.props));\n\n return { output: renderer.getRenderOutput() };\n}\n"})}),"\n",(0,s.jsxs)(n.h2,{id:"removed-functions",children:["Removed functions",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#removed-functions",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"Following query functions have been removed after being deprecated for more than a year now:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"getByName"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"getAllByName"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"queryByName"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"queryAllByName"})}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"*ByType"})," and ",(0,s.jsx)(n.code,{children:"*ByProps"})," queries has been prefixed with ",(0,s.jsx)(n.code,{children:"UNSAFE_"}),". These ",(0,s.jsx)(n.code,{children:"UNSAFE_"})," functions are not planned for removal in future versions but their usage is discouraged. You can rename them using global search/replace in your project:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"getByType"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_getByType"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"getAllByType"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_getAllByType"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"queryByType"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_queryByType"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"queryAllByType"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_queryAllByType"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"getByProps"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_getByProps"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"getAllByProps"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_getAllByProps"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"queryByProps"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_queryByProps"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"queryAllByProps"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_queryAllByProps"})]}),"\n"]}),"\n",(0,s.jsxs)(n.h2,{id:"some-bytestid-queries-behavior-changes",children:["Some ",(0,s.jsx)(n.code,{children:"ByTestId"})," queries behavior changes",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#some-bytestid-queries-behavior-changes",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["In version ",(0,s.jsx)(n.code,{children:"1.x"})," the ",(0,s.jsx)(n.code,{children:"getByTestId"})," and ",(0,s.jsx)(n.code,{children:"queryByTestId"})," queries could return non-native instances. This was a serious bug. Other query functions like ",(0,s.jsx)(n.code,{children:"getAllByTestId"}),", ",(0,s.jsx)(n.code,{children:"queryAllByTestId"}),", ",(0,s.jsx)(n.code,{children:"findByTestId"})," and ",(0,s.jsx)(n.code,{children:"findAllByTestId"})," didn't have this issue. These correctly returned only native components instances (e.g. ",(0,s.jsx)(n.code,{children:"View"}),", ",(0,s.jsx)(n.code,{children:"Text"}),", etc) that got the ",(0,s.jsx)(n.code,{children:"testID"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"In v2 we fixed this inconsistency, which may result in failing tests, if you relied on this behavior. There are few ways to handle these failures:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["pass the ",(0,s.jsx)(n.code,{children:"testID"})," prop down so it can reach a native component, like ",(0,s.jsx)(n.code,{children:"View"})," or ",(0,s.jsx)(n.code,{children:"Text"})]}),"\n",(0,s.jsxs)(n.li,{children:["replace ",(0,s.jsx)(n.code,{children:"testID"})," with proper ",(0,s.jsx)(n.code,{children:"accessibilityHint"})," or ",(0,s.jsx)(n.code,{children:"accessibilityLabel"})," if it benefits the user"]}),"\n",(0,s.jsxs)(n.li,{children:["use safe queries like ",(0,s.jsx)(n.code,{children:"*ByText"})," or ",(0,s.jsx)(n.code,{children:"*ByA11yHint"})]}),"\n"]}),"\n",(0,s.jsxs)(n.h2,{id:"deprecated-flushmicrotasksqueue",children:["Deprecated ",(0,s.jsx)(n.code,{children:"flushMicrotasksQueue"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#deprecated-flushmicrotasksqueue",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["We have deprecated ",(0,s.jsx)(n.code,{children:"flushMicrotasksQueue"})," and plan to remove it in the next major. We have better alternatives available for helping you write async tests – ",(0,s.jsx)(n.code,{children:"findBy"})," async queries and ",(0,s.jsx)(n.code,{children:"waitFor"})," helper."]}),"\n",(0,s.jsx)(n.p,{children:"If you can't or don't want to migrate your tests, don't worry. You can use the same implementation we have today:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"function flushMicrotasksQueue() {\n return new Promise((resolve) => setImmediate(resolve));\n}\n"})})]})}function t(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,i.ah)(),e.components);return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}let o=t;t.__RSPRESS_PAGE_META={},t.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fmigration%2Fprevious%2Fv2.mdx"]={toc:[{text:"Dropping Node 8",id:"dropping-node-8",depth:2},{text:"Auto Cleanup",id:"auto-cleanup",depth:2},{text:"WaitFor API changes",id:"waitfor-api-changes",depth:2},{text:"Removed global `debug` function",id:"removed-global-debug-function",depth:2},{text:"Removed global `shallow` function",id:"removed-global-shallow-function",depth:2},{text:"Removed functions",id:"removed-functions",depth:2},{text:"Some `ByTestId` queries behavior changes",id:"some-bytestid-queries-behavior-changes",depth:2},{text:"Deprecated `flushMicrotasksQueue`",id:"deprecated-flushmicrotasksqueue",depth:2}],title:"Migration to 2.x",headingTitle:"Migration to 2.x",frontmatter:{}}}}]); \ No newline at end of file +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["3655"],{9910:function(e,n,r){r.r(n),r.d(n,{default:()=>o});var s=r(5893),i=r(65);function d(e){let n=Object.assign({h1:"h1",a:"a",p:"p",code:"code",h2:"h2",ul:"ul",li:"li",pre:"pre",div:"div"},(0,i.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.h1,{id:"migration-to-2x",children:["Migration to 2.x",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#migration-to-2x",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["This guide describes steps necessary to migrate from React Native Testing Library ",(0,s.jsx)(n.code,{children:"v1.x"})," to ",(0,s.jsx)(n.code,{children:"v2.x"}),"."]}),"\n",(0,s.jsxs)(n.h2,{id:"dropping-node-8",children:["Dropping Node 8",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#dropping-node-8",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"Node 8 reached its EOL more than 5 months ago, so it's about time to target the library to Node 10. If you used lower version, you'll have to upgrade to v10, but we recommend using the latest LTS version."}),"\n",(0,s.jsxs)(n.h2,{id:"auto-cleanup",children:["Auto Cleanup",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#auto-cleanup",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"cleanup()"})," function is now called automatically after every test if your testing framework supports ",(0,s.jsx)(n.code,{children:"afterEach"})," hook (like Jest, Mocha, and Jasmine)."]}),"\n",(0,s.jsxs)(n.p,{children:["You should be able to remove all ",(0,s.jsx)(n.code,{children:"afterEach(cleanup)"})," calls in your code."]}),"\n",(0,s.jsxs)(n.p,{children:["This change might break your code, if you tests are not isolated, i.e. you call ",(0,s.jsx)(n.code,{children:"render"})," outside ",(0,s.jsx)(n.code,{children:"test"})," block. Generally, you should ",(0,s.jsx)(n.a,{href:"https://kentcdodds.com/blog/test-isolation-with-react",target:"_blank",rel:"noopener noreferrer",children:"keep your tests isolated"}),". But if you can't or don't want to do this right away you can prevent this behavior using any of the following ways:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["by importing ",(0,s.jsx)(n.code,{children:"'react-native-testing-library/pure'"})," instead of ",(0,s.jsx)(n.code,{children:"'react-native-testing-library'"})]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["by importing ",(0,s.jsx)(n.code,{children:"'react-native-testing-library/dont-cleanup-after-each'"})," before importing ",(0,s.jsx)(n.code,{children:"'react-native-testing-library'"}),". You can do it in a global way by using Jest's ",(0,s.jsx)(n.code,{children:"setupFiles"})," like this:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "setupFiles": ["react-native-testing-library/dont-cleanup-after-each"];\n}\n'})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["by setting ",(0,s.jsx)(n.code,{children:"RNTL_SKIP_AUTO_CLEANUP"})," env variable to ",(0,s.jsx)(n.code,{children:"true"}),". You can do this with ",(0,s.jsx)(n.code,{children:"cross-evn"})," like this:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh",children:"cross-env RNTL_SKIP_AUTO_CLEANUP=true jest\n"})}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.h2,{id:"waitfor-api-changes",children:["WaitFor API changes",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#waitfor-api-changes",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["We renamed ",(0,s.jsx)(n.code,{children:"waitForElement"})," function to ",(0,s.jsx)(n.code,{children:"waitFor"})," for consistency with React Testing Library. Additionally, the signature has slightly changed from:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"export default function waitForElement(\n expectation: () => T,\n timeout?: number,\n interval?: number\n): Promise {}\n"})}),"\n",(0,s.jsx)(n.p,{children:"to:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"export default function waitFor(\n expectation: () => T,\n options: {\n timeout?: number,\n interval?: number,\n }\n): Promise {}\n"})}),"\n",(0,s.jsx)(n.p,{children:"Both changes should improve code readibility."}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"waitFor"})," calls (and hence also ",(0,s.jsx)(n.code,{children:"findBy"})," queries) are now wrapped in ",(0,s.jsx)(n.code,{children:"act"})," by default, so that you should no longer need to use ",(0,s.jsx)(n.code,{children:"act"})," directly in your tests."]}),"\n",(0,s.jsxs)(n.div,{className:"rspress-directive tip",children:[(0,s.jsx)(n.div,{className:"rspress-directive-title",children:"TIP"}),(0,s.jsx)(n.div,{className:"rspress-directive-content",children:(0,s.jsxs)(n.p,{children:["You can usually avoid ",(0,s.jsx)(n.code,{children:"waitFor"})," by a proper use of ",(0,s.jsx)(n.code,{children:"findBy"})," asynchronous queries. It will result in more streamlined testing experience.\n"]})})]}),"\n",(0,s.jsxs)(n.h2,{id:"removed-global-debug-function",children:["Removed global ",(0,s.jsx)(n.code,{children:"debug"})," function",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#removed-global-debug-function",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"debug()"})," method returned from ",(0,s.jsx)(n.code,{children:"render()"})," function is all you need. We removed the global export to avoid confusion."]}),"\n",(0,s.jsxs)(n.h2,{id:"removed-global-shallow-function",children:["Removed global ",(0,s.jsx)(n.code,{children:"shallow"})," function",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#removed-global-shallow-function",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"Shallow rendering React component is usually not a good idea, so we decided to remove the API. But, if you find it useful or need to support legacy tests, feel free to use this implementation:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"import ShallowRenderer from 'react-test-renderer/shallow';\n\nexport function shallow(instance: HostElement | React.Element) {\n const renderer = new ShallowRenderer();\n renderer.render(React.createElement(instance.type, instance.props));\n\n return { output: renderer.getRenderOutput() };\n}\n"})}),"\n",(0,s.jsxs)(n.h2,{id:"removed-functions",children:["Removed functions",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#removed-functions",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"Following query functions have been removed after being deprecated for more than a year now:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"getByName"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"getAllByName"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"queryByName"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"queryAllByName"})}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"*ByType"})," and ",(0,s.jsx)(n.code,{children:"*ByProps"})," queries has been prefixed with ",(0,s.jsx)(n.code,{children:"UNSAFE_"}),". These ",(0,s.jsx)(n.code,{children:"UNSAFE_"})," functions are not planned for removal in future versions but their usage is discouraged. You can rename them using global search/replace in your project:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"getByType"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_getByType"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"getAllByType"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_getAllByType"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"queryByType"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_queryByType"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"queryAllByType"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_queryAllByType"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"getByProps"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_getByProps"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"getAllByProps"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_getAllByProps"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"queryByProps"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_queryByProps"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"queryAllByProps"})," -> ",(0,s.jsx)(n.code,{children:"UNSAFE_queryAllByProps"})]}),"\n"]}),"\n",(0,s.jsxs)(n.h2,{id:"some-bytestid-queries-behavior-changes",children:["Some ",(0,s.jsx)(n.code,{children:"ByTestId"})," queries behavior changes",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#some-bytestid-queries-behavior-changes",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["In version ",(0,s.jsx)(n.code,{children:"1.x"})," the ",(0,s.jsx)(n.code,{children:"getByTestId"})," and ",(0,s.jsx)(n.code,{children:"queryByTestId"})," queries could return non-native instances. This was a serious bug. Other query functions like ",(0,s.jsx)(n.code,{children:"getAllByTestId"}),", ",(0,s.jsx)(n.code,{children:"queryAllByTestId"}),", ",(0,s.jsx)(n.code,{children:"findByTestId"})," and ",(0,s.jsx)(n.code,{children:"findAllByTestId"})," didn't have this issue. These correctly returned only native components instances (e.g. ",(0,s.jsx)(n.code,{children:"View"}),", ",(0,s.jsx)(n.code,{children:"Text"}),", etc) that got the ",(0,s.jsx)(n.code,{children:"testID"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"In v2 we fixed this inconsistency, which may result in failing tests, if you relied on this behavior. There are few ways to handle these failures:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["pass the ",(0,s.jsx)(n.code,{children:"testID"})," prop down so it can reach a native component, like ",(0,s.jsx)(n.code,{children:"View"})," or ",(0,s.jsx)(n.code,{children:"Text"})]}),"\n",(0,s.jsxs)(n.li,{children:["replace ",(0,s.jsx)(n.code,{children:"testID"})," with proper ",(0,s.jsx)(n.code,{children:"accessibilityHint"})," or ",(0,s.jsx)(n.code,{children:"accessibilityLabel"})," if it benefits the user"]}),"\n",(0,s.jsxs)(n.li,{children:["use safe queries like ",(0,s.jsx)(n.code,{children:"*ByText"})," or ",(0,s.jsx)(n.code,{children:"*ByA11yHint"})]}),"\n"]}),"\n",(0,s.jsxs)(n.h2,{id:"deprecated-flushmicrotasksqueue",children:["Deprecated ",(0,s.jsx)(n.code,{children:"flushMicrotasksQueue"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#deprecated-flushmicrotasksqueue",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["We have deprecated ",(0,s.jsx)(n.code,{children:"flushMicrotasksQueue"})," and plan to remove it in the next major. We have better alternatives available for helping you write async tests – ",(0,s.jsx)(n.code,{children:"findBy"})," async queries and ",(0,s.jsx)(n.code,{children:"waitFor"})," helper."]}),"\n",(0,s.jsx)(n.p,{children:"If you can't or don't want to migrate your tests, don't worry. You can use the same implementation we have today:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"function flushMicrotasksQueue() {\n return new Promise((resolve) => setImmediate(resolve));\n}\n"})})]})}function t(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,i.ah)(),e.components);return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}let o=t;t.__RSPRESS_PAGE_META={},t.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fmigration%2Fv2.mdx"]={toc:[{text:"Dropping Node 8",id:"dropping-node-8",depth:2},{text:"Auto Cleanup",id:"auto-cleanup",depth:2},{text:"WaitFor API changes",id:"waitfor-api-changes",depth:2},{text:"Removed global `debug` function",id:"removed-global-debug-function",depth:2},{text:"Removed global `shallow` function",id:"removed-global-shallow-function",depth:2},{text:"Removed functions",id:"removed-functions",depth:2},{text:"Some `ByTestId` queries behavior changes",id:"some-bytestid-queries-behavior-changes",depth:2},{text:"Deprecated `flushMicrotasksQueue`",id:"deprecated-flushmicrotasksqueue",depth:2}],title:"Migration to 2.x",headingTitle:"Migration to 2.x",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/3748.c600a55e.js b/static/js/async/3748.c600a55e.js deleted file mode 100644 index 28edbc38..00000000 --- a/static/js/async/3748.c600a55e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["3748"],{8523:function(e,i,n){n.r(i),n.d(i,{default:()=>a});var s=n(5893),t=n(65);function r(e){let i=Object.assign({h1:"h1",a:"a",div:"div",p:"p",code:"code",h2:"h2",h3:"h3",h4:"h4",pre:"pre",strong:"strong"},(0,t.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(i.h1,{id:"migration-to-12x",children:["Migration to 12.x",(0,s.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#migration-to-12x",children:"#"})]}),"\n",(0,s.jsxs)(i.div,{className:"rspress-directive info",children:[(0,s.jsx)(i.div,{className:"rspress-directive-title",children:"INFO"}),(0,s.jsxs)(i.div,{className:"rspress-directive-content",children:["\n",(0,s.jsxs)(i.p,{children:["If you are already using legacy ",(0,s.jsx)(i.code,{children:"@testing-library/jest-native"})," Jest Matchers, we have a ",(0,s.jsx)(i.a,{href:"/docs/migration/jest-matchers",children:"migration guide"})," for moving to the built-in matchers."]}),"\n"]})]}),"\n",(0,s.jsxs)(i.p,{children:["React Native Testing Library 12 introduces a handful of breaking changes compared to 11.x versions. We believe they were necessary to improve the experience using the library and help the users ",(0,s.jsx)(i.a,{href:"https://blog.codinghorror.com/falling-into-the-pit-of-success/",target:"_blank",rel:"noopener noreferrer",children:"fall into the pit of success"})," when writing meaningful tests. You will find migration instructions for each and every change described below."]}),"\n",(0,s.jsxs)(i.h2,{id:"breaking-changes",children:["Breaking changes",(0,s.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#breaking-changes",children:"#"})]}),"\n",(0,s.jsxs)(i.h3,{id:"1-all-queries-exclude-elements-hidden-from-accessibility-by-default",children:["1. All queries exclude elements hidden from accessibility by default",(0,s.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#1-all-queries-exclude-elements-hidden-from-accessibility-by-default",children:"#"})]}),"\n",(0,s.jsxs)(i.p,{children:["Elements that are hidden from accessiblity, e.g. elements on non-active screen when using React Navigation, now will not be matched by default by all queries. This is the effect of switching the default value for global config option ",(0,s.jsx)(i.code,{children:"defaultIncludeHiddenElements"}),"(api#defaultincludehiddenelements-option) to ",(0,s.jsx)(i.code,{children:"false"}),"."]}),"\n",(0,s.jsxs)(i.p,{children:["Previous behaviour of matching hidden elements can be enabled on query level using ",(0,s.jsx)(i.a,{href:"/docs/api/queries#includehiddenelements-option",children:"includeHiddenElements"})," query options or globally using ",(0,s.jsx)(i.code,{children:"defaultIncludeHiddenElements"}),"(api#defaultincludehiddenelements-option) configuration option."]}),"\n",(0,s.jsxs)(i.h3,{id:"2-byrole-queries-now-return-only-accessibility-elements",children:["2. ",(0,s.jsx)(i.code,{children:"*ByRole"})," queries now return only accessibility elements",(0,s.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#2-byrole-queries-now-return-only-accessibility-elements",children:"#"})]}),"\n",(0,s.jsxs)(i.p,{children:[(0,s.jsx)(i.code,{children:"*ByRole"})," queries now return only accessibility elements, either explicitly marked with ",(0,s.jsx)(i.code,{children:"accessible"})," prop or implicit ones where this status is derived from component type itself (e.g ",(0,s.jsx)(i.code,{children:"Text"}),", ",(0,s.jsx)(i.code,{children:"TextInput"}),", ",(0,s.jsx)(i.code,{children:"Switch"}),", but not ",(0,s.jsx)(i.code,{children:"View"}),")."]}),"\n",(0,s.jsxs)(i.p,{children:["You may need to adjust relevant components under test to make sure they pass ",(0,s.jsx)(i.code,{children:"isAccessibilityElement"})," check."]}),"\n",(0,s.jsxs)(i.h4,{id:"examples",children:["Examples",(0,s.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#examples",children:"#"})]}),"\n",(0,s.jsxs)(i.p,{children:["Let's assume we are using ",(0,s.jsx)(i.code,{children:'getByRole("button")'})," query."]}),"\n",(0,s.jsx)(i.p,{children:"Following elements will match:"}),"\n",(0,s.jsx)(i.pre,{children:(0,s.jsx)(i.code,{className:"language-tsx",children:'// Explicit "accessible" prop for View\n\n\n// No need to "accessible" prop for Text, as it is implicitly accessible element.\nButton\n'})}),"\n",(0,s.jsx)(i.p,{children:"While following elements will not match:"}),"\n",(0,s.jsx)(i.pre,{children:(0,s.jsx)(i.code,{className:"language-tsx",children:'// Missing "accessible" prop for View\n\n\n// Explicit "accessible={false}" prop for View\n\n\n// Explicit "accessible={false}" for Text, which is implicitly accessible element\nButton\n'})}),"\n",(0,s.jsxs)(i.h3,{id:"3-bytext-bydisplayvalue-byplaceholdertext-queries-now-return-host-elements",children:["3. ",(0,s.jsx)(i.code,{children:"*ByText"}),", ",(0,s.jsx)(i.code,{children:"*ByDisplayValue"}),", ",(0,s.jsx)(i.code,{children:"*ByPlaceholderText"})," queries now return host elements",(0,s.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#3-bytext-bydisplayvalue-byplaceholdertext-queries-now-return-host-elements",children:"#"})]}),"\n",(0,s.jsxs)(i.p,{children:[(0,s.jsx)(i.code,{children:"*ByText"}),", ",(0,s.jsx)(i.code,{children:"*ByDisplayValue"}),", ",(0,s.jsx)(i.code,{children:"*ByPlaceholderText"})," queries now return ",(0,s.jsx)(i.a,{href:"/docs/advanced/testing-env#host-and-composite-components",children:"host elements"}),", which is consistent with other queries."]}),"\n",(0,s.jsx)(i.p,{children:"While potentially breaking, this should not cause issues in tests if you are using recommended queries and Jest Matchers from Jest Native package."}),"\n",(0,s.jsxs)(i.p,{children:["Problematic cases may include: directly checking some prop values (without using Jest Native matchers), referencing other nodes using ",(0,s.jsx)(i.code,{children:"parent"})," or ",(0,s.jsx)(i.code,{children:"children"})," props, examining ",(0,s.jsx)(i.code,{children:"type"})," property of ",(0,s.jsx)(i.code,{children:"HostElement"}),", etc."]}),"\n",(0,s.jsxs)(i.h3,{id:"4-container-api-has-been-renamed-to-unsafe_root",children:["4. ",(0,s.jsx)(i.code,{children:"container"})," API has been renamed to ",(0,s.jsx)(i.code,{children:"UNSAFE_root"}),".",(0,s.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#4-container-api-has-been-renamed-to-unsafe_root",children:"#"})]}),"\n",(0,s.jsxs)(i.p,{children:["Historically ",(0,s.jsx)(i.code,{children:"container"})," was supposed to mimic the ",(0,s.jsx)(i.a,{href:"https://testing-library.com/docs/react-testing-library/screen#container",target:"_blank",rel:"noopener noreferrer",children:"RTL's container"}),". However it turned out not so relevant in RNTL's environment, where we actually used it to return React Test Renderer's root instance."]}),"\n",(0,s.jsxs)(i.p,{children:["RNTL v12 introduces ",(0,s.jsx)(i.code,{children:"root"})," API as an alternative that returns a root ",(0,s.jsx)(i.strong,{children:"host"})," element. The difference between ",(0,s.jsx)(i.code,{children:"root"})," and ",(0,s.jsx)(i.code,{children:"UNSAFE_root"})," properties is that that ",(0,s.jsx)(i.code,{children:"root"})," will always represents a host element, while ",(0,s.jsx)(i.code,{children:"UNSAFE_root"})," will typically represent a composite element."]}),"\n",(0,s.jsxs)(i.p,{children:["If you use ",(0,s.jsx)(i.code,{children:"toBeOnTheScreen"})," matcher from ",(0,s.jsx)(i.a,{href:"https://github.com/testing-library/jest-native",target:"_blank",rel:"noopener noreferrer",children:"@testing-library/jest-native"})," your tests will fail because it uses the ",(0,s.jsx)(i.code,{children:"container"})," api. To fix this, update ",(0,s.jsx)(i.code,{children:"@testing-library/jest-native"})," to version 5.4.2."]}),"\n",(0,s.jsxs)(i.h2,{id:"full-changelog",children:["Full Changelog",(0,s.jsx)(i.a,{className:"header-anchor","aria-hidden":"true",href:"#full-changelog",children:"#"})]}),"\n",(0,s.jsx)(i.p,{children:(0,s.jsx)(i.a,{href:"https://github.com/callstack/react-native-testing-library/compare/v11.5.2...v12.0.0",target:"_blank",rel:"noopener noreferrer",children:"https://github.com/callstack/react-native-testing-library/compare/v11.5.2...v12.0.0"})})]})}function l(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:i}=Object.assign({},(0,t.ah)(),e.components);return i?(0,s.jsx)(i,{...e,children:(0,s.jsx)(r,{...e})}):r(e)}let a=l;l.__RSPRESS_PAGE_META={},l.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fmigration%2Fprevious%2Fv12.mdx"]={toc:[{text:"Breaking changes",id:"breaking-changes",depth:2},{text:"1. All queries exclude elements hidden from accessibility by default",id:"1-all-queries-exclude-elements-hidden-from-accessibility-by-default",depth:3},{text:"2. `*ByRole` queries now return only accessibility elements",id:"2-byrole-queries-now-return-only-accessibility-elements",depth:3},{text:"Examples",id:"examples",depth:4},{text:"3. `*ByText`, `*ByDisplayValue`, `*ByPlaceholderText` queries now return host elements",id:"3-bytext-bydisplayvalue-byplaceholdertext-queries-now-return-host-elements",depth:3},{text:"4. `container` API has been renamed to `UNSAFE_root`.",id:"4-container-api-has-been-renamed-to-unsafe_root",depth:3},{text:"Full Changelog",id:"full-changelog",depth:2}],title:"Migration to 12.x",headingTitle:"Migration to 12.x",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/3815.f906da67.js b/static/js/async/3815.f906da67.js new file mode 100644 index 00000000..0f497764 --- /dev/null +++ b/static/js/async/3815.f906da67.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["3815"],{4380:function(e,n,i){i.r(n),i.d(n,{default:()=>a});var s=i(5893),t=i(65);function r(e){let n=Object.assign({h1:"h1",a:"a",div:"div",p:"p",code:"code",h2:"h2",h3:"h3",h4:"h4",pre:"pre",strong:"strong"},(0,t.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.h1,{id:"migration-to-12x",children:["Migration to 12.x",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#migration-to-12x",children:"#"})]}),"\n",(0,s.jsxs)(n.div,{className:"rspress-directive info",children:[(0,s.jsx)(n.div,{className:"rspress-directive-title",children:"INFO"}),(0,s.jsxs)(n.div,{className:"rspress-directive-content",children:["\n",(0,s.jsxs)(n.p,{children:["If you are already using legacy ",(0,s.jsx)(n.code,{children:"@testing-library/jest-native"})," Jest Matchers, we have a ",(0,s.jsx)(n.a,{href:"/docs/migration/jest-matchers",children:"migration guide"})," for moving to the built-in matchers."]}),"\n"]})]}),"\n",(0,s.jsxs)(n.p,{children:["React Native Testing Library 12 introduces a handful of breaking changes compared to 11.x versions. We believe they were necessary to improve the experience using the library and help the users ",(0,s.jsx)(n.a,{href:"https://blog.codinghorror.com/falling-into-the-pit-of-success/",target:"_blank",rel:"noopener noreferrer",children:"fall into the pit of success"})," when writing meaningful tests. You will find migration instructions for each and every change described below."]}),"\n",(0,s.jsxs)(n.h2,{id:"breaking-changes",children:["Breaking changes",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#breaking-changes",children:"#"})]}),"\n",(0,s.jsxs)(n.h3,{id:"1-all-queries-exclude-elements-hidden-from-accessibility-by-default",children:["1. All queries exclude elements hidden from accessibility by default",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#1-all-queries-exclude-elements-hidden-from-accessibility-by-default",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["Elements that are hidden from accessiblity, e.g. elements on non-active screen when using React Navigation, now will not be matched by default by all queries. This is the effect of switching the default value for global config option ",(0,s.jsx)(n.code,{children:"defaultIncludeHiddenElements"}),"(api#defaultincludehiddenelements-option) to ",(0,s.jsx)(n.code,{children:"false"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Previous behaviour of matching hidden elements can be enabled on query level using ",(0,s.jsx)(n.a,{href:"/docs/api/queries#includehiddenelements-option",children:"includeHiddenElements"})," query options or globally using ",(0,s.jsx)(n.code,{children:"defaultIncludeHiddenElements"}),"(api#defaultincludehiddenelements-option) configuration option."]}),"\n",(0,s.jsxs)(n.h3,{id:"2-byrole-queries-now-return-only-accessibility-elements",children:["2. ",(0,s.jsx)(n.code,{children:"*ByRole"})," queries now return only accessibility elements",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#2-byrole-queries-now-return-only-accessibility-elements",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"*ByRole"})," queries now return only accessibility elements, either explicitly marked with ",(0,s.jsx)(n.code,{children:"accessible"})," prop or implicit ones where this status is derived from component type itself (e.g ",(0,s.jsx)(n.code,{children:"Text"}),", ",(0,s.jsx)(n.code,{children:"TextInput"}),", ",(0,s.jsx)(n.code,{children:"Switch"}),", but not ",(0,s.jsx)(n.code,{children:"View"}),")."]}),"\n",(0,s.jsxs)(n.p,{children:["You may need to adjust relevant components under test to make sure they pass ",(0,s.jsx)(n.code,{children:"isAccessibilityElement"})," check."]}),"\n",(0,s.jsxs)(n.h4,{id:"examples",children:["Examples",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#examples",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["Let's assume we are using ",(0,s.jsx)(n.code,{children:'getByRole("button")'})," query."]}),"\n",(0,s.jsx)(n.p,{children:"Following elements will match:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-tsx",children:'// Explicit "accessible" prop for View\n\n\n// No need to "accessible" prop for Text, as it is implicitly accessible element.\nButton\n'})}),"\n",(0,s.jsx)(n.p,{children:"While following elements will not match:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-tsx",children:'// Missing "accessible" prop for View\n\n\n// Explicit "accessible={false}" prop for View\n\n\n// Explicit "accessible={false}" for Text, which is implicitly accessible element\nButton\n'})}),"\n",(0,s.jsxs)(n.h3,{id:"3-bytext-bydisplayvalue-byplaceholdertext-queries-now-return-host-elements",children:["3. ",(0,s.jsx)(n.code,{children:"*ByText"}),", ",(0,s.jsx)(n.code,{children:"*ByDisplayValue"}),", ",(0,s.jsx)(n.code,{children:"*ByPlaceholderText"})," queries now return host elements",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#3-bytext-bydisplayvalue-byplaceholdertext-queries-now-return-host-elements",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"*ByText"}),", ",(0,s.jsx)(n.code,{children:"*ByDisplayValue"}),", ",(0,s.jsx)(n.code,{children:"*ByPlaceholderText"})," queries now return ",(0,s.jsx)(n.a,{href:"/docs/advanced/testing-env#host-and-composite-components",children:"host elements"}),", which is consistent with other queries."]}),"\n",(0,s.jsx)(n.p,{children:"While potentially breaking, this should not cause issues in tests if you are using recommended queries and Jest Matchers from Jest Native package."}),"\n",(0,s.jsxs)(n.p,{children:["Problematic cases may include: directly checking some prop values (without using Jest Native matchers), referencing other nodes using ",(0,s.jsx)(n.code,{children:"parent"})," or ",(0,s.jsx)(n.code,{children:"children"})," props, examining ",(0,s.jsx)(n.code,{children:"type"})," property of ",(0,s.jsx)(n.code,{children:"HostElement"}),", etc."]}),"\n",(0,s.jsxs)(n.h3,{id:"4-container-api-has-been-renamed-to-unsafe_root",children:["4. ",(0,s.jsx)(n.code,{children:"container"})," API has been renamed to ",(0,s.jsx)(n.code,{children:"UNSAFE_root"}),".",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#4-container-api-has-been-renamed-to-unsafe_root",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["Historically ",(0,s.jsx)(n.code,{children:"container"})," was supposed to mimic the ",(0,s.jsx)(n.a,{href:"https://testing-library.com/docs/react-testing-library/screen#container",target:"_blank",rel:"noopener noreferrer",children:"RTL's container"}),". However it turned out not so relevant in RNTL's environment, where we actually used it to return React Test Renderer's root instance."]}),"\n",(0,s.jsxs)(n.p,{children:["RNTL v12 introduces ",(0,s.jsx)(n.code,{children:"root"})," API as an alternative that returns a root ",(0,s.jsx)(n.strong,{children:"host"})," element. The difference between ",(0,s.jsx)(n.code,{children:"root"})," and ",(0,s.jsx)(n.code,{children:"UNSAFE_root"})," properties is that that ",(0,s.jsx)(n.code,{children:"root"})," will always represents a host element, while ",(0,s.jsx)(n.code,{children:"UNSAFE_root"})," will typically represent a composite element."]}),"\n",(0,s.jsxs)(n.p,{children:["If you use ",(0,s.jsx)(n.code,{children:"toBeOnTheScreen"})," matcher from ",(0,s.jsx)(n.a,{href:"https://github.com/testing-library/jest-native",target:"_blank",rel:"noopener noreferrer",children:"@testing-library/jest-native"})," your tests will fail because it uses the ",(0,s.jsx)(n.code,{children:"container"})," api. To fix this, update ",(0,s.jsx)(n.code,{children:"@testing-library/jest-native"})," to version 5.4.2."]}),"\n",(0,s.jsxs)(n.h2,{id:"full-changelog",children:["Full Changelog",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#full-changelog",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.a,{href:"https://github.com/callstack/react-native-testing-library/compare/v11.5.2...v12.0.0",target:"_blank",rel:"noopener noreferrer",children:"https://github.com/callstack/react-native-testing-library/compare/v11.5.2...v12.0.0"})})]})}function l(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,t.ah)(),e.components);return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(r,{...e})}):r(e)}let a=l;l.__RSPRESS_PAGE_META={},l.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fmigration%2Fv12.mdx"]={toc:[{text:"Breaking changes",id:"breaking-changes",depth:2},{text:"1. All queries exclude elements hidden from accessibility by default",id:"1-all-queries-exclude-elements-hidden-from-accessibility-by-default",depth:3},{text:"2. `*ByRole` queries now return only accessibility elements",id:"2-byrole-queries-now-return-only-accessibility-elements",depth:3},{text:"Examples",id:"examples",depth:4},{text:"3. `*ByText`, `*ByDisplayValue`, `*ByPlaceholderText` queries now return host elements",id:"3-bytext-bydisplayvalue-byplaceholdertext-queries-now-return-host-elements",depth:3},{text:"4. `container` API has been renamed to `UNSAFE_root`.",id:"4-container-api-has-been-renamed-to-unsafe_root",depth:3},{text:"Full Changelog",id:"full-changelog",depth:2}],title:"Migration to 12.x",headingTitle:"Migration to 12.x",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/3828.a2961b5a.js b/static/js/async/3828.a2961b5a.js deleted file mode 100644 index af14b001..00000000 --- a/static/js/async/3828.a2961b5a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["3828"],{9236:function(e,n,s){s.r(n),s.d(n,{default:()=>o});var i=s(5893),t=s(65);function r(e){let n=Object.assign({h1:"h1",a:"a",h2:"h2",p:"p",ol:"ol",li:"li",strong:"strong",h3:"h3",pre:"pre",code:"code",h4:"h4",ul:"ul"},(0,t.ah)(),e.components);return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.h1,{id:"async-tests",children:["Async tests",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#async-tests",children:"#"})]}),"\n",(0,i.jsxs)(n.h2,{id:"summary",children:["Summary",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#summary",children:"#"})]}),"\n",(0,i.jsx)(n.p,{children:"Typically, you would write synchronous tests, as they are simple and get the work done. However, there are cases when using asynchronous (async) tests might be necessary or beneficial. The two most common cases are:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Testing Code with asynchronous operations"}),": When your code relies on asynchronous operations, such as network calls or database queries, async tests are essential. Even though you should mock these network calls, the mock should act similarly to the actual behavior and hence by async."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"UserEvent API:"})," Using the ",(0,i.jsx)(n.a,{href:"/docs/api/events/user-event",children:"User Event API"})," in your tests creates more realistic event handling. These interactions introduce delays (even though these are typically event-loop ticks with 0 ms delays), requiring async tests to handle the timing correctly."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Using async tests when\xa0needed ensures your tests\xa0are\xa0reliable and\xa0simulate\xa0real-world conditions\xa0accurately."}),"\n",(0,i.jsxs)(n.h3,{id:"example",children:["Example",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#example",children:"#"})]}),"\n",(0,i.jsx)(n.p,{children:"Consider a basic asynchronous test for a user signing in with correct credentials:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-javascript",children:"test('User can sign in with correct credentials', async () => {\n // Typical test setup\n const user = userEvent.setup();\n await render();\n\n // No need to use async here, components are already rendered\n expect(screen.getByRole('header', { name: 'Sign in to Hello World App!' })).toBeOnTheScreen();\n\n // Using await as User Event requires it\n await user.type(screen.getByLabelText('Username'), 'admin');\n await user.type(screen.getByLabelText('Password'), 'admin1');\n await user.press(screen.getByRole('button', { name: 'Sign In' }));\n\n // Using await as sign in operation is asynchronous\n expect(await screen.findByRole('header', { name: 'Welcome admin!' })).toBeOnTheScreen();\n\n // Follow-up assertions do not need to be async, as we already waited for sign in operation to complete\n expect(\n screen.queryByRole('header', { name: 'Sign in to Hello World App' })\n ).not.toBeOnTheScreen();\n expect(screen.queryByLabelText('Username')).not.toBeOnTheScreen();\n expect(screen.queryByLabelText('Password')).not.toBeOnTheScreen();\n});\n"})}),"\n",(0,i.jsxs)(n.h2,{id:"async-utilities",children:["Async utilities",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#async-utilities",children:"#"})]}),"\n",(0,i.jsx)(n.p,{children:"There are several asynchronous utilities you might use in your tests."}),"\n",(0,i.jsxs)(n.h3,{id:"findby-queries",children:[(0,i.jsx)(n.code,{children:"findBy*"})," queries",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#findby-queries",children:"#"})]}),"\n",(0,i.jsxs)(n.p,{children:["The most common are the ",(0,i.jsxs)(n.a,{href:"/docs/api/queries#find-by",children:[(0,i.jsx)(n.code,{children:"findBy*"})," queries"]}),". These are useful when waiting for a matching element to appear. They can be understood as a ",(0,i.jsxs)(n.a,{href:"/docs/api/queries#get-by",children:[(0,i.jsx)(n.code,{children:"getBy*"})," queries"]})," used in conjunction with a ",(0,i.jsxs)(n.a,{href:"/docs/api/misc/async#waitfor",children:[(0,i.jsx)(n.code,{children:"waitFor"})," function"]}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["They accept the same predicates as ",(0,i.jsx)(n.code,{children:"getBy*"})," queries like ",(0,i.jsx)(n.code,{children:"findByRole"}),", ",(0,i.jsx)(n.code,{children:"findByTest"}),", etc. They also have a multiple elements variant called ",(0,i.jsx)(n.a,{href:"/docs/api/queries#find-all-by",children:(0,i.jsx)(n.code,{children:"findAllBy*"})}),"."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-typescript",children:"function findByRole: (\n role: TextMatch,\n queryOptions?: {\n // Query specific options\n }\n waitForOptions?: {\n timeout?: number;\n interval?: number;\n // ..\n }\n): Promise;\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Each query has a default ",(0,i.jsx)(n.code,{children:"timeout"})," value of 1000 ms and a default ",(0,i.jsx)(n.code,{children:"interval"})," of 50 ms. Custom timeout and check intervals can be specified if needed, as shown below:"]}),"\n",(0,i.jsxs)(n.h4,{id:"example-1",children:["Example",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#example-1",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-typescript",children:"const button = await screen.findByRole('button'), { name: 'Start' }, { timeout: 1000, interval: 50 });\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Alternatively, a default global ",(0,i.jsx)(n.code,{children:"timeout"})," value can be set using the ",(0,i.jsxs)(n.a,{href:"/docs/api/misc/config#configure",children:[(0,i.jsx)(n.code,{children:"configure"})," function"]}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-typescript",children:"configure({ asyncUtilTimeout: timeout });\n"})}),"\n",(0,i.jsxs)(n.h3,{id:"waitfor-function",children:[(0,i.jsx)(n.code,{children:"waitFor"})," function",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#waitfor-function",children:"#"})]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"waitFor"})," function is another option, serving as a lower-level utility in more advanced cases."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-typescript",children:"function waitFor(\n expectation: () => T,\n options?: {\n timeout: number;\n interval: number;\n }\n): Promise;\n"})}),"\n",(0,i.jsxs)(n.p,{children:["It accepts an ",(0,i.jsx)(n.code,{children:"expectation"})," to be validated and repeats the check every defined interval until it no longer throws an error. Similarly to ",(0,i.jsx)(n.code,{children:"findBy*"})," queries they accept ",(0,i.jsx)(n.code,{children:"timeout"})," and ",(0,i.jsx)(n.code,{children:"interval"})," options and have the same default values of 1000ms for timeout, and a checking interval of 50 ms."]}),"\n",(0,i.jsxs)(n.h4,{id:"example-2",children:["Example",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#example-2",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-typescript",children:"await waitFor(() => expect(mockAPI).toHaveBeenCalledTimes(1));\n"})}),"\n",(0,i.jsxs)(n.p,{children:["If you want to use it with ",(0,i.jsx)(n.code,{children:"getBy*"})," queries, use the ",(0,i.jsx)(n.code,{children:"findBy*"})," queries instead, as they essentially do the same, but offer better developer experience."]}),"\n",(0,i.jsxs)(n.h3,{id:"waitforelementtoberemoved-function",children:[(0,i.jsx)(n.code,{children:"waitForElementToBeRemoved"})," function",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#waitforelementtoberemoved-function",children:"#"})]}),"\n",(0,i.jsxs)(n.p,{children:["A specialized function, ",(0,i.jsx)(n.a,{href:"/docs/api/misc/async#waitforelementtoberemoved",children:(0,i.jsx)(n.code,{children:"waitForElementToBeRemoved"})}),", is used to verify that a matching element was present but has since been removed."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-typescript",children:"function waitForElementToBeRemoved(\n expectation: () => T,\n options?: {\n timeout: number;\n interval: number;\n }\n): Promise {}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This function is, in a way, the negation of ",(0,i.jsx)(n.code,{children:"waitFor"})," as it expects the initial expectation to be true (not throw an error), only to turn invalid (start throwing errors) on subsequent runs. It operates using the same ",(0,i.jsx)(n.code,{children:"timeout"})," and ",(0,i.jsx)(n.code,{children:"interval"})," parameters as ",(0,i.jsx)(n.code,{children:"findBy*"})," queries and ",(0,i.jsx)(n.code,{children:"waitFor"}),"."]}),"\n",(0,i.jsxs)(n.h4,{id:"example-3",children:["Example",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#example-3",children:"#"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-typescript",children:"await waitForElementToBeRemoved(() => getByText('Hello World'));\n"})}),"\n",(0,i.jsxs)(n.h2,{id:"fake-timers",children:["Fake Timers",(0,i.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#fake-timers",children:"#"})]}),"\n",(0,i.jsxs)(n.p,{children:["Asynchronous tests can take long to execute due to the delays introduced by asynchronous operations. To mitigate this, fake timers can be used. These are particularly useful when delays are mere waits, such as the 130 milliseconds wait introduced by the UserEvent ",(0,i.jsx)(n.code,{children:"press()"})," event due to React Native runtime behavior or simulated 1000 wait in a API call mock. Fake timers allow for precise fast-forwarding through these wait periods."]}),"\n",(0,i.jsxs)(n.p,{children:["Here are the basics of using ",(0,i.jsx)(n.a,{href:"https://jestjs.io/docs/timer-mocks",target:"_blank",rel:"noopener noreferrer",children:"Jest fake timers"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Enable fake timers with: ",(0,i.jsx)(n.code,{children:"jest.useFakeTimers()"})]}),"\n",(0,i.jsxs)(n.li,{children:["Disable fake timers with: ",(0,i.jsx)(n.code,{children:"jest.useRealTimers()"})]}),"\n",(0,i.jsxs)(n.li,{children:["Advance fake timers forward with: ",(0,i.jsx)(n.code,{children:"jest.advanceTimersByTime(interval)"})]}),"\n",(0,i.jsxs)(n.li,{children:["Run ",(0,i.jsx)(n.strong,{children:"all timers"})," to completion with: ",(0,i.jsx)(n.code,{children:"jest.runAllTimers()"})]}),"\n",(0,i.jsxs)(n.li,{children:["Run ",(0,i.jsx)(n.strong,{children:"currently pending timers"})," to completion with: ",(0,i.jsx)(n.code,{children:"jest.runOnlyPendingTimers()"})]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Be cautious when running all timers to completion as it might create an infinite loop if these timers schedule follow-up timers. In such cases, it's safer to use ",(0,i.jsx)(n.code,{children:"jest.runOnlyPendingTimers()"})," to avoid ending up in an infinite loop of scheduled tasks."]}),"\n",(0,i.jsxs)(n.p,{children:["You can use both built-in Jest fake timers, as well as ",(0,i.jsx)(n.a,{href:"https://sinonjs.org/releases/latest/fake-timers/",target:"_blank",rel:"noopener noreferrer",children:"Sinon.JS fake timers"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Note: you do not need to advance timers by hand when using User Event API, as it's automatically."})]})}function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,t.ah)(),e.components);return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(r,{...e})}):r(e)}let o=a;a.__RSPRESS_PAGE_META={},a.__RSPRESS_PAGE_META["14.x%2Fcookbook%2Fbasics%2Fasync-tests.md"]={toc:[{text:"Summary",id:"summary",depth:2},{text:"Example",id:"example",depth:3},{text:"Async utilities",id:"async-utilities",depth:2},{text:"`findBy*` queries",id:"findby-queries",depth:3},{text:"Example",id:"example-1",depth:4},{text:"`waitFor` function",id:"waitfor-function",depth:3},{text:"Example",id:"example-2",depth:4},{text:"`waitForElementToBeRemoved` function",id:"waitforelementtoberemoved-function",depth:3},{text:"Example",id:"example-3",depth:4},{text:"Fake Timers",id:"fake-timers",depth:2}],title:"Async tests",headingTitle:"Async tests",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/3858.22f98cfe.js b/static/js/async/3858.22f98cfe.js new file mode 100644 index 00000000..9e3deb12 --- /dev/null +++ b/static/js/async/3858.22f98cfe.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["3858"],{68:function(e,n,i){i.r(n),i.d(n,{default:()=>o});var t=i(5893),r=i(65);function s(e){let n=Object.assign({h1:"h1",a:"a",h2:"h2",code:"code",p:"p",pre:"pre",div:"div",h3:"h3",ul:"ul",li:"li"},(0,r.ah)(),e.components);return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.h1,{id:"async-utilities",children:["Async utilities",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#async-utilities",children:"#"})]}),"\n",(0,t.jsxs)(n.h2,{id:"findby-queries",children:[(0,t.jsx)(n.code,{children:"findBy*"})," queries",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#findby-queries",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"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 ",(0,t.jsx)(n.a,{href:"/docs/api/queries#find-by",children:"here"}),"."]}),"\n",(0,t.jsxs)(n.h2,{id:"waitfor",children:[(0,t.jsx)(n.code,{children:"waitFor"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#waitfor",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",children:"function waitFor(\n expectation: () => T,\n options?: {\n timeout?: number;\n interval?: number;\n onTimeout?: (error: Error) => Error;\n }\n): Promise;\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Waits for a period of time for the ",(0,t.jsx)(n.code,{children:"expectation"})," callback to pass. ",(0,t.jsx)(n.code,{children:"waitFor"})," may run the callback a number of times until timeout is reached, as specified by the ",(0,t.jsx)(n.code,{children:"timeout"})," and ",(0,t.jsx)(n.code,{children:"interval"})," options. The callback must throw an error when the expectation is not met. Returning any value, including a falsy one, will be treated as meeting the expectation, and the callback result will be returned to the caller of ",(0,t.jsx)(n.code,{children:"waitFor"})," function."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",children:"await waitFor(() => expect(mockFunction).toHaveBeenCalledWith());\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"waitFor"})," function will be executing ",(0,t.jsx)(n.code,{children:"expectation"})," callback every ",(0,t.jsx)(n.code,{children:"interval"})," (default: every 50 ms) until ",(0,t.jsx)(n.code,{children:"timeout"})," (default: 1000 ms) is reached. The repeated execution of callback is stopped as soon as it does not throw an error, in such case the value returned by the callback is returned to ",(0,t.jsx)(n.code,{children:"waitFor"})," caller. Otherwise, when it reaches the timeout, the final error thrown by ",(0,t.jsx)(n.code,{children:"expectation"})," will be re-thrown by ",(0,t.jsx)(n.code,{children:"waitFor"})," to the calling code."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",children:"// ❌ `waitFor` will return immediately because callback does not throw\nawait waitFor(() => false);\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"waitFor"})," is an async function so you need to ",(0,t.jsx)(n.code,{children:"await"})," the result to pause test execution."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-jsx",children:"// ❌ missing `await`: `waitFor` will just return Promise that will be rejected when the timeout is reached\nwaitFor(() => expect(1).toBe(2));\n"})}),"\n",(0,t.jsxs)(n.div,{className:"rspress-directive note",children:[(0,t.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,t.jsx)(n.div,{className:"rspress-directive-content",children:(0,t.jsxs)(n.p,{children:["You can enforce awaiting ",(0,t.jsx)(n.code,{children:"waitFor"})," by using the ",(0,t.jsx)(n.a,{href:"https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/await-async-utils.md",target:"_blank",rel:"noopener noreferrer",children:"await-async-utils"})," rule from ",(0,t.jsx)(n.a,{href:"https://github.com/testing-library/eslint-plugin-testing-library",target:"_blank",rel:"noopener noreferrer",children:"eslint-plugin-testing-library"}),".\n"]})})]}),"\n",(0,t.jsxs)(n.p,{children:["Since ",(0,t.jsx)(n.code,{children:"waitFor"})," is likely to run ",(0,t.jsx)(n.code,{children:"expectation"})," callback multiple times, it is highly recommended for it ",(0,t.jsx)(n.a,{href:"https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#performing-side-effects-in-waitfor",target:"_blank",rel:"noopener noreferrer",children:"not to perform any side effects"})," in ",(0,t.jsx)(n.code,{children:"waitFor"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-jsx",children:"await waitFor(async () => {\n // ❌ button will be pressed on each waitFor iteration\n await fireEvent.press(screen.getByText('press me'));\n expect(mockOnPress).toHaveBeenCalled();\n});\n"})}),"\n",(0,t.jsxs)(n.div,{className:"rspress-directive note",children:[(0,t.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,t.jsx)(n.div,{className:"rspress-directive-content",children:(0,t.jsxs)(n.p,{children:["Avoiding side effects in ",(0,t.jsx)(n.code,{children:"expectation"})," callback can be partially enforced with the ",(0,t.jsxs)(n.a,{href:"https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-wait-for-side-effects.md",target:"_blank",rel:"noopener noreferrer",children:[(0,t.jsx)(n.code,{children:"no-wait-for-side-effects"})," rule"]}),".\n"]})})]}),"\n",(0,t.jsxs)(n.p,{children:["It is also recommended to have a ",(0,t.jsxs)(n.a,{href:"https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#having-multiple-assertions-in-a-single-waitfor-callback",target:"_blank",rel:"noopener noreferrer",children:["single assertion per each ",(0,t.jsx)(n.code,{children:"waitFor"})]})," for more consistency and faster failing tests. If you want to make several assertions, then they should be in seperate ",(0,t.jsx)(n.code,{children:"waitFor"})," calls. In many cases you won't actually need to wrap the second assertion in ",(0,t.jsx)(n.code,{children:"waitFor"})," since the first one will do the waiting required for asynchronous change to happen."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"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:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",children:"let fakeTimeRemaining = timeout;\nlet lastError;\n\nwhile (fakeTimeRemaining > 0) {\n fakeTimeRemaining = fakeTimeRemaining - interval;\n jest.advanceTimersByTime(interval);\n try {\n // resolve\n return expectation();\n } catch (error) {\n lastError = error;\n }\n}\n\n// reject\nthrow lastError;\n"})}),"\n",(0,t.jsxs)(n.p,{children:["In the following example we test that a function is called after 10 seconds using fake timers. Since we're using fake timers, the test won't depend on real time passing and thus be much faster and more reliable. Also we don't have to advance fake timers through Jest fake timers API because ",(0,t.jsx)(n.code,{children:"waitFor"})," already does this for us."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",children:"// in component\nsetTimeout(() => {\n someFunction();\n}, 10000);\n\n// in test\njest.useFakeTimers();\n\nawait waitFor(\n () => {\n expect(someFunction).toHaveBeenCalledWith();\n },\n { timeout: 10000 }\n);\n"})}),"\n",(0,t.jsxs)(n.div,{className:"rspress-directive note",children:[(0,t.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,t.jsx)(n.div,{className:"rspress-directive-content",children:(0,t.jsxs)(n.p,{children:["If you receive warnings related to ",(0,t.jsx)(n.code,{children:"act()"})," function consult our ",(0,t.jsx)(n.a,{href:"/docs/advanced/understanding-act",children:"Understanding Act"})," function document.\n"]})})]}),"\n",(0,t.jsxs)(n.h3,{id:"options",children:["Options",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#options",children:"#"})]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"timeout"}),": How long to wait for, in ms. Defaults to 1000 ms (configured by ",(0,t.jsx)(n.code,{children:"asyncUtilTimeout"})," option)."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"interval"}),": How often to check, in ms. Defaults to 50 ms."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"onTimeout"}),": Callback to transform the error before it's thrown. Useful for debugging, e.g., ",(0,t.jsx)(n.code,{children:"onTimeout: () => { screen.debug(); }"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.h2,{id:"waitforelementtoberemoved",children:[(0,t.jsx)(n.code,{children:"waitForElementToBeRemoved"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#waitforelementtoberemoved",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"function waitForElementToBeRemoved(\n expectation: () => T,\n options?: {\n timeout?: number;\n interval?: number;\n onTimeout?: (error: Error) => Error;\n }\n): Promise;\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Waits for non-deterministic periods of time until queried element is removed or times out. ",(0,t.jsx)(n.code,{children:"waitForElementToBeRemoved"})," periodically calls ",(0,t.jsx)(n.code,{children:"expectation"})," every ",(0,t.jsx)(n.code,{children:"interval"})," milliseconds to determine whether the element has been removed or not."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-jsx",children:"import { render, screen, waitForElementToBeRemoved } from '@testing-library/react-native';\n\ntest('waiting for an Banana to be removed', async () => {\n await render();\n\n await waitForElementToBeRemoved(() => screen.getByText('Banana ready'));\n});\n"})}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["You can use any of ",(0,t.jsx)(n.code,{children:"getBy"}),", ",(0,t.jsx)(n.code,{children:"getAllBy"}),", ",(0,t.jsx)(n.code,{children:"queryBy"})," and ",(0,t.jsx)(n.code,{children:"queryAllBy"})," queries for ",(0,t.jsx)(n.code,{children:"expectation"})," parameter."]}),"\n",(0,t.jsxs)(n.div,{className:"rspress-directive note",children:[(0,t.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,t.jsx)(n.div,{className:"rspress-directive-content",children:(0,t.jsxs)(n.p,{children:["If you receive warnings related to ",(0,t.jsx)(n.code,{children:"act()"})," function consult our ",(0,t.jsx)(n.a,{href:"/docs/advanced/understanding-act",children:"Understanding Act"})," function document.\n"]})})]})]})}function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,r.ah)(),e.components);return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(s,{...e})}):s(e)}let o=a;a.__RSPRESS_PAGE_META={},a.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fapi%2Fmisc%2Fasync.mdx"]={toc:[{text:"`findBy*` queries",id:"findby-queries",depth:2},{text:"`waitFor`",id:"waitfor",depth:2},{text:"Options",id:"options",depth:3},{text:"`waitForElementToBeRemoved`",id:"waitforelementtoberemoved",depth:2}],title:"Async utilities",headingTitle:"Async utilities",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/3858.3ac4becb.js b/static/js/async/3858.3ac4becb.js deleted file mode 100644 index 09aab9fe..00000000 --- a/static/js/async/3858.3ac4becb.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["3858"],{68:function(e,n,i){i.r(n),i.d(n,{default:()=>c});var t=i(5893),r=i(65);function s(e){let n=Object.assign({h1:"h1",a:"a",h2:"h2",code:"code",p:"p",pre:"pre",div:"div"},(0,r.ah)(),e.components);return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.h1,{id:"async-utilities",children:["Async utilities",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#async-utilities",children:"#"})]}),"\n",(0,t.jsxs)(n.h2,{id:"findby-queries",children:[(0,t.jsx)(n.code,{children:"findBy*"})," queries",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#findby-queries",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"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 ",(0,t.jsx)(n.a,{href:"/docs/api/queries#find-by",children:"here"}),"."]}),"\n",(0,t.jsxs)(n.h2,{id:"waitfor",children:[(0,t.jsx)(n.code,{children:"waitFor"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#waitfor",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",children:"function waitFor(\n expectation: () => T,\n options?: { timeout: number; interval: number }\n): Promise;\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Waits for a period of time for the ",(0,t.jsx)(n.code,{children:"expectation"})," callback to pass. ",(0,t.jsx)(n.code,{children:"waitFor"})," may run the callback a number of times until timeout is reached, as specified by the ",(0,t.jsx)(n.code,{children:"timeout"})," and ",(0,t.jsx)(n.code,{children:"interval"})," options. The callback must throw an error when the expectation is not met. Returning any value, including a falsy one, will be treated as meeting the expectation, and the callback result will be returned to the caller of ",(0,t.jsx)(n.code,{children:"waitFor"})," function."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",children:"await waitFor(() => expect(mockFunction).toHaveBeenCalledWith());\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"waitFor"})," function will be executing ",(0,t.jsx)(n.code,{children:"expectation"})," callback every ",(0,t.jsx)(n.code,{children:"interval"})," (default: every 50 ms) until ",(0,t.jsx)(n.code,{children:"timeout"})," (default: 1000 ms) is reached. The repeated execution of callback is stopped as soon as it does not throw an error, in such case the value returned by the callback is returned to ",(0,t.jsx)(n.code,{children:"waitFor"})," caller. Otherwise, when it reaches the timeout, the final error thrown by ",(0,t.jsx)(n.code,{children:"expectation"})," will be re-thrown by ",(0,t.jsx)(n.code,{children:"waitFor"})," to the calling code."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",children:"// ❌ `waitFor` will return immediately because callback does not throw\nawait waitFor(() => false);\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"waitFor"})," is an async function so you need to ",(0,t.jsx)(n.code,{children:"await"})," the result to pause test execution."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-jsx",children:"// ❌ missing `await`: `waitFor` will just return Promise that will be rejected when the timeout is reached\nwaitFor(() => expect(1).toBe(2));\n"})}),"\n",(0,t.jsxs)(n.div,{className:"rspress-directive note",children:[(0,t.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,t.jsx)(n.div,{className:"rspress-directive-content",children:(0,t.jsxs)(n.p,{children:["You can enforce awaiting ",(0,t.jsx)(n.code,{children:"waitFor"})," by using the ",(0,t.jsx)(n.a,{href:"https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/await-async-utils.md",target:"_blank",rel:"noopener noreferrer",children:"await-async-utils"})," rule from ",(0,t.jsx)(n.a,{href:"https://github.com/testing-library/eslint-plugin-testing-library",target:"_blank",rel:"noopener noreferrer",children:"eslint-plugin-testing-library"}),".\n"]})})]}),"\n",(0,t.jsxs)(n.p,{children:["Since ",(0,t.jsx)(n.code,{children:"waitFor"})," is likely to run ",(0,t.jsx)(n.code,{children:"expectation"})," callback multiple times, it is highly recommended for it ",(0,t.jsx)(n.a,{href:"https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#performing-side-effects-in-waitfor",target:"_blank",rel:"noopener noreferrer",children:"not to perform any side effects"})," in ",(0,t.jsx)(n.code,{children:"waitFor"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-jsx",children:"await waitFor(() => {\n // ❌ button will be pressed on each waitFor iteration\n fireEvent.press(screen.getByText('press me'));\n expect(mockOnPress).toHaveBeenCalled();\n});\n"})}),"\n",(0,t.jsxs)(n.div,{className:"rspress-directive note",children:[(0,t.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,t.jsx)(n.div,{className:"rspress-directive-content",children:(0,t.jsxs)(n.p,{children:["Avoiding side effects in ",(0,t.jsx)(n.code,{children:"expectation"})," callback can be partially enforced with the ",(0,t.jsxs)(n.a,{href:"https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-wait-for-side-effects.md",target:"_blank",rel:"noopener noreferrer",children:[(0,t.jsx)(n.code,{children:"no-wait-for-side-effects"})," rule"]}),".\n"]})})]}),"\n",(0,t.jsxs)(n.p,{children:["It is also recommended to have a ",(0,t.jsxs)(n.a,{href:"https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#having-multiple-assertions-in-a-single-waitfor-callback",target:"_blank",rel:"noopener noreferrer",children:["single assertion per each ",(0,t.jsx)(n.code,{children:"waitFor"})]})," for more consistency and faster failing tests. If you want to make several assertions, then they should be in seperate ",(0,t.jsx)(n.code,{children:"waitFor"})," calls. In many cases you won't actually need to wrap the second assertion in ",(0,t.jsx)(n.code,{children:"waitFor"})," since the first one will do the waiting required for asynchronous change to happen."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"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:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",children:"let fakeTimeRemaining = timeout;\nlet lastError;\n\nwhile (fakeTimeRemaining > 0) {\n fakeTimeRemaining = fakeTimeRemaining - interval;\n jest.advanceTimersByTime(interval);\n try {\n // resolve\n return expectation();\n } catch (error) {\n lastError = error;\n }\n}\n\n// reject\nthrow lastError;\n"})}),"\n",(0,t.jsxs)(n.p,{children:["In the following example we test that a function is called after 10 seconds using fake timers. Since we're using fake timers, the test won't depend on real time passing and thus be much faster and more reliable. Also we don't have to advance fake timers through Jest fake timers API because ",(0,t.jsx)(n.code,{children:"waitFor"})," already does this for us."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",children:"// in component\nsetTimeout(() => {\n someFunction();\n}, 10000);\n\n// in test\njest.useFakeTimers();\n\nawait waitFor(() => {\n expect(someFunction).toHaveBeenCalledWith();\n}, 10000);\n"})}),"\n",(0,t.jsxs)(n.div,{className:"rspress-directive note",children:[(0,t.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,t.jsx)(n.div,{className:"rspress-directive-content",children:(0,t.jsxs)(n.p,{children:["If you receive warnings related to ",(0,t.jsx)(n.code,{children:"act()"})," function consult our ",(0,t.jsx)(n.a,{href:"/docs/advanced/understanding-act",children:"Understanding Act"})," function document.\n"]})})]}),"\n",(0,t.jsxs)(n.h2,{id:"waitforelementtoberemoved",children:[(0,t.jsx)(n.code,{children:"waitForElementToBeRemoved"}),(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#waitforelementtoberemoved",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ts",children:"function waitForElementToBeRemoved(\n expectation: () => T,\n options?: { timeout: number; interval: number }\n): Promise;\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Waits for non-deterministic periods of time until queried element is removed or times out. ",(0,t.jsx)(n.code,{children:"waitForElementToBeRemoved"})," periodically calls ",(0,t.jsx)(n.code,{children:"expectation"})," every ",(0,t.jsx)(n.code,{children:"interval"})," milliseconds to determine whether the element has been removed or not."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-jsx",children:"import { render, screen, waitForElementToBeRemoved } from '@testing-library/react-native';\n\ntest('waiting for an Banana to be removed', async () => {\n render();\n\n await waitForElementToBeRemoved(() => screen.getByText('Banana ready'));\n});\n"})}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["You can use any of ",(0,t.jsx)(n.code,{children:"getBy"}),", ",(0,t.jsx)(n.code,{children:"getAllBy"}),", ",(0,t.jsx)(n.code,{children:"queryBy"})," and ",(0,t.jsx)(n.code,{children:"queryAllBy"})," queries for ",(0,t.jsx)(n.code,{children:"expectation"})," parameter."]}),"\n",(0,t.jsxs)(n.div,{className:"rspress-directive note",children:[(0,t.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,t.jsx)(n.div,{className:"rspress-directive-content",children:(0,t.jsxs)(n.p,{children:["If you receive warnings related to ",(0,t.jsx)(n.code,{children:"act()"})," function consult our ",(0,t.jsx)(n.a,{href:"/docs/advanced/understanding-act",children:"Understanding Act"})," function document.\n"]})})]})]})}function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,r.ah)(),e.components);return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(s,{...e})}):s(e)}let c=a;a.__RSPRESS_PAGE_META={},a.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fapi%2Fmisc%2Fasync.mdx"]={toc:[{text:"`findBy*` queries",id:"findby-queries",depth:2},{text:"`waitFor`",id:"waitfor",depth:2},{text:"`waitForElementToBeRemoved`",id:"waitforelementtoberemoved",depth:2}],title:"Async utilities",headingTitle:"Async utilities",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/435.2768959d.js b/static/js/async/435.2768959d.js deleted file mode 100644 index 796c9889..00000000 --- a/static/js/async/435.2768959d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["435"],{6942:function(e,n,t){t.r(n),t.d(n,{default:()=>i});var s=t(5893),r=t(65);function a(e){let n=Object.assign({h1:"h1",code:"code",a:"a",p:"p",h2:"h2",pre:"pre",h3:"h3",strong:"strong",ul:"ul",li:"li"},(0,r.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.h1,{id:"understanding-act-function",children:["Understanding ",(0,s.jsx)(n.code,{children:"act"})," function",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#understanding-act-function",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["When writing RNTL tests one of the things that confuses developers the most are cryptic ",(0,s.jsx)(n.a,{href:"https://reactjs.org/docs/testing-recipes.html#act",target:"_blank",rel:"noopener noreferrer",children:(0,s.jsx)(n.code,{children:"act()"})})," function errors logged into console. In this article I will try to build an understanding of the purpose and behaviour of ",(0,s.jsx)(n.code,{children:"act()"})," so you can build your tests with more confidence."]}),"\n",(0,s.jsxs)(n.h2,{id:"act-warnings",children:[(0,s.jsx)(n.code,{children:"act"})," warnings",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#act-warnings",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["Let’s start with typical ",(0,s.jsx)(n.code,{children:"act()"}),' warnings logged to console. There are two kinds of these issues, let’s call the first one the "sync ',(0,s.jsx)(n.code,{children:"act()"}),'" warning:']}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"Warning: An update to Component inside a test was not wrapped in act(...).\n\nWhen testing, code that causes React state updates should be wrapped into act(...):\n\nact(() => {\n /* fire events that update state */\n});\n/* assert on the output */\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The second one relates to async usage of ",(0,s.jsx)(n.code,{children:"act"}),' so let’s call it the "async ',(0,s.jsx)(n.code,{children:"act"}),'" error:']}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"Warning: You called act(async () => ...) without await. This could lead to unexpected\ntesting behaviour, interleaving multiple act calls and mixing their scopes. You should\n- await act(async () => ...);\n"})}),"\n",(0,s.jsxs)(n.h2,{id:"synchronous-act",children:["Synchronous ",(0,s.jsx)(n.code,{children:"act"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#synchronous-act",children:"#"})]}),"\n",(0,s.jsxs)(n.h3,{id:"responsibility",children:["Responsibility",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#responsibility",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"This function is intended only for using in automated tests and works only in development mode. Attempting to use it in production build will throw an error."}),"\n",(0,s.jsxs)(n.p,{children:["The responsibility for ",(0,s.jsx)(n.code,{children:"act"})," function is to make React renders and updates work in tests in a similar way they work in real application by grouping and executing related units of interaction (e.g. renders, effects, etc) together."]}),"\n",(0,s.jsxs)(n.p,{children:["To showcase that behaviour let make a small experiment. First we define a function component that uses ",(0,s.jsx)(n.code,{children:"useEffect"})," hook in a trivial way."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"function TestComponent() {\n const [count, setCount] = React.useState(0);\n React.useEffect(() => {\n setCount((c) => c + 1);\n }, []);\n\n return Count {count};\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["In the following tests we will directly use ",(0,s.jsx)(n.code,{children:"ReactTestRenderer"})," instead of RNTL ",(0,s.jsx)(n.code,{children:"render"})," function to render our component for tests. In order to expose familiar queries like ",(0,s.jsx)(n.code,{children:"getByText"})," we will use ",(0,s.jsx)(n.code,{children:"within"})," function from RNTL."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"test('render without act', () => {\n const renderer = TestRenderer.create();\n\n // Bind RNTL queries for root element.\n const view = within(renderer.root);\n expect(view.getByText('Count 0')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When testing without ",(0,s.jsx)(n.code,{children:"act"})," call wrapping rendering call, we see that the assertion runs just after the rendering but before ",(0,s.jsx)(n.code,{children:"useEffect"}),"hooks effects are applied. Which is not what we expected in our tests."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"test('render with act', async () => {\n let renderer: ReactTestRenderer;\n await act(async () => {\n renderer = TestRenderer.create();\n });\n\n // Bind RNTL queries for root element.\n const view = within(renderer!.root);\n expect(view.getByText('Count 1')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Note"}),": In v14, ",(0,s.jsx)(n.code,{children:"act"})," is now async by default and always returns a Promise. Even if your callback is synchronous, you should use ",(0,s.jsx)(n.code,{children:"await act(async () => ...)"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["When wrapping rendering call with ",(0,s.jsx)(n.code,{children:"act"})," we see that the changes caused by ",(0,s.jsx)(n.code,{children:"useEffect"})," hook have been applied as we would expect."]}),"\n",(0,s.jsxs)(n.h3,{id:"when-to-use-act",children:["When to use act",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#when-to-use-act",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["The name ",(0,s.jsx)(n.code,{children:"act"})," comes from ",(0,s.jsx)(n.a,{href:"http://wiki.c2.com/?ArrangeActAssert",target:"_blank",rel:"noopener noreferrer",children:"Arrange-Act-Assert"})," unit testing pattern. Which means it’s related to part of the test when we execute some actions on the component tree."]}),"\n",(0,s.jsxs)(n.p,{children:["So far we learned that ",(0,s.jsx)(n.code,{children:"act"})," function allows tests to wait for all pending React interactions to be applied before we make our assertions. When using ",(0,s.jsx)(n.code,{children:"act"})," we get guarantee that any state updates will be executed as well as any enqueued effects will be executed."]}),"\n",(0,s.jsxs)(n.p,{children:["Therefore, we should use ",(0,s.jsx)(n.code,{children:"act"})," whenever there is some action that causes element tree to render, particularly:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["initial render call - ",(0,s.jsx)(n.code,{children:"ReactTestRenderer.create"})," call"]}),"\n",(0,s.jsxs)(n.li,{children:["re-rendering of component -",(0,s.jsx)(n.code,{children:"renderer.rerender"})," call"]}),"\n",(0,s.jsx)(n.li,{children:"triggering any event handlers that cause component tree render"}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Thankfully, for these basic cases RNTL has got you covered as our ",(0,s.jsx)(n.code,{children:"render"}),", ",(0,s.jsx)(n.code,{children:"rerender"})," and ",(0,s.jsx)(n.code,{children:"fireEvent"})," methods already wrap their calls in ",(0,s.jsx)(n.code,{children:"act"})," so that you do not have to do it explicitly."]}),"\n",(0,s.jsxs)(n.p,{children:["Note that ",(0,s.jsx)(n.code,{children:"act"})," calls can be safely nested and internally form a stack of calls. However, overlapping ",(0,s.jsx)(n.code,{children:"act"})," calls, which can be achieved using async version of ",(0,s.jsx)(n.code,{children:"act"}),", ",(0,s.jsx)(n.a,{href:"https://github.com/facebook/react/blob/main/packages/react/src/ReactAct.js#L161",target:"_blank",rel:"noopener noreferrer",children:"are not supported"}),"."]}),"\n",(0,s.jsxs)(n.h3,{id:"implementation",children:["Implementation",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#implementation",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["As of React version of 18.1.0, the ",(0,s.jsx)(n.code,{children:"act"})," implementation is defined in the ",(0,s.jsx)(n.a,{href:"https://github.com/facebook/react/blob/main/packages/react/src/ReactAct.js",target:"_blank",rel:"noopener noreferrer",children:"ReactAct.js source file"})," inside React repository. This implementation has been fairly stable since React 17.0."]}),"\n",(0,s.jsxs)(n.p,{children:["RNTL exports ",(0,s.jsx)(n.code,{children:"act"})," for convenience of the users as defined in the ",(0,s.jsx)(n.a,{href:"https://github.com/callstack/react-native-testing-library/blob/main/src/act.ts",target:"_blank",rel:"noopener noreferrer",children:"act.ts source file"}),". In v14, ",(0,s.jsx)(n.code,{children:"act"})," is now async by default and always returns a Promise, making it compatible with React 19, React Suspense, and ",(0,s.jsx)(n.code,{children:"React.use()"}),". The underlying implementation still uses React's ",(0,s.jsx)(n.code,{children:"act"})," function, but wraps it to ensure consistent async behavior."]}),"\n",(0,s.jsxs)(n.h2,{id:"asynchronous-act",children:["Asynchronous ",(0,s.jsx)(n.code,{children:"act"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#asynchronous-act",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["So far we have seen synchronous version of ",(0,s.jsx)(n.code,{children:"act"})," which runs its callback immediately. This can deal with things like synchronous effects or mocks using already resolved promises. However, not all component code is synchronous. Frequently our components or mocks contain some asynchronous behaviours like ",(0,s.jsx)(n.code,{children:"setTimeout"})," calls or network calls. Starting from React 16.9, ",(0,s.jsx)(n.code,{children:"act"})," can also be called in asynchronous mode. In such case ",(0,s.jsx)(n.code,{children:"act"})," implementation checks that the passed callback returns ",(0,s.jsx)(n.a,{href:"https://github.com/facebook/react/blob/ce13860281f833de8a3296b7a3dad9caced102e9/packages/react/src/ReactAct.js#L60",target:"_blank",rel:"noopener noreferrer",children:"object resembling promise"}),"."]}),"\n",(0,s.jsxs)(n.h3,{id:"asynchronous-code",children:["Asynchronous code",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#asynchronous-code",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["Asynchronous version of ",(0,s.jsx)(n.code,{children:"act"})," also is executed immediately, but the callback is not yet completed because of some asynchronous operations inside."]}),"\n",(0,s.jsxs)(n.p,{children:["Lets look at a simple example with component using ",(0,s.jsx)(n.code,{children:"setTimeout"})," call to simulate asynchronous behaviour:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"function TestAsyncComponent() {\n const [count, setCount] = React.useState(0);\n React.useEffect(() => {\n setTimeout(() => {\n setCount((c) => c + 1);\n }, 50);\n }, []);\n\n return Count {count};\n}\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"import { render, screen } from '@testing-library/react-native';\n\ntest('render async natively', () => {\n render();\n expect(screen.getByText('Count 0')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsx)(n.p,{children:"If we test our component in a native way without handling its asynchronous behaviour we will end up with sync act warning:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"Warning: An update to TestAsyncComponent inside a test was not wrapped in act(...).\n\nWhen testing, code that causes React state updates should be wrapped into act(...):\n\nact(() => {\n /* fire events that update state */\n});\n/* assert on the output */\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Note that this is not yet the infamous async act warning. It only asks us to wrap our event code with ",(0,s.jsx)(n.code,{children:"act"})," calls. However, this time our immediate state change does not originate from externally triggered events but rather forms an internal part of the component. So how can we apply ",(0,s.jsx)(n.code,{children:"act"})," in such scenario?"]}),"\n",(0,s.jsxs)(n.h3,{id:"solution-with-fake-timers",children:["Solution with fake timers",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#solution-with-fake-timers",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"First solution is to use Jest's fake timers inside out tests:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"test('render with fake timers', async () => {\n jest.useFakeTimers();\n render();\n\n await act(async () => {\n jest.runAllTimers();\n });\n expect(screen.getByText('Count 1')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Note"}),": In v14, ",(0,s.jsx)(n.code,{children:"act"})," is now async by default, so you should await it even when using fake timers."]}),"\n",(0,s.jsxs)(n.p,{children:["That way we can wrap ",(0,s.jsx)(n.code,{children:"jest.runAllTimers()"})," call which triggers the ",(0,s.jsx)(n.code,{children:"setTimeout"})," updates inside an ",(0,s.jsx)(n.code,{children:"act"})," call, hence resolving the act warning. Note that this whole code is synchronous thanks to usage of Jest fake timers."]}),"\n",(0,s.jsxs)(n.h3,{id:"solution-with-real-timers",children:["Solution with real timers",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#solution-with-real-timers",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["If we wanted to stick with real timers then things get a bit more complex. Let’s start by applying a crude solution of opening async ",(0,s.jsx)(n.code,{children:"act()"})," call for the expected duration of components updates:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"test('render with real timers - sleep', async () => {\n render();\n await act(async () => {\n await sleep(100); // Wait a bit longer than setTimeout in `TestAsyncComponent`\n });\n\n expect(screen.getByText('Count 1')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This works correctly as we use an explicit async ",(0,s.jsx)(n.code,{children:"act()"})," call that resolves the console error. However, it relies on our knowledge of exact implementation details which is a bad practice."]}),"\n",(0,s.jsxs)(n.p,{children:["Let’s try more elegant solution using ",(0,s.jsx)(n.code,{children:"waitFor"})," that will wait for our desired state:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"test('render with real timers - waitFor', async () => {\n render();\n\n await waitFor(() => screen.getByText('Count 1'));\n expect(screen.getByText('Count 1')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This also works correctly, because ",(0,s.jsx)(n.code,{children:"waitFor"})," call executes async ",(0,s.jsx)(n.code,{children:"act()"})," call internally."]}),"\n",(0,s.jsxs)(n.p,{children:["The above code can be simplified using ",(0,s.jsx)(n.code,{children:"findBy"})," query:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"test('render with real timers - findBy', async () => {\n render();\n\n expect(await screen.findByText('Count 1')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This also works since ",(0,s.jsx)(n.code,{children:"findByText"})," internally calls ",(0,s.jsx)(n.code,{children:"waitFor"})," which uses async ",(0,s.jsx)(n.code,{children:"act()"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Note that all of the above examples are async tests using & awaiting async ",(0,s.jsx)(n.code,{children:"act()"})," function call."]}),"\n",(0,s.jsxs)(n.h3,{id:"async-act-warning",children:["Async act warning",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#async-act-warning",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["If we modify any of the above async tests and remove ",(0,s.jsx)(n.code,{children:"await"})," keyword, then we will trigger the notorious async ",(0,s.jsx)(n.code,{children:"act()"}),"warning:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"Warning: You called act(async () => ...) without await. This could lead to unexpected\ntesting behaviour, interleaving multiple act calls and mixing their scopes. You should\n- await act(async () => ...);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["React decides to show this error whenever it detects that async ",(0,s.jsx)(n.code,{children:"act()"}),"call ",(0,s.jsx)(n.a,{href:"https://github.com/facebook/react/blob/ce13860281f833de8a3296b7a3dad9caced102e9/packages/react/src/ReactAct.js#L93",target:"_blank",rel:"noopener noreferrer",children:"has not been awaited"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["The exact reasons why you might see async ",(0,s.jsx)(n.code,{children:"act()"})," warnings vary, but finally it means that ",(0,s.jsx)(n.code,{children:"act()"})," has been called with callback that returns ",(0,s.jsx)(n.code,{children:"Promise"}),"-like object, but it has not been waited on."]}),"\n",(0,s.jsxs)(n.h2,{id:"references",children:["References",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#references",children:"#"})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsxs)(n.a,{href:"https://github.com/facebook/react/blob/main/packages/react/src/ReactAct.js",target:"_blank",rel:"noopener noreferrer",children:["React ",(0,s.jsx)(n.code,{children:"act"})," implementation source"]})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsxs)(n.a,{href:"https://reactjs.org/docs/testing-recipes.html#act",target:"_blank",rel:"noopener noreferrer",children:["React testing recipes: ",(0,s.jsx)(n.code,{children:"act()"})]})}),"\n"]})]})}function c(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,r.ah)(),e.components);return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}let i=c;c.__RSPRESS_PAGE_META={},c.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fadvanced%2Funderstanding-act.mdx"]={toc:[{text:"`act` warnings",id:"act-warnings",depth:2},{text:"Synchronous `act`",id:"synchronous-act",depth:2},{text:"Responsibility",id:"responsibility",depth:3},{text:"When to use act",id:"when-to-use-act",depth:3},{text:"Implementation",id:"implementation",depth:3},{text:"Asynchronous `act`",id:"asynchronous-act",depth:2},{text:"Asynchronous code",id:"asynchronous-code",depth:3},{text:"Solution with fake timers",id:"solution-with-fake-timers",depth:3},{text:"Solution with real timers",id:"solution-with-real-timers",depth:3},{text:"Async act warning",id:"async-act-warning",depth:3},{text:"References",id:"references",depth:2}],title:"Understanding `act` function",headingTitle:"Understanding `act` function",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/435.be1e8f69.js b/static/js/async/435.be1e8f69.js new file mode 100644 index 00000000..89e2918e --- /dev/null +++ b/static/js/async/435.be1e8f69.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["435"],{6942:function(e,n,t){t.r(n),t.d(n,{default:()=>c});var s=t(5893),r=t(65);function a(e){let n=Object.assign({h1:"h1",code:"code",a:"a",p:"p",h2:"h2",pre:"pre",h3:"h3",strong:"strong",ul:"ul",li:"li"},(0,r.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.h1,{id:"understanding-act-function",children:["Understanding ",(0,s.jsx)(n.code,{children:"act"})," function",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#understanding-act-function",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["When writing RNTL tests one of the things that confuses developers the most are cryptic ",(0,s.jsx)(n.a,{href:"https://react.dev/link/wrap-tests-with-act",target:"_blank",rel:"noopener noreferrer",children:(0,s.jsx)(n.code,{children:"act()"})})," function errors logged into console. In this article I will try to build an understanding of the purpose and behaviour of ",(0,s.jsx)(n.code,{children:"act()"})," so you can build your tests with more confidence."]}),"\n",(0,s.jsxs)(n.h2,{id:"act-warning",children:[(0,s.jsx)(n.code,{children:"act"})," warning",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#act-warning",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["Let's start with a typical ",(0,s.jsx)(n.code,{children:"act()"})," warning logged to console:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"An update to Root inside a test was not wrapped in act(...).\n\nWhen testing, code that causes React state updates should be wrapped into act(...):\n\nact(() => {\n /* fire events that update state */\n});\n/* assert on the output */\n\nThis ensures that you're testing the behavior the user would see in the browser.\nLearn more at https://react.dev/link/wrap-tests-with-act\n"})}),"\n",(0,s.jsxs)(n.h2,{id:"understanding-act",children:["Understanding ",(0,s.jsx)(n.code,{children:"act"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#understanding-act",children:"#"})]}),"\n",(0,s.jsxs)(n.h3,{id:"responsibility",children:["Responsibility",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#responsibility",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"This function is intended only for using in automated tests and works only in development mode. Attempting to use it in production build will throw an error."}),"\n",(0,s.jsxs)(n.p,{children:["The responsibility for ",(0,s.jsx)(n.code,{children:"act"})," function is to make React renders and updates work in tests in a similar way they work in real application by grouping and executing related units of interaction (e.g. renders, effects, etc) together."]}),"\n",(0,s.jsxs)(n.p,{children:["To showcase that behaviour let make a small experiment. First we define a function component that uses ",(0,s.jsx)(n.code,{children:"useEffect"})," hook in a trivial way."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"function TestComponent() {\n const [count, setCount] = React.useState(0);\n React.useEffect(() => {\n setCount((c) => c + 1);\n }, []);\n\n return Count {count};\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["In the following tests we will directly use ",(0,s.jsx)(n.a,{href:"https://github.com/mdjastrzebski/test-renderer",target:"_blank",rel:"noopener noreferrer",children:"Test Renderer"})," instead of RNTL ",(0,s.jsx)(n.code,{children:"render"})," function to render our component for tests. In order to expose familiar queries like ",(0,s.jsx)(n.code,{children:"getByText"})," we will use ",(0,s.jsx)(n.code,{children:"within"})," function from RNTL."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"import { createRoot } from 'test-renderer';\nimport { within } from '@testing-library/react-native';\n\ntest('render without act', () => {\n const renderer = createRoot();\n renderer.render();\n\n // Bind RNTL queries for root element.\n const view = within(renderer.container);\n expect(view.getByText('Count 0')).toBeTruthy();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When testing without ",(0,s.jsx)(n.code,{children:"act"})," call wrapping rendering call, we see that the assertion runs just after the rendering but before ",(0,s.jsx)(n.code,{children:"useEffect"})," hooks effects are applied. Which is not what we expected in our tests."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"import { createRoot } from 'test-renderer';\nimport { act, within } from '@testing-library/react-native';\n\ntest('render with act', async () => {\n const renderer = createRoot();\n await act(() => {\n renderer.render();\n });\n\n // Bind RNTL queries for root element.\n const view = within(renderer.container);\n expect(view.getByText('Count 1')).toBeTruthy();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Note"}),": In v14, ",(0,s.jsx)(n.code,{children:"act"})," is now async by default and always returns a Promise. You should always use ",(0,s.jsx)(n.code,{children:"await act(...)"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["When wrapping rendering call with ",(0,s.jsx)(n.code,{children:"act"})," we see that the changes caused by ",(0,s.jsx)(n.code,{children:"useEffect"})," hook have been applied as we would expect."]}),"\n",(0,s.jsxs)(n.h3,{id:"when-to-use-act",children:["When to use act",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#when-to-use-act",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["The name ",(0,s.jsx)(n.code,{children:"act"})," comes from ",(0,s.jsx)(n.a,{href:"http://wiki.c2.com/?ArrangeActAssert",target:"_blank",rel:"noopener noreferrer",children:"Arrange-Act-Assert"})," unit testing pattern. Which means it's related to part of the test when we execute some actions on the component tree."]}),"\n",(0,s.jsxs)(n.p,{children:["So far we learned that ",(0,s.jsx)(n.code,{children:"act"})," function allows tests to wait for all pending React interactions to be applied before we make our assertions. When using ",(0,s.jsx)(n.code,{children:"act"})," we get guarantee that any state updates will be executed as well as any enqueued effects will be executed."]}),"\n",(0,s.jsxs)(n.p,{children:["Therefore, we should use ",(0,s.jsx)(n.code,{children:"act"})," whenever there is some action that causes element tree to render, particularly:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["initial render call - ",(0,s.jsx)(n.code,{children:"renderer.render"})," call"]}),"\n",(0,s.jsxs)(n.li,{children:["re-rendering of component - ",(0,s.jsx)(n.code,{children:"renderer.render"})," call with updated element"]}),"\n",(0,s.jsx)(n.li,{children:"triggering any event handlers that cause component tree render"}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Thankfully, for these basic cases RNTL has got you covered as our ",(0,s.jsx)(n.code,{children:"render"}),", ",(0,s.jsx)(n.code,{children:"rerender"})," and ",(0,s.jsx)(n.code,{children:"fireEvent"})," methods already wrap their calls in ",(0,s.jsx)(n.code,{children:"act"})," so that you do not have to do it explicitly. In v14, these functions are all async and should be awaited."]}),"\n",(0,s.jsxs)(n.p,{children:["Note that ",(0,s.jsx)(n.code,{children:"act"})," calls can be safely nested and internally form a stack of calls."]}),"\n",(0,s.jsxs)(n.h3,{id:"implementation",children:["Implementation",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#implementation",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"act"})," implementation is defined in the ",(0,s.jsx)(n.a,{href:"https://github.com/facebook/react/blob/main/packages/react/src/ReactAct.js",target:"_blank",rel:"noopener noreferrer",children:"ReactAct.js source file"})," inside React repository. RNTL v14 requires React 19+, which provides the ",(0,s.jsx)(n.code,{children:"act"})," function directly via ",(0,s.jsx)(n.code,{children:"React.act"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["RNTL exports ",(0,s.jsx)(n.code,{children:"act"})," for convenience of the users as defined in the ",(0,s.jsx)(n.a,{href:"https://github.com/callstack/react-native-testing-library/blob/main/src/act.ts",target:"_blank",rel:"noopener noreferrer",children:"act.ts source file"}),". In v14, ",(0,s.jsx)(n.code,{children:"act"})," is now async by default and always returns a Promise, making it compatible with async React features like ",(0,s.jsx)(n.code,{children:"Suspense"})," boundary or ",(0,s.jsx)(n.code,{children:"use()"})," hook. The underlying implementation wraps React's ",(0,s.jsx)(n.code,{children:"act"})," function to ensure consistent async behavior."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Important"}),": You should always use ",(0,s.jsx)(n.code,{children:"act"})," exported from ",(0,s.jsx)(n.code,{children:"@testing-library/react-native"})," rather than the one from ",(0,s.jsx)(n.code,{children:"react"}),". The RNTL version automatically ensures async behavior, whereas using ",(0,s.jsx)(n.code,{children:"React.act"})," directly could still trigger synchronous act behavior if used improperly, leading to subtle test issues."]}),"\n",(0,s.jsxs)(n.h2,{id:"asynchronous-code",children:["Asynchronous code",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#asynchronous-code",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["In v14, ",(0,s.jsx)(n.code,{children:"act"})," is always async and returns a Promise. While the callback you pass to ",(0,s.jsx)(n.code,{children:"act"})," can be synchronous (dealing with things like synchronous effects or mocks using already resolved promises), the ",(0,s.jsx)(n.code,{children:"act"})," function itself should always be awaited. However, not all component code is synchronous. Frequently our components or mocks contain some asynchronous behaviours like ",(0,s.jsx)(n.code,{children:"setTimeout"})," calls or network calls."]}),"\n",(0,s.jsxs)(n.h3,{id:"handling-asynchronous-operations",children:["Handling asynchronous operations",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#handling-asynchronous-operations",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["When the callback passed to ",(0,s.jsx)(n.code,{children:"act"})," contains asynchronous operations, the Promise returned by ",(0,s.jsx)(n.code,{children:"act"})," will resolve only after those operations complete."]}),"\n",(0,s.jsxs)(n.p,{children:["Lets look at a simple example with component using ",(0,s.jsx)(n.code,{children:"setTimeout"})," call to simulate asynchronous behaviour:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"function TestAsyncComponent() {\n const [count, setCount] = React.useState(0);\n React.useEffect(() => {\n setTimeout(() => {\n setCount((c) => c + 1);\n }, 50);\n }, []);\n\n return Count {count};\n}\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"import { render, screen } from '@testing-library/react-native';\n\ntest('render async natively', async () => {\n await render();\n expect(screen.getByText('Count 0')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If we test our component in a native way without handling its asynchronous behaviour we will end up with an act warning. This is because the ",(0,s.jsx)(n.code,{children:"setTimeout"})," callback will trigger a state update after the test has finished."]}),"\n",(0,s.jsxs)(n.h3,{id:"solution-with-fake-timers",children:["Solution with fake timers",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#solution-with-fake-timers",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"First solution is to use Jest's fake timers inside out tests:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"test('render with fake timers', async () => {\n jest.useFakeTimers();\n await render();\n\n await act(() => {\n jest.runAllTimers();\n });\n expect(screen.getByText('Count 1')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Note"}),": In v14, both ",(0,s.jsx)(n.code,{children:"render"})," and ",(0,s.jsx)(n.code,{children:"act"})," are async by default, so you should await them."]}),"\n",(0,s.jsxs)(n.p,{children:["That way we can wrap ",(0,s.jsx)(n.code,{children:"jest.runAllTimers()"})," call which triggers the ",(0,s.jsx)(n.code,{children:"setTimeout"})," updates inside an ",(0,s.jsx)(n.code,{children:"act"})," call, hence resolving the act warning."]}),"\n",(0,s.jsxs)(n.h3,{id:"solution-with-real-timers",children:["Solution with real timers",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#solution-with-real-timers",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["If we wanted to stick with real timers then things get a bit more complex. Let's start by applying a crude solution of opening async ",(0,s.jsx)(n.code,{children:"act()"})," call for the expected duration of components updates:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"test('render with real timers - sleep', async () => {\n await render();\n await act(() => {\n await sleep(100); // Wait a bit longer than setTimeout in `TestAsyncComponent`\n });\n\n expect(screen.getByText('Count 1')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This works correctly as we use an explicit async ",(0,s.jsx)(n.code,{children:"act()"})," call that resolves the console error. However, it relies on our knowledge of exact implementation details which is a bad practice."]}),"\n",(0,s.jsxs)(n.p,{children:["Let's try more elegant solution using ",(0,s.jsx)(n.code,{children:"waitFor"})," that will wait for our desired state:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"test('render with real timers - waitFor', async () => {\n await render();\n\n await waitFor(() => screen.getByText('Count 1'));\n expect(screen.getByText('Count 1')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This also works correctly, because ",(0,s.jsx)(n.code,{children:"waitFor"})," call executes async ",(0,s.jsx)(n.code,{children:"act()"})," call internally."]}),"\n",(0,s.jsxs)(n.p,{children:["The above code can be simplified using ",(0,s.jsx)(n.code,{children:"findBy"})," query:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"test('render with real timers - findBy', async () => {\n await render();\n\n expect(await screen.findByText('Count 1')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This also works since ",(0,s.jsx)(n.code,{children:"findByText"})," internally calls ",(0,s.jsx)(n.code,{children:"waitFor"})," which uses async ",(0,s.jsx)(n.code,{children:"act()"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Note that all of the above examples are async tests using & awaiting async ",(0,s.jsx)(n.code,{children:"act()"})," function call."]}),"\n",(0,s.jsxs)(n.h2,{id:"references",children:["References",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#references",children:"#"})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsxs)(n.a,{href:"https://github.com/facebook/react/blob/main/packages/react/src/ReactAct.js",target:"_blank",rel:"noopener noreferrer",children:["React ",(0,s.jsx)(n.code,{children:"act"})," implementation source"]})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://react.dev/link/wrap-tests-with-act",target:"_blank",rel:"noopener noreferrer",children:"React testing documentation"})}),"\n"]})]})}function i(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,r.ah)(),e.components);return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}let c=i;i.__RSPRESS_PAGE_META={},i.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fadvanced%2Funderstanding-act.mdx"]={toc:[{text:"`act` warning",id:"act-warning",depth:2},{text:"Understanding `act`",id:"understanding-act",depth:2},{text:"Responsibility",id:"responsibility",depth:3},{text:"When to use act",id:"when-to-use-act",depth:3},{text:"Implementation",id:"implementation",depth:3},{text:"Asynchronous code",id:"asynchronous-code",depth:2},{text:"Handling asynchronous operations",id:"handling-asynchronous-operations",depth:3},{text:"Solution with fake timers",id:"solution-with-fake-timers",depth:3},{text:"Solution with real timers",id:"solution-with-real-timers",depth:3},{text:"References",id:"references",depth:2}],title:"Understanding `act` function",headingTitle:"Understanding `act` function",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/8756.26448bca.js b/static/js/async/4672.f3cfc7e3.js similarity index 87% rename from static/js/async/8756.26448bca.js rename to static/js/async/4672.f3cfc7e3.js index e92fb9d6..8eb72cbb 100644 --- a/static/js/async/8756.26448bca.js +++ b/static/js/async/4672.f3cfc7e3.js @@ -1 +1 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["8756"],{2688:function(e,t,n){n.r(t),n.d(t,{default:()=>a});var i=n(5893),r=n(65);function s(e){let t=Object.assign({h1:"h1",a:"a",p:"p",h2:"h2",h3:"h3",code:"code",pre:"pre"},(0,r.ah)(),e.components);return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.h1,{id:"migration-to-11x",children:["Migration to 11.x",(0,i.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#migration-to-11x",children:"#"})]}),"\n",(0,i.jsx)(t.p,{children:"Migration to React Native Testing Library version 11 from version 9.x or 10.x should be a relatively easy task due small amount of breaking changes."}),"\n",(0,i.jsxs)(t.h2,{id:"breaking-changes",children:["Breaking changes",(0,i.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#breaking-changes",children:"#"})]}),"\n",(0,i.jsxs)(t.h3,{id:"update-to-jest-28-if-you-use-fake-timers",children:["Update to Jest 28 if you use fake timers",(0,i.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#update-to-jest-28-if-you-use-fake-timers",children:"#"})]}),"\n",(0,i.jsxs)(t.p,{children:["If you use fake timers in any of your tests you should update your Jest dependencies to version 28. This is due to the fact that ",(0,i.jsxs)(t.a,{href:"https://jestjs.io/docs/jest-object#jestusefaketimersfaketimersconfig",target:"_blank",rel:"noopener noreferrer",children:[(0,i.jsx)(t.code,{children:"jest.useFakeTimers()"})," config structure"]})," has changed."]}),"\n",(0,i.jsxs)(t.h3,{id:"refactor-legacy-waitforoptions-position",children:["Refactor legacy ",(0,i.jsx)(t.code,{children:"waitForOptions"})," position",(0,i.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#refactor-legacy-waitforoptions-position",children:"#"})]}),"\n",(0,i.jsxs)(t.p,{children:["In version 9 we introducted query ",(0,i.jsx)(t.code,{children:"options"})," parameters for each query type. This affected all ",(0,i.jsx)(t.code,{children:"findBy"})," and ",(0,i.jsx)(t.code,{children:"findAllBy"})," queries because their signatures changed e.g. from:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ts",children:"function findByText(text: TextMatch, waitForOptions?: WaitForOptions);\nfunction findAllByText(text: TextMatch, waitForOptions?: WaitForOptions);\n"})}),"\n",(0,i.jsx)(t.p,{children:"to"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ts",children:"function findByText(text: TextMatch, options?: TextMatchOptions, waitForOptions?: WaitForOptions);\nfunction findAllByText(\n text: TextMatch,\n options?: TextMatchOptions,\n waitForOptions?: WaitForOptions\n);\n"})}),"\n",(0,i.jsxs)(t.p,{children:["In order to facilitate transition, in version 9 and 10, we provided a temporary possibility to pass ",(0,i.jsx)(t.code,{children:"WaitForOptions"})," like ",(0,i.jsx)(t.code,{children:"timeout"}),", ",(0,i.jsx)(t.code,{children:"interval"}),", etc inside ",(0,i.jsx)(t.code,{children:"options"})," argument. From this release we require passing these as the proper third parameter."]}),"\n",(0,i.jsx)(t.p,{children:"This change is easy to implement:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ts",children:"findByText(/Text/, { timeout: 1000 });\n"})}),"\n",(0,i.jsx)(t.p,{children:"should become"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ts",children:"findByText(/Text/, {}, { timeout: 1000 });\n"})}),"\n",(0,i.jsxs)(t.h3,{id:"triggering-non-touch-events-on-targets-with-pointereventsbox-none-prop",children:["Triggering non-touch events on targets with ",(0,i.jsx)(t.code,{children:'pointerEvents="box-none"'})," prop",(0,i.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#triggering-non-touch-events-on-targets-with-pointereventsbox-none-prop",children:"#"})]}),"\n",(0,i.jsxs)(t.p,{children:["Up to version 10, RNTL disables all events for a target with ",(0,i.jsx)(t.code,{children:'pointerEvents="box-none"'}),". This behavior is counter to how React Native itself functions."]}),"\n",(0,i.jsxs)(t.p,{children:["From version 11, RNTL continues to disable ",(0,i.jsx)(t.code,{children:"press"})," event for these targets but allows triggering other events, e.g. ",(0,i.jsx)(t.code,{children:"layout"}),"."]}),"\n",(0,i.jsxs)(t.h2,{id:"full-changelog",children:["Full Changelog",(0,i.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#full-changelog",children:"#"})]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://github.com/callstack/react-native-testing-library/compare/v10.1.1...v11.0.0",target:"_blank",rel:"noopener noreferrer",children:"https://github.com/callstack/react-native-testing-library/compare/v10.1.1...v11.0.0"})})]})}function o(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:t}=Object.assign({},(0,r.ah)(),e.components);return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(s,{...e})}):s(e)}let a=o;o.__RSPRESS_PAGE_META={},o.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fmigration%2Fprevious%2Fv11.mdx"]={toc:[{text:"Breaking changes",id:"breaking-changes",depth:2},{text:"Update to Jest 28 if you use fake timers",id:"update-to-jest-28-if-you-use-fake-timers",depth:3},{text:"Refactor legacy `waitForOptions` position",id:"refactor-legacy-waitforoptions-position",depth:3},{text:'Triggering non-touch events on targets with `pointerEvents="box-none"` prop',id:"triggering-non-touch-events-on-targets-with-pointereventsbox-none-prop",depth:3},{text:"Full Changelog",id:"full-changelog",depth:2}],title:"Migration to 11.x",headingTitle:"Migration to 11.x",frontmatter:{}}}}]); \ No newline at end of file +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["4672"],{6276:function(e,t,n){n.r(t),n.d(t,{default:()=>a});var i=n(5893),r=n(65);function s(e){let t=Object.assign({h1:"h1",a:"a",p:"p",h2:"h2",h3:"h3",code:"code",pre:"pre"},(0,r.ah)(),e.components);return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.h1,{id:"migration-to-11x",children:["Migration to 11.x",(0,i.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#migration-to-11x",children:"#"})]}),"\n",(0,i.jsx)(t.p,{children:"Migration to React Native Testing Library version 11 from version 9.x or 10.x should be a relatively easy task due small amount of breaking changes."}),"\n",(0,i.jsxs)(t.h2,{id:"breaking-changes",children:["Breaking changes",(0,i.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#breaking-changes",children:"#"})]}),"\n",(0,i.jsxs)(t.h3,{id:"update-to-jest-28-if-you-use-fake-timers",children:["Update to Jest 28 if you use fake timers",(0,i.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#update-to-jest-28-if-you-use-fake-timers",children:"#"})]}),"\n",(0,i.jsxs)(t.p,{children:["If you use fake timers in any of your tests you should update your Jest dependencies to version 28. This is due to the fact that ",(0,i.jsxs)(t.a,{href:"https://jestjs.io/docs/jest-object#jestusefaketimersfaketimersconfig",target:"_blank",rel:"noopener noreferrer",children:[(0,i.jsx)(t.code,{children:"jest.useFakeTimers()"})," config structure"]})," has changed."]}),"\n",(0,i.jsxs)(t.h3,{id:"refactor-legacy-waitforoptions-position",children:["Refactor legacy ",(0,i.jsx)(t.code,{children:"waitForOptions"})," position",(0,i.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#refactor-legacy-waitforoptions-position",children:"#"})]}),"\n",(0,i.jsxs)(t.p,{children:["In version 9 we introducted query ",(0,i.jsx)(t.code,{children:"options"})," parameters for each query type. This affected all ",(0,i.jsx)(t.code,{children:"findBy"})," and ",(0,i.jsx)(t.code,{children:"findAllBy"})," queries because their signatures changed e.g. from:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ts",children:"function findByText(text: TextMatch, waitForOptions?: WaitForOptions);\nfunction findAllByText(text: TextMatch, waitForOptions?: WaitForOptions);\n"})}),"\n",(0,i.jsx)(t.p,{children:"to"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ts",children:"function findByText(text: TextMatch, options?: TextMatchOptions, waitForOptions?: WaitForOptions);\nfunction findAllByText(\n text: TextMatch,\n options?: TextMatchOptions,\n waitForOptions?: WaitForOptions\n);\n"})}),"\n",(0,i.jsxs)(t.p,{children:["In order to facilitate transition, in version 9 and 10, we provided a temporary possibility to pass ",(0,i.jsx)(t.code,{children:"WaitForOptions"})," like ",(0,i.jsx)(t.code,{children:"timeout"}),", ",(0,i.jsx)(t.code,{children:"interval"}),", etc inside ",(0,i.jsx)(t.code,{children:"options"})," argument. From this release we require passing these as the proper third parameter."]}),"\n",(0,i.jsx)(t.p,{children:"This change is easy to implement:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ts",children:"findByText(/Text/, { timeout: 1000 });\n"})}),"\n",(0,i.jsx)(t.p,{children:"should become"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ts",children:"findByText(/Text/, {}, { timeout: 1000 });\n"})}),"\n",(0,i.jsxs)(t.h3,{id:"triggering-non-touch-events-on-targets-with-pointereventsbox-none-prop",children:["Triggering non-touch events on targets with ",(0,i.jsx)(t.code,{children:'pointerEvents="box-none"'})," prop",(0,i.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#triggering-non-touch-events-on-targets-with-pointereventsbox-none-prop",children:"#"})]}),"\n",(0,i.jsxs)(t.p,{children:["Up to version 10, RNTL disables all events for a target with ",(0,i.jsx)(t.code,{children:'pointerEvents="box-none"'}),". This behavior is counter to how React Native itself functions."]}),"\n",(0,i.jsxs)(t.p,{children:["From version 11, RNTL continues to disable ",(0,i.jsx)(t.code,{children:"press"})," event for these targets but allows triggering other events, e.g. ",(0,i.jsx)(t.code,{children:"layout"}),"."]}),"\n",(0,i.jsxs)(t.h2,{id:"full-changelog",children:["Full Changelog",(0,i.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#full-changelog",children:"#"})]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://github.com/callstack/react-native-testing-library/compare/v10.1.1...v11.0.0",target:"_blank",rel:"noopener noreferrer",children:"https://github.com/callstack/react-native-testing-library/compare/v10.1.1...v11.0.0"})})]})}function o(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:t}=Object.assign({},(0,r.ah)(),e.components);return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(s,{...e})}):s(e)}let a=o;o.__RSPRESS_PAGE_META={},o.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fmigration%2Fv11.mdx"]={toc:[{text:"Breaking changes",id:"breaking-changes",depth:2},{text:"Update to Jest 28 if you use fake timers",id:"update-to-jest-28-if-you-use-fake-timers",depth:3},{text:"Refactor legacy `waitForOptions` position",id:"refactor-legacy-waitforoptions-position",depth:3},{text:'Triggering non-touch events on targets with `pointerEvents="box-none"` prop',id:"triggering-non-touch-events-on-targets-with-pointereventsbox-none-prop",depth:3},{text:"Full Changelog",id:"full-changelog",depth:2}],title:"Migration to 11.x",headingTitle:"Migration to 11.x",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/1954.b9b89bd7.js b/static/js/async/4682.ee73a00b.js similarity index 90% rename from static/js/async/1954.b9b89bd7.js rename to static/js/async/4682.ee73a00b.js index dbe375b4..9c6a233c 100644 --- a/static/js/async/1954.b9b89bd7.js +++ b/static/js/async/4682.ee73a00b.js @@ -1 +1 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["1954"],{3391:function(e,r,n){n.r(r),n.d(r,{default:()=>d});var i=n(5893),s=n(65);function t(e){let r=Object.assign({h1:"h1",a:"a",div:"div",p:"p",code:"code",h2:"h2",h3:"h3",ol:"ol",li:"li",ul:"ul",pre:"pre"},(0,s.ah)(),e.components);return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(r.h1,{id:"migration-to-7x",children:["Migration to 7.x",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#migration-to-7x",children:"#"})]}),"\n",(0,i.jsxs)(r.div,{className:"rspress-directive info",children:[(0,i.jsx)(r.div,{className:"rspress-directive-title",children:"INFO"}),(0,i.jsxs)(r.div,{className:"rspress-directive-content",children:["\n",(0,i.jsxs)(r.p,{children:["We renamed the ",(0,i.jsx)(r.code,{children:"react-native-testing-library"})," npm package to ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"}),', officially joining the "Testing Library" family \uD83C\uDF89.']}),"\n"]})]}),"\n",(0,i.jsx)(r.p,{children:"As the version 7.0 involves merging two libraries together, there are two variants for migration guide, dependent on library you used previously:"}),"\n",(0,i.jsxs)(r.h2,{id:"guide-for-react-native-testing-library-users",children:["Guide for ",(0,i.jsx)(r.code,{children:"react-native-testing-library"})," users",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#guide-for-react-native-testing-library-users",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["This guide describes steps necessary to migrate from React Native Testing Library ",(0,i.jsx)(r.code,{children:"v2.x"})," or ",(0,i.jsx)(r.code,{children:"v6.0"})," to ",(0,i.jsx)(r.code,{children:"v7.0"}),"."]}),"\n",(0,i.jsxs)(r.h3,{id:"renaming-the-library",children:["Renaming the library",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#renaming-the-library",children:"#"})]}),"\n",(0,i.jsxs)(r.ol,{children:["\n",(0,i.jsxs)(r.li,{children:["Install ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"}),"."]}),"\n",(0,i.jsxs)(r.li,{children:["Uninstall ",(0,i.jsx)(r.code,{children:"react-native-testing-library"}),"."]}),"\n",(0,i.jsxs)(r.li,{children:["Rename all references of ",(0,i.jsx)(r.code,{children:"react-native-testing-library"})," to ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(r.p,{children:["You may have noticed a strange v2 to v7 upgrade, skipping versions 3, 4, 5 and 6. This is because we renamed the ",(0,i.jsx)(r.code,{children:"react-native-testing-library"})," npm package to ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"}),', officially joining the "Testing Library" family \uD83C\uDF89. We\'re merging existing two libraries into a single one. The ',(0,i.jsx)(r.a,{href:"https://github.com/testing-library/native-testing-library",target:"_blank",rel:"noopener noreferrer",children:"native-testing-library"})," repository, which had v6, will soon be archived and using ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"})," below v7, sourced from mentioned repository, is deprecated."]}),"\n",(0,i.jsx)(r.p,{children:'For branding purposes we keep the "React Native Testing Library" name, similar to "React Testing Library". Only the npm published package is changing. The code repository also stays the same under Callstack governance.'}),"\n",(0,i.jsxs)(r.h3,{id:"new-aliases",children:["New aliases",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#new-aliases",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["To improve compatibility with React Testing Library, and ease the migration for ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"})," users using version below v7, we've introduced new aliases to our accessibility queries:"]}),"\n",(0,i.jsxs)(r.ul,{children:["\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.code,{children:"ByLabelText"})," aliasing ",(0,i.jsx)(r.code,{children:"ByA11yLabel"})," queries"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.code,{children:"ByHintText"})," aliasing ",(0,i.jsx)(r.code,{children:"ByA11yHint"})," queries"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.code,{children:"ByRole"})," aliasing ",(0,i.jsx)(r.code,{children:"ByA11yRole"})," queries"]}),"\n"]}),"\n",(0,i.jsx)(r.p,{children:"We like the new names and consider removing the aliases in future releases."}),"\n",(0,i.jsxs)(r.h3,{id:"renaming-byplaceholder-queries",children:["Renaming ",(0,i.jsx)(r.code,{children:"ByPlaceholder"})," queries",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#renaming-byplaceholder-queries",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["To improve compatibility with React Testing Library, and to ease the migration for ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"})," users using version below v7, we've renamed following queries:"]}),"\n",(0,i.jsxs)(r.ul,{children:["\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.code,{children:"ByPlaceholder"})," -> ",(0,i.jsx)(r.code,{children:"ByPlaceholderText"})]}),"\n"]}),"\n",(0,i.jsx)(r.p,{children:"Please replace all occurrences of these queries in your codebase."}),"\n",(0,i.jsxs)(r.h3,{id:"fireevent-support-for-disabled-components",children:[(0,i.jsx)(r.code,{children:"fireEvent"})," support for disabled components",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#fireevent-support-for-disabled-components",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["To improve compatibility with the real React Native environment ",(0,i.jsx)(r.code,{children:"fireEvent"}),' now performs checks whether the component is "disabled" before firing an event on it. It uses the Responder system to establish should the event fire, which resembles the actual React Native runtime closer than we used to.']}),"\n",(0,i.jsx)(r.p,{children:"If your code contained any workarounds for preventing events firing on disabled events, you should now be able to remove them."}),"\n",(0,i.jsxs)(r.h2,{id:"guide-for-testing-libraryreact-native-users",children:["Guide for ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"})," users",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#guide-for-testing-libraryreact-native-users",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["This guide describes steps necessary to migrate from ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"})," from ",(0,i.jsx)(r.code,{children:"v6.0"})," to ",(0,i.jsx)(r.code,{children:"v7.0"}),". Although the name stays the same, this is a different library, sourced at ",(0,i.jsx)(r.a,{href:"https://github.com/callstack/react-native-testing-library",target:"_blank",rel:"noopener noreferrer",children:"Callstack GitHub repository"}),". We made sure the upgrade path is as easy for you as possible."]}),"\n",(0,i.jsxs)(r.h3,{id:"renaming-wait-helpers",children:['Renaming "wait" helpers',(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#renaming-wait-helpers",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["The ",(0,i.jsx)(r.code,{children:"wait"})," and ",(0,i.jsx)(r.code,{children:"waitForElement"})," helpers are replaced by ",(0,i.jsx)(r.code,{children:"waitFor"}),". Please rename all occurrences of these in your codebase."]}),"\n",(0,i.jsxs)(r.h3,{id:"changes-to-bytestid-queries",children:["Changes to ",(0,i.jsx)(r.code,{children:"ByTestId"})," queries",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#changes-to-bytestid-queries",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["The ",(0,i.jsx)(r.code,{children:"ByTestId"})," queries don't accept RegExps. Please use strings instead. We're happy to accept PRs adding this functionality :)."]}),"\n",(0,i.jsxs)(r.h3,{id:"no-bytitle-queries",children:["No ",(0,i.jsx)(r.code,{children:"ByTitle"})," queries",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#no-bytitle-queries",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["Our library doesn't implement ",(0,i.jsx)(r.code,{children:"ByTitle"})," queries, which are targetting components with ",(0,i.jsx)(r.code,{children:"title"})," prop, specifically ",(0,i.jsx)(r.code,{children:"Button"})," and ",(0,i.jsx)(r.code,{children:"RefreshControl"}),". If your tests only use ",(0,i.jsx)(r.code,{children:"ByTitle"})," to target ",(0,i.jsx)(r.code,{children:"Button"})," components, you can replace them with ",(0,i.jsx)(r.code,{children:"ByText"})," queries, since React Native renders ",(0,i.jsx)(r.code,{children:"Text"})," under the hood."]}),"\n",(0,i.jsxs)(r.p,{children:["If you need to query ",(0,i.jsx)(r.code,{children:"RefreshControl"})," component and can't figure out other way around it, you can use e.g. ",(0,i.jsx)(r.code,{children:"UNSAFE_getByProps({title})"})," query."]}),"\n",(0,i.jsxs)(r.h3,{id:"no-custom-jest-configuration",children:["No custom Jest configuration",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#no-custom-jest-configuration",children:"#"})]}),"\n",(0,i.jsx)(r.p,{children:"Use the official React Native preset for Jest:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-diff",children:'{\n "jest": {\n- "preset": "@testing-library/react-native"\n+ "preset": "react-native"\n }\n}\n'})}),"\n",(0,i.jsx)(r.p,{children:"We're told this also speeds up your tests startup on cold cache. Using official preset has another benefit – the library is compatible with any version of React Native without introducing breaking changes."}),"\n",(0,i.jsxs)(r.h3,{id:"cleanup-is-included-by-default",children:["Cleanup is included by default",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#cleanup-is-included-by-default",children:"#"})]}),"\n",(0,i.jsx)(r.p,{children:"Cleaning up (unmounting) components after each test is included by default in the same manner as in React Testing Library. Please remove this setup file from Jest config:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-diff",children:'{\n "jest": {\n- "setupFilesAfterEnv": ["@testing-library/react-native/cleanup-after-each"]\n }\n}\n'})}),"\n",(0,i.jsxs)(r.p,{children:["You can opt-out of this behavior by running tests with ",(0,i.jsx)(r.code,{children:"RNTL_SKIP_AUTO_CLEANUP=true"})," flag or importing from ",(0,i.jsx)(r.code,{children:"@testing-library/react-native/pure"}),". We encourage you to keep the default though."]}),"\n",(0,i.jsxs)(r.h3,{id:"no-nativetestinstance-abstraction",children:["No ",(0,i.jsx)(r.a,{href:"https://www.native-testing-library.com/docs/api-test-instance",target:"_blank",rel:"noopener noreferrer",children:"NativeTestInstance"})," abstraction",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#no-nativetestinstance-abstraction",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["We don't provide any abstraction over ",(0,i.jsx)(r.code,{children:"HostElement"})," returned by queries, but allow to use it directly to access queried component's ",(0,i.jsx)(r.code,{children:"props"})," or ",(0,i.jsx)(r.code,{children:"type"})," for that example."]}),"\n",(0,i.jsxs)(r.h3,{id:"no-container-nor-baseelement-returned-from-render",children:["No ",(0,i.jsx)(r.code,{children:"container"})," nor ",(0,i.jsx)(r.code,{children:"baseElement"})," returned from ",(0,i.jsx)(r.code,{children:"render"}),(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#no-container-nor-baseelement-returned-from-render",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["There's no ",(0,i.jsx)(r.code,{children:"container"})," returned from the ",(0,i.jsx)(r.code,{children:"render"})," function. If you must, use ",(0,i.jsx)(r.code,{children:"react-test-renderer"})," directly, although we advise against doing so. We also don't implement ",(0,i.jsx)(r.code,{children:"baseElement"})," because of that, since there's no ",(0,i.jsx)(r.code,{children:"document.documentElement"})," nor ",(0,i.jsx)(r.code,{children:"container"}),"."]}),"\n",(0,i.jsxs)(r.h3,{id:"firing-events-changes",children:["Firing events changes",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#firing-events-changes",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["There are slight differences in how ",(0,i.jsx)(r.code,{children:"fireEvent"})," works in both libraries:"]}),"\n",(0,i.jsxs)(r.ol,{children:["\n",(0,i.jsx)(r.li,{children:"Our library doesn't perform validation checks for events fired upon tested components."}),"\n",(0,i.jsxs)(r.li,{children:["Signature is different:","\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-diff",children:"-fireEvent[eventName](node: FiberRoot, eventProperties: NativeTestEvent)\n+fireEvent(element: HostElement, eventName: string, ...data: Array)\n"})}),"\n"]}),"\n",(0,i.jsxs)(r.li,{children:["There is no ",(0,i.jsx)(r.code,{children:"NativeTestEvent"})," - second and rest arguments are used instead."]}),"\n",(0,i.jsxs)(r.li,{children:["There are only 3 short-hand events: ",(0,i.jsx)(r.a,{href:"/docs/api/events/fire-event#press",children:(0,i.jsx)(r.code,{children:"fireEvent.press"})}),", ",(0,i.jsx)(r.a,{href:"/docs/api/events/fire-event#change-text",children:(0,i.jsx)(r.code,{children:"fireEvent.changeText"})})," and ",(0,i.jsx)(r.a,{href:"/docs/api/events/fire-event#scroll",children:(0,i.jsx)(r.code,{children:"fireEvent.scroll"})}),". For all other or custom events you can use the base signature."]}),"\n"]})]})}function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:r}=Object.assign({},(0,s.ah)(),e.components);return r?(0,i.jsx)(r,{...e,children:(0,i.jsx)(t,{...e})}):t(e)}let d=a;a.__RSPRESS_PAGE_META={},a.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fmigration%2Fprevious%2Fv7.mdx"]={toc:[{text:"Guide for `react-native-testing-library` users",id:"guide-for-react-native-testing-library-users",depth:2},{text:"Renaming the library",id:"renaming-the-library",depth:3},{text:"New aliases",id:"new-aliases",depth:3},{text:"Renaming `ByPlaceholder` queries",id:"renaming-byplaceholder-queries",depth:3},{text:"`fireEvent` support for disabled components",id:"fireevent-support-for-disabled-components",depth:3},{text:"Guide for `@testing-library/react-native` users",id:"guide-for-testing-libraryreact-native-users",depth:2},{text:'Renaming "wait" helpers',id:"renaming-wait-helpers",depth:3},{text:"Changes to `ByTestId` queries",id:"changes-to-bytestid-queries",depth:3},{text:"No `ByTitle` queries",id:"no-bytitle-queries",depth:3},{text:"No custom Jest configuration",id:"no-custom-jest-configuration",depth:3},{text:"Cleanup is included by default",id:"cleanup-is-included-by-default",depth:3},{text:"No NativeTestInstance abstraction",id:"no-nativetestinstance-abstraction",depth:3},{text:"No `container` nor `baseElement` returned from `render`",id:"no-container-nor-baseelement-returned-from-render",depth:3},{text:"Firing events changes",id:"firing-events-changes",depth:3}],title:"Migration to 7.x",headingTitle:"Migration to 7.x",frontmatter:{}}}}]); \ No newline at end of file +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["4682"],{7136:function(e,r,n){n.r(r),n.d(r,{default:()=>d});var i=n(5893),s=n(65);function t(e){let r=Object.assign({h1:"h1",a:"a",div:"div",p:"p",code:"code",h2:"h2",h3:"h3",ol:"ol",li:"li",ul:"ul",pre:"pre"},(0,s.ah)(),e.components);return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(r.h1,{id:"migration-to-7x",children:["Migration to 7.x",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#migration-to-7x",children:"#"})]}),"\n",(0,i.jsxs)(r.div,{className:"rspress-directive info",children:[(0,i.jsx)(r.div,{className:"rspress-directive-title",children:"INFO"}),(0,i.jsxs)(r.div,{className:"rspress-directive-content",children:["\n",(0,i.jsxs)(r.p,{children:["We renamed the ",(0,i.jsx)(r.code,{children:"react-native-testing-library"})," npm package to ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"}),', officially joining the "Testing Library" family \uD83C\uDF89.']}),"\n"]})]}),"\n",(0,i.jsx)(r.p,{children:"As the version 7.0 involves merging two libraries together, there are two variants for migration guide, dependent on library you used previously:"}),"\n",(0,i.jsxs)(r.h2,{id:"guide-for-react-native-testing-library-users",children:["Guide for ",(0,i.jsx)(r.code,{children:"react-native-testing-library"})," users",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#guide-for-react-native-testing-library-users",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["This guide describes steps necessary to migrate from React Native Testing Library ",(0,i.jsx)(r.code,{children:"v2.x"})," or ",(0,i.jsx)(r.code,{children:"v6.0"})," to ",(0,i.jsx)(r.code,{children:"v7.0"}),"."]}),"\n",(0,i.jsxs)(r.h3,{id:"renaming-the-library",children:["Renaming the library",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#renaming-the-library",children:"#"})]}),"\n",(0,i.jsxs)(r.ol,{children:["\n",(0,i.jsxs)(r.li,{children:["Install ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"}),"."]}),"\n",(0,i.jsxs)(r.li,{children:["Uninstall ",(0,i.jsx)(r.code,{children:"react-native-testing-library"}),"."]}),"\n",(0,i.jsxs)(r.li,{children:["Rename all references of ",(0,i.jsx)(r.code,{children:"react-native-testing-library"})," to ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(r.p,{children:["You may have noticed a strange v2 to v7 upgrade, skipping versions 3, 4, 5 and 6. This is because we renamed the ",(0,i.jsx)(r.code,{children:"react-native-testing-library"})," npm package to ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"}),', officially joining the "Testing Library" family \uD83C\uDF89. We\'re merging existing two libraries into a single one. The ',(0,i.jsx)(r.a,{href:"https://github.com/testing-library/native-testing-library",target:"_blank",rel:"noopener noreferrer",children:"native-testing-library"})," repository, which had v6, will soon be archived and using ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"})," below v7, sourced from mentioned repository, is deprecated."]}),"\n",(0,i.jsx)(r.p,{children:'For branding purposes we keep the "React Native Testing Library" name, similar to "React Testing Library". Only the npm published package is changing. The code repository also stays the same under Callstack governance.'}),"\n",(0,i.jsxs)(r.h3,{id:"new-aliases",children:["New aliases",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#new-aliases",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["To improve compatibility with React Testing Library, and ease the migration for ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"})," users using version below v7, we've introduced new aliases to our accessibility queries:"]}),"\n",(0,i.jsxs)(r.ul,{children:["\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.code,{children:"ByLabelText"})," aliasing ",(0,i.jsx)(r.code,{children:"ByA11yLabel"})," queries"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.code,{children:"ByHintText"})," aliasing ",(0,i.jsx)(r.code,{children:"ByA11yHint"})," queries"]}),"\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.code,{children:"ByRole"})," aliasing ",(0,i.jsx)(r.code,{children:"ByA11yRole"})," queries"]}),"\n"]}),"\n",(0,i.jsx)(r.p,{children:"We like the new names and consider removing the aliases in future releases."}),"\n",(0,i.jsxs)(r.h3,{id:"renaming-byplaceholder-queries",children:["Renaming ",(0,i.jsx)(r.code,{children:"ByPlaceholder"})," queries",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#renaming-byplaceholder-queries",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["To improve compatibility with React Testing Library, and to ease the migration for ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"})," users using version below v7, we've renamed following queries:"]}),"\n",(0,i.jsxs)(r.ul,{children:["\n",(0,i.jsxs)(r.li,{children:[(0,i.jsx)(r.code,{children:"ByPlaceholder"})," -> ",(0,i.jsx)(r.code,{children:"ByPlaceholderText"})]}),"\n"]}),"\n",(0,i.jsx)(r.p,{children:"Please replace all occurrences of these queries in your codebase."}),"\n",(0,i.jsxs)(r.h3,{id:"fireevent-support-for-disabled-components",children:[(0,i.jsx)(r.code,{children:"fireEvent"})," support for disabled components",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#fireevent-support-for-disabled-components",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["To improve compatibility with the real React Native environment ",(0,i.jsx)(r.code,{children:"fireEvent"}),' now performs checks whether the component is "disabled" before firing an event on it. It uses the Responder system to establish should the event fire, which resembles the actual React Native runtime closer than we used to.']}),"\n",(0,i.jsx)(r.p,{children:"If your code contained any workarounds for preventing events firing on disabled events, you should now be able to remove them."}),"\n",(0,i.jsxs)(r.h2,{id:"guide-for-testing-libraryreact-native-users",children:["Guide for ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"})," users",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#guide-for-testing-libraryreact-native-users",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["This guide describes steps necessary to migrate from ",(0,i.jsx)(r.code,{children:"@testing-library/react-native"})," from ",(0,i.jsx)(r.code,{children:"v6.0"})," to ",(0,i.jsx)(r.code,{children:"v7.0"}),". Although the name stays the same, this is a different library, sourced at ",(0,i.jsx)(r.a,{href:"https://github.com/callstack/react-native-testing-library",target:"_blank",rel:"noopener noreferrer",children:"Callstack GitHub repository"}),". We made sure the upgrade path is as easy for you as possible."]}),"\n",(0,i.jsxs)(r.h3,{id:"renaming-wait-helpers",children:['Renaming "wait" helpers',(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#renaming-wait-helpers",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["The ",(0,i.jsx)(r.code,{children:"wait"})," and ",(0,i.jsx)(r.code,{children:"waitForElement"})," helpers are replaced by ",(0,i.jsx)(r.code,{children:"waitFor"}),". Please rename all occurrences of these in your codebase."]}),"\n",(0,i.jsxs)(r.h3,{id:"changes-to-bytestid-queries",children:["Changes to ",(0,i.jsx)(r.code,{children:"ByTestId"})," queries",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#changes-to-bytestid-queries",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["The ",(0,i.jsx)(r.code,{children:"ByTestId"})," queries don't accept RegExps. Please use strings instead. We're happy to accept PRs adding this functionality :)."]}),"\n",(0,i.jsxs)(r.h3,{id:"no-bytitle-queries",children:["No ",(0,i.jsx)(r.code,{children:"ByTitle"})," queries",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#no-bytitle-queries",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["Our library doesn't implement ",(0,i.jsx)(r.code,{children:"ByTitle"})," queries, which are targetting components with ",(0,i.jsx)(r.code,{children:"title"})," prop, specifically ",(0,i.jsx)(r.code,{children:"Button"})," and ",(0,i.jsx)(r.code,{children:"RefreshControl"}),". If your tests only use ",(0,i.jsx)(r.code,{children:"ByTitle"})," to target ",(0,i.jsx)(r.code,{children:"Button"})," components, you can replace them with ",(0,i.jsx)(r.code,{children:"ByText"})," queries, since React Native renders ",(0,i.jsx)(r.code,{children:"Text"})," under the hood."]}),"\n",(0,i.jsxs)(r.p,{children:["If you need to query ",(0,i.jsx)(r.code,{children:"RefreshControl"})," component and can't figure out other way around it, you can use e.g. ",(0,i.jsx)(r.code,{children:"UNSAFE_getByProps({title})"})," query."]}),"\n",(0,i.jsxs)(r.h3,{id:"no-custom-jest-configuration",children:["No custom Jest configuration",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#no-custom-jest-configuration",children:"#"})]}),"\n",(0,i.jsx)(r.p,{children:"Use the official React Native preset for Jest:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-diff",children:'{\n "jest": {\n- "preset": "@testing-library/react-native"\n+ "preset": "react-native"\n }\n}\n'})}),"\n",(0,i.jsx)(r.p,{children:"We're told this also speeds up your tests startup on cold cache. Using official preset has another benefit – the library is compatible with any version of React Native without introducing breaking changes."}),"\n",(0,i.jsxs)(r.h3,{id:"cleanup-is-included-by-default",children:["Cleanup is included by default",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#cleanup-is-included-by-default",children:"#"})]}),"\n",(0,i.jsx)(r.p,{children:"Cleaning up (unmounting) components after each test is included by default in the same manner as in React Testing Library. Please remove this setup file from Jest config:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-diff",children:'{\n "jest": {\n- "setupFilesAfterEnv": ["@testing-library/react-native/cleanup-after-each"]\n }\n}\n'})}),"\n",(0,i.jsxs)(r.p,{children:["You can opt-out of this behavior by running tests with ",(0,i.jsx)(r.code,{children:"RNTL_SKIP_AUTO_CLEANUP=true"})," flag or importing from ",(0,i.jsx)(r.code,{children:"@testing-library/react-native/pure"}),". We encourage you to keep the default though."]}),"\n",(0,i.jsxs)(r.h3,{id:"no-nativetestinstance-abstraction",children:["No ",(0,i.jsx)(r.a,{href:"https://www.native-testing-library.com/docs/api-test-instance",target:"_blank",rel:"noopener noreferrer",children:"NativeTestInstance"})," abstraction",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#no-nativetestinstance-abstraction",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["We don't provide any abstraction over ",(0,i.jsx)(r.code,{children:"HostElement"})," returned by queries, but allow to use it directly to access queried component's ",(0,i.jsx)(r.code,{children:"props"})," or ",(0,i.jsx)(r.code,{children:"type"})," for that example."]}),"\n",(0,i.jsxs)(r.h3,{id:"no-container-nor-baseelement-returned-from-render",children:["No ",(0,i.jsx)(r.code,{children:"container"})," nor ",(0,i.jsx)(r.code,{children:"baseElement"})," returned from ",(0,i.jsx)(r.code,{children:"render"}),(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#no-container-nor-baseelement-returned-from-render",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["There's no ",(0,i.jsx)(r.code,{children:"container"})," returned from the ",(0,i.jsx)(r.code,{children:"render"})," function. If you must, use ",(0,i.jsx)(r.code,{children:"react-test-renderer"})," directly, although we advise against doing so. We also don't implement ",(0,i.jsx)(r.code,{children:"baseElement"})," because of that, since there's no ",(0,i.jsx)(r.code,{children:"document.documentElement"})," nor ",(0,i.jsx)(r.code,{children:"container"}),"."]}),"\n",(0,i.jsxs)(r.h3,{id:"firing-events-changes",children:["Firing events changes",(0,i.jsx)(r.a,{className:"header-anchor","aria-hidden":"true",href:"#firing-events-changes",children:"#"})]}),"\n",(0,i.jsxs)(r.p,{children:["There are slight differences in how ",(0,i.jsx)(r.code,{children:"fireEvent"})," works in both libraries:"]}),"\n",(0,i.jsxs)(r.ol,{children:["\n",(0,i.jsx)(r.li,{children:"Our library doesn't perform validation checks for events fired upon tested components."}),"\n",(0,i.jsxs)(r.li,{children:["Signature is different:","\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-diff",children:"-fireEvent[eventName](node: FiberRoot, eventProperties: NativeTestEvent)\n+fireEvent(element: HostElement, eventName: string, ...data: Array)\n"})}),"\n"]}),"\n",(0,i.jsxs)(r.li,{children:["There is no ",(0,i.jsx)(r.code,{children:"NativeTestEvent"})," - second and rest arguments are used instead."]}),"\n",(0,i.jsxs)(r.li,{children:["There are only 3 short-hand events: ",(0,i.jsx)(r.a,{href:"/docs/api/events/fire-event#press",children:(0,i.jsx)(r.code,{children:"fireEvent.press"})}),", ",(0,i.jsx)(r.a,{href:"/docs/api/events/fire-event#change-text",children:(0,i.jsx)(r.code,{children:"fireEvent.changeText"})})," and ",(0,i.jsx)(r.a,{href:"/docs/api/events/fire-event#scroll",children:(0,i.jsx)(r.code,{children:"fireEvent.scroll"})}),". For all other or custom events you can use the base signature."]}),"\n"]})]})}function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:r}=Object.assign({},(0,s.ah)(),e.components);return r?(0,i.jsx)(r,{...e,children:(0,i.jsx)(t,{...e})}):t(e)}let d=a;a.__RSPRESS_PAGE_META={},a.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fmigration%2Fv7.mdx"]={toc:[{text:"Guide for `react-native-testing-library` users",id:"guide-for-react-native-testing-library-users",depth:2},{text:"Renaming the library",id:"renaming-the-library",depth:3},{text:"New aliases",id:"new-aliases",depth:3},{text:"Renaming `ByPlaceholder` queries",id:"renaming-byplaceholder-queries",depth:3},{text:"`fireEvent` support for disabled components",id:"fireevent-support-for-disabled-components",depth:3},{text:"Guide for `@testing-library/react-native` users",id:"guide-for-testing-libraryreact-native-users",depth:2},{text:'Renaming "wait" helpers',id:"renaming-wait-helpers",depth:3},{text:"Changes to `ByTestId` queries",id:"changes-to-bytestid-queries",depth:3},{text:"No `ByTitle` queries",id:"no-bytitle-queries",depth:3},{text:"No custom Jest configuration",id:"no-custom-jest-configuration",depth:3},{text:"Cleanup is included by default",id:"cleanup-is-included-by-default",depth:3},{text:"No NativeTestInstance abstraction",id:"no-nativetestinstance-abstraction",depth:3},{text:"No `container` nor `baseElement` returned from `render`",id:"no-container-nor-baseelement-returned-from-render",depth:3},{text:"Firing events changes",id:"firing-events-changes",depth:3}],title:"Migration to 7.x",headingTitle:"Migration to 7.x",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/4804.a2b409b6.js b/static/js/async/4804.a2b409b6.js new file mode 100644 index 00000000..ac4f94dc --- /dev/null +++ b/static/js/async/4804.a2b409b6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["4804"],{5353:function(e,n,i){i.r(n),i.d(n,{default:()=>o});var s=i(5893),t=i(65);function r(e){let n=Object.assign({h1:"h1",a:"a",h2:"h2",p:"p",code:"code",ol:"ol",li:"li",strong:"strong",h3:"h3",pre:"pre",h4:"h4",ul:"ul"},(0,t.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.h1,{id:"async-events",children:["Async Events",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#async-events",children:"#"})]}),"\n",(0,s.jsxs)(n.h2,{id:"summary",children:["Summary",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#summary",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["In RNTL v14, all tests are async since ",(0,s.jsx)(n.code,{children:"render()"}),", ",(0,s.jsx)(n.code,{children:"fireEvent()"}),", and other core APIs return Promises. Beyond the basic async APIs, there are additional async utilities for handling events that complete over time:"]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Waiting for elements to appear"}),": Use ",(0,s.jsx)(n.code,{children:"findBy*"})," queries when elements appear after some delay (e.g., after data fetching)."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Waiting for conditions"}),": Use ",(0,s.jsx)(n.code,{children:"waitFor()"})," to wait for arbitrary conditions to be met."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Waiting for elements to disappear"}),": Use ",(0,s.jsx)(n.code,{children:"waitForElementToBeRemoved()"})," when elements should be removed after some action."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"These utilities help you write reliable tests that properly handle timing in your application."}),"\n",(0,s.jsxs)(n.h3,{id:"example",children:["Example",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#example",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"Consider a test for a user signing in with correct credentials:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-javascript",children:"test('User can sign in with correct credentials', async () => {\n // Typical test setup\n const user = userEvent.setup();\n await render();\n\n // No need to use async here, components are already rendered\n expect(screen.getByRole('header', { name: 'Sign in to Hello World App!' })).toBeOnTheScreen();\n\n // Using await as User Event requires it\n await user.type(screen.getByLabelText('Username'), 'admin');\n await user.type(screen.getByLabelText('Password'), 'admin1');\n await user.press(screen.getByRole('button', { name: 'Sign In' }));\n\n // Using await as sign in operation is asynchronous\n expect(await screen.findByRole('header', { name: 'Welcome admin!' })).toBeOnTheScreen();\n\n // Follow-up assertions do not need to be async, as we already waited for sign in operation to complete\n expect(\n screen.queryByRole('header', { name: 'Sign in to Hello World App' })\n ).not.toBeOnTheScreen();\n expect(screen.queryByLabelText('Username')).not.toBeOnTheScreen();\n expect(screen.queryByLabelText('Password')).not.toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.h2,{id:"async-utilities",children:["Async utilities",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#async-utilities",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"There are several asynchronous utilities you might use in your tests."}),"\n",(0,s.jsxs)(n.h3,{id:"findby-queries",children:[(0,s.jsx)(n.code,{children:"findBy*"})," queries",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#findby-queries",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["The most common are the ",(0,s.jsxs)(n.a,{href:"/docs/api/queries#find-by",children:[(0,s.jsx)(n.code,{children:"findBy*"})," queries"]}),". These are useful when waiting for a matching element to appear. They can be understood as a ",(0,s.jsxs)(n.a,{href:"/docs/api/queries#get-by",children:[(0,s.jsx)(n.code,{children:"getBy*"})," queries"]})," used in conjunction with a ",(0,s.jsxs)(n.a,{href:"/docs/api/misc/async#waitfor",children:[(0,s.jsx)(n.code,{children:"waitFor"})," function"]}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["They accept the same predicates as ",(0,s.jsx)(n.code,{children:"getBy*"})," queries like ",(0,s.jsx)(n.code,{children:"findByRole"}),", ",(0,s.jsx)(n.code,{children:"findByTest"}),", etc. They also have a multiple elements variant called ",(0,s.jsx)(n.a,{href:"/docs/api/queries#find-all-by",children:(0,s.jsx)(n.code,{children:"findAllBy*"})}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"function findByRole: (\n role: TextMatch,\n queryOptions?: {\n // Query specific options\n }\n waitForOptions?: {\n timeout?: number;\n interval?: number;\n // ..\n }\n): Promise;\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Each query has a default ",(0,s.jsx)(n.code,{children:"timeout"})," value of 1000 ms and a default ",(0,s.jsx)(n.code,{children:"interval"})," of 50 ms. Custom timeout and check intervals can be specified if needed, as shown below:"]}),"\n",(0,s.jsxs)(n.h4,{id:"example-1",children:["Example",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#example-1",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"const button = await screen.findByRole('button'), { name: 'Start' }, { timeout: 1000, interval: 50 });\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Alternatively, a default global ",(0,s.jsx)(n.code,{children:"timeout"})," value can be set using the ",(0,s.jsxs)(n.a,{href:"/docs/api/misc/config#configure",children:[(0,s.jsx)(n.code,{children:"configure"})," function"]}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"configure({ asyncUtilTimeout: timeout });\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"waitfor-function",children:[(0,s.jsx)(n.code,{children:"waitFor"})," function",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#waitfor-function",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"waitFor"})," function is another option, serving as a lower-level utility in more advanced cases."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"function waitFor(\n expectation: () => T,\n options?: {\n timeout: number;\n interval: number;\n }\n): Promise;\n"})}),"\n",(0,s.jsxs)(n.p,{children:["It accepts an ",(0,s.jsx)(n.code,{children:"expectation"})," to be validated and repeats the check every defined interval until it no longer throws an error. Similarly to ",(0,s.jsx)(n.code,{children:"findBy*"})," queries they accept ",(0,s.jsx)(n.code,{children:"timeout"})," and ",(0,s.jsx)(n.code,{children:"interval"})," options and have the same default values of 1000ms for timeout, and a checking interval of 50 ms."]}),"\n",(0,s.jsxs)(n.h4,{id:"example-2",children:["Example",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#example-2",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"await waitFor(() => expect(mockAPI).toHaveBeenCalledTimes(1));\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If you want to use it with ",(0,s.jsx)(n.code,{children:"getBy*"})," queries, use the ",(0,s.jsx)(n.code,{children:"findBy*"})," queries instead, as they essentially do the same, but offer better developer experience."]}),"\n",(0,s.jsxs)(n.h3,{id:"waitforelementtoberemoved-function",children:[(0,s.jsx)(n.code,{children:"waitForElementToBeRemoved"})," function",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#waitforelementtoberemoved-function",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["A specialized function, ",(0,s.jsx)(n.a,{href:"/docs/api/misc/async#waitforelementtoberemoved",children:(0,s.jsx)(n.code,{children:"waitForElementToBeRemoved"})}),", is used to verify that a matching element was present but has since been removed."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"function waitForElementToBeRemoved(\n expectation: () => T,\n options?: {\n timeout: number;\n interval: number;\n }\n): Promise {}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This function is, in a way, the negation of ",(0,s.jsx)(n.code,{children:"waitFor"})," as it expects the initial expectation to be true (not throw an error), only to turn invalid (start throwing errors) on subsequent runs. It operates using the same ",(0,s.jsx)(n.code,{children:"timeout"})," and ",(0,s.jsx)(n.code,{children:"interval"})," parameters as ",(0,s.jsx)(n.code,{children:"findBy*"})," queries and ",(0,s.jsx)(n.code,{children:"waitFor"}),"."]}),"\n",(0,s.jsxs)(n.h4,{id:"example-3",children:["Example",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#example-3",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"await waitForElementToBeRemoved(() => getByText('Hello World'));\n"})}),"\n",(0,s.jsxs)(n.h2,{id:"fake-timers",children:["Fake Timers",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#fake-timers",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["Asynchronous tests can take long to execute due to the delays introduced by asynchronous operations. To mitigate this, fake timers can be used. These are particularly useful when delays are mere waits, such as the 130 milliseconds wait introduced by the UserEvent ",(0,s.jsx)(n.code,{children:"press()"})," event due to React Native runtime behavior or simulated 1000 wait in a API call mock. Fake timers allow for precise fast-forwarding through these wait periods."]}),"\n",(0,s.jsxs)(n.p,{children:["Here are the basics of using ",(0,s.jsx)(n.a,{href:"https://jestjs.io/docs/timer-mocks",target:"_blank",rel:"noopener noreferrer",children:"Jest fake timers"}),":"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Enable fake timers with: ",(0,s.jsx)(n.code,{children:"jest.useFakeTimers()"})]}),"\n",(0,s.jsxs)(n.li,{children:["Disable fake timers with: ",(0,s.jsx)(n.code,{children:"jest.useRealTimers()"})]}),"\n",(0,s.jsxs)(n.li,{children:["Advance fake timers forward with: ",(0,s.jsx)(n.code,{children:"jest.advanceTimersByTime(interval)"})]}),"\n",(0,s.jsxs)(n.li,{children:["Run ",(0,s.jsx)(n.strong,{children:"all timers"})," to completion with: ",(0,s.jsx)(n.code,{children:"jest.runAllTimers()"})]}),"\n",(0,s.jsxs)(n.li,{children:["Run ",(0,s.jsx)(n.strong,{children:"currently pending timers"})," to completion with: ",(0,s.jsx)(n.code,{children:"jest.runOnlyPendingTimers()"})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Be cautious when running all timers to completion as it might create an infinite loop if these timers schedule follow-up timers. In such cases, it's safer to use ",(0,s.jsx)(n.code,{children:"jest.runOnlyPendingTimers()"})," to avoid ending up in an infinite loop of scheduled tasks."]}),"\n",(0,s.jsxs)(n.p,{children:["You can use both built-in Jest fake timers, as well as ",(0,s.jsx)(n.a,{href:"https://sinonjs.org/releases/latest/fake-timers/",target:"_blank",rel:"noopener noreferrer",children:"Sinon.JS fake timers"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"Note: you do not need to advance timers by hand when using User Event API, as it's automatically."})]})}function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,t.ah)(),e.components);return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(r,{...e})}):r(e)}let o=a;a.__RSPRESS_PAGE_META={},a.__RSPRESS_PAGE_META["14.x%2Fcookbook%2Fbasics%2Fasync-events.md"]={toc:[{text:"Summary",id:"summary",depth:2},{text:"Example",id:"example",depth:3},{text:"Async utilities",id:"async-utilities",depth:2},{text:"`findBy*` queries",id:"findby-queries",depth:3},{text:"Example",id:"example-1",depth:4},{text:"`waitFor` function",id:"waitfor-function",depth:3},{text:"Example",id:"example-2",depth:4},{text:"`waitForElementToBeRemoved` function",id:"waitforelementtoberemoved-function",depth:3},{text:"Example",id:"example-3",depth:4},{text:"Fake Timers",id:"fake-timers",depth:2}],title:"Async Events",headingTitle:"Async Events",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/4880.2c547bd2.js b/static/js/async/4880.2c547bd2.js deleted file mode 100644 index 951bcda3..00000000 --- a/static/js/async/4880.2c547bd2.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["4880"],{1310:function(e,n,r){r.r(n),r.d(n,{default:()=>o});var s=r(5893),t=r(65);function i(e){let n=Object.assign({h1:"h1",code:"code",a:"a",pre:"pre",p:"p",h3:"h3",h4:"h4",div:"div"},(0,t.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.h1,{id:"screen-object",children:[(0,s.jsx)(n.code,{children:"screen"})," object",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#screen-object",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"let screen: {\n ...queries;\n rerender(element: React.Element): Promise;\n unmount(): Promise;\n debug(options?: DebugOptions): void\n toJSON(): JsonElement | null;\n container: HostElement;\n root: HostElement;\n};\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"screen"})," object offers a recommended way to access queries and utilities for the currently rendered UI."]}),"\n",(0,s.jsxs)(n.p,{children:["This object is assigned after the ",(0,s.jsx)(n.code,{children:"render"})," call and cleared after each test by calling ",(0,s.jsx)(n.a,{href:"/docs/api/misc/other#cleanup",children:(0,s.jsx)(n.code,{children:"cleanup"})}),". If no ",(0,s.jsx)(n.code,{children:"render"})," call has been made in a given test, then it holds a special object and throws a helpful error on each property and method access."]}),"\n",(0,s.jsxs)(n.h3,{id:"queries",children:[(0,s.jsx)(n.code,{children:"...queries"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#queries",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["The most important feature of ",(0,s.jsx)(n.code,{children:"screen"})," is providing a set of helpful queries that allow you to find certain elements in the view hierarchy."]}),"\n",(0,s.jsxs)(n.p,{children:["See ",(0,s.jsx)(n.a,{href:"/docs/api/queries",children:"Queries"})," for a complete list."]}),"\n",(0,s.jsxs)(n.h4,{id:"example",children:["Example",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#example",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"import { render, screen } from '@testing-library/react-native';\n\ntest('example', async () => {\n await render();\n const buttonStart = screen.getByRole('button', { name: 'start' });\n});\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"rerender",children:[(0,s.jsx)(n.code,{children:"rerender"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#rerender",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"function rerender(element: React.Element): Promise;\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Re-render the in-memory tree with a new root element. This simulates a React update render at the root. If the new element has the same type (and ",(0,s.jsx)(n.code,{children:"key"}),") as the previous element, the tree will be updated; otherwise, it will re-mount a new tree, in both cases triggering the appropriate lifecycle events."]}),"\n",(0,s.jsxs)(n.p,{children:["This method is async and uses async ",(0,s.jsx)(n.code,{children:"act"})," function internally to ensure all pending React updates are executed during updating, making it compatible with React 19, React Suspense, and ",(0,s.jsx)(n.code,{children:"React.use()"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"import { render, screen } from '@testing-library/react-native';\n\ntest('async rerender test', async () => {\n await render();\n\n await screen.rerender();\n expect(screen.getByText('updated')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"unmount",children:[(0,s.jsx)(n.code,{children:"unmount"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#unmount",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"function unmount(): Promise;\n"})}),"\n",(0,s.jsx)(n.p,{children:"Unmount the in-memory tree, triggering the appropriate lifecycle events."}),"\n",(0,s.jsxs)(n.p,{children:["This method is async and uses async ",(0,s.jsx)(n.code,{children:"act"})," function internally to ensure all pending React updates are executed during unmounting, making it compatible with React 19, React Suspense, and ",(0,s.jsx)(n.code,{children:"React.use()"}),"."]}),"\n",(0,s.jsxs)(n.div,{className:"rspress-directive note",children:[(0,s.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,s.jsxs)(n.div,{className:"rspress-directive-content",children:["\n",(0,s.jsxs)(n.p,{children:["Usually you should not need to call ",(0,s.jsx)(n.code,{children:"unmount"})," as it is done automatically if your test runner supports ",(0,s.jsx)(n.code,{children:"afterEach"})," hook (like Jest, mocha, Jasmine)."]}),"\n"]})]}),"\n",(0,s.jsxs)(n.h3,{id:"debug",children:[(0,s.jsx)(n.code,{children:"debug"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#debug",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"function debug(options?: { message?: string; mapProps?: MapPropsFunction }): void;\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Pretty prints deeply rendered component passed to ",(0,s.jsx)(n.code,{children:"render"}),"."]}),"\n",(0,s.jsxs)(n.h4,{id:"debug-message-option",children:[(0,s.jsx)(n.code,{children:"message"})," option",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#debug-message-option",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"You can provide a message that will be printed on top."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"await render();\nscreen.debug({ message: 'optional message' });\n"})}),"\n",(0,s.jsx)(n.p,{children:"logs optional message and colored JSX:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"optional message\n\n\n Press me\n\n"})}),"\n",(0,s.jsxs)(n.h4,{id:"debug-map-props-option",children:[(0,s.jsx)(n.code,{children:"mapProps"})," option",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#debug-map-props-option",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"function debug({ mapProps: (props) => ({}) });\n"})}),"\n",(0,s.jsxs)(n.p,{children:["You can use the ",(0,s.jsx)(n.code,{children:"mapProps"})," option to transform the props that will be printed :"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"await render();\nscreen.debug({ mapProps: ({ style, ...props }) => ({ props }) });\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This will log the rendered JSX without the ",(0,s.jsx)(n.code,{children:"style"})," props."]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"children"})," prop cannot be filtered out so the following will print all rendered components with all props but ",(0,s.jsx)(n.code,{children:"children"})," filtered out."]}),"\n",(0,s.jsxs)(n.p,{children:["This option can be used to target specific props when debugging a query (for instance, keeping only the ",(0,s.jsx)(n.code,{children:"children"})," prop when debugging a ",(0,s.jsx)(n.code,{children:"getByText"})," query)."]}),"\n",(0,s.jsx)(n.p,{children:"You can also transform prop values so that they are more readable (e.g., flatten styles)."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { StyleSheet } from 'react-native';\n\nscreen.debug({ mapProps : {({ style, ...props })} => ({ style : StyleSheet.flatten(style), ...props }) });\n"})}),"\n",(0,s.jsx)(n.p,{children:"Or remove props that have little value when debugging tests, e.g. path prop for svgs"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"screen.debug({ mapProps: ({ path, ...props }) => ({ ...props }) });\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"tojson",children:[(0,s.jsx)(n.code,{children:"toJSON"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#tojson",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"function toJSON(): JsonElement | null;\n"})}),"\n",(0,s.jsx)(n.p,{children:"Get the rendered component JSON representation, e.g. for snapshot testing."}),"\n",(0,s.jsxs)(n.h3,{id:"container",children:[(0,s.jsx)(n.code,{children:"container"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#container",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"const container: HostElement;\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Returns a pseudo-element container whose children are the elements you asked to render. This is the root container element from ",(0,s.jsx)(n.a,{href:"https://github.com/mdjastrzebski/test-renderer",target:"_blank",rel:"noopener noreferrer",children:"Test Renderer"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"container"})," is safe to use and provides access to the entire rendered tree. It's useful when you need to query or manipulate the entire rendered output, similar to how ",(0,s.jsx)(n.code,{children:"container"})," works in ",(0,s.jsx)(n.a,{href:"https://testing-library.com/docs/react-testing-library/other#container-1",target:"_blank",rel:"noopener noreferrer",children:"React Testing Library"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"import { render, screen } from '@testing-library/react-native';\n\ntest('example', async () => {\n await render();\n // container contains the entire rendered tree\n const container = screen.container;\n expect(container).toBeTruthy();\n});\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"root",children:[(0,s.jsx)(n.code,{children:"root"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#root",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"const root: HostElement;\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Returns the rendered root ",(0,s.jsx)(n.a,{href:"/docs/advanced/testing-env#host-and-composite-components",children:"host element"}),". This is the first child of the ",(0,s.jsx)(n.code,{children:"container"}),", which represents the actual root element you rendered."]}),"\n",(0,s.jsxs)(n.p,{children:["This API is primarily useful for component tests, as it allows you to access root host view without using ",(0,s.jsx)(n.code,{children:"*ByTestId"})," queries or similar methods."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"import { render, screen } from '@testing-library/react-native';\n\ntest('example', async () => {\n await render(\n \n Hello\n \n );\n // root is the View element you rendered\n expect(screen.root.props.testID).toBe('root-view');\n});\n"})})]})}function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,t.ah)(),e.components);return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(i,{...e})}):i(e)}let o=a;a.__RSPRESS_PAGE_META={},a.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fapi%2Fscreen.mdx"]={toc:[{text:"`...queries`",id:"queries",depth:3},{text:"Example",id:"example",depth:4},{text:"`rerender`",id:"rerender",depth:3},{text:"`unmount`",id:"unmount",depth:3},{text:"`debug`",id:"debug",depth:3},{text:"`message` option",id:"debug-message-option",depth:4},{text:"`mapProps` option",id:"debug-map-props-option",depth:4},{text:"`toJSON`",id:"tojson",depth:3},{text:"`container`",id:"container",depth:3},{text:"`root`",id:"root",depth:3}],title:"`screen` object",headingTitle:"`screen` object",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/4880.9cbeb824.js b/static/js/async/4880.9cbeb824.js new file mode 100644 index 00000000..4b57e5bc --- /dev/null +++ b/static/js/async/4880.9cbeb824.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["4880"],{1310:function(e,n,r){r.r(n),r.d(n,{default:()=>a});var s=r(5893),t=r(65);function i(e){let n=Object.assign({h1:"h1",code:"code",a:"a",pre:"pre",p:"p",h3:"h3",h4:"h4",div:"div"},(0,t.ah)(),e.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.h1,{id:"screen-object",children:[(0,s.jsx)(n.code,{children:"screen"})," object",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#screen-object",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"let screen: {\n ...queries;\n rerender(element: React.Element): Promise;\n unmount(): Promise;\n debug(options?: DebugOptions): void\n toJSON(): JsonElement | null;\n container: HostElement;\n root: HostElement | null;\n};\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"screen"})," object offers a recommended way to access queries and utilities for the currently rendered UI."]}),"\n",(0,s.jsxs)(n.p,{children:["This object is assigned after the ",(0,s.jsx)(n.code,{children:"render"})," call and cleared after each test by calling ",(0,s.jsx)(n.a,{href:"/docs/api/misc/other#cleanup",children:(0,s.jsx)(n.code,{children:"cleanup"})}),". If no ",(0,s.jsx)(n.code,{children:"render"})," call has been made in a given test, then it holds a special object and throws a helpful error on each property and method access."]}),"\n",(0,s.jsxs)(n.h3,{id:"queries",children:[(0,s.jsx)(n.code,{children:"...queries"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#queries",children:"#"})]}),"\n",(0,s.jsxs)(n.p,{children:["The most important feature of ",(0,s.jsx)(n.code,{children:"screen"})," is providing a set of helpful queries that allow you to find certain elements in the view hierarchy."]}),"\n",(0,s.jsxs)(n.p,{children:["See ",(0,s.jsx)(n.a,{href:"/docs/api/queries",children:"Queries"})," for a complete list."]}),"\n",(0,s.jsxs)(n.h4,{id:"example",children:["Example",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#example",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"import { render, screen } from '@testing-library/react-native';\n\ntest('example', async () => {\n await render();\n const buttonStart = screen.getByRole('button', { name: 'start' });\n});\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"rerender",children:[(0,s.jsx)(n.code,{children:"rerender"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#rerender",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"function rerender(element: React.Element): Promise;\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Re-render the in-memory tree with a new root element. This simulates a React update render at the root. If the new element has the same type (and ",(0,s.jsx)(n.code,{children:"key"}),") as the previous element, the tree will be updated; otherwise, it will re-mount a new tree, in both cases triggering the appropriate lifecycle events."]}),"\n",(0,s.jsxs)(n.p,{children:["This method is async and uses async ",(0,s.jsx)(n.code,{children:"act"})," function internally to ensure all pending React updates are executed during updating, making it compatible with async React features like ",(0,s.jsx)(n.code,{children:"Suspense"})," boundary or ",(0,s.jsx)(n.code,{children:"use()"})," hook."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"import { render, screen } from '@testing-library/react-native';\n\ntest('async rerender test', async () => {\n await render();\n\n await screen.rerender();\n expect(screen.getByText('updated')).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"unmount",children:[(0,s.jsx)(n.code,{children:"unmount"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#unmount",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"function unmount(): Promise;\n"})}),"\n",(0,s.jsx)(n.p,{children:"Unmount the in-memory tree, triggering the appropriate lifecycle events."}),"\n",(0,s.jsxs)(n.p,{children:["This method is async and uses async ",(0,s.jsx)(n.code,{children:"act"})," function internally to ensure all pending React updates are executed during unmounting, making it compatible with async React features like ",(0,s.jsx)(n.code,{children:"Suspense"})," boundary or ",(0,s.jsx)(n.code,{children:"use()"})," hook."]}),"\n",(0,s.jsxs)(n.div,{className:"rspress-directive note",children:[(0,s.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,s.jsxs)(n.div,{className:"rspress-directive-content",children:["\n",(0,s.jsxs)(n.p,{children:["Usually you should not need to call ",(0,s.jsx)(n.code,{children:"unmount"})," as it is done automatically if your test runner supports ",(0,s.jsx)(n.code,{children:"afterEach"})," hook (like Jest, mocha, Jasmine)."]}),"\n"]})]}),"\n",(0,s.jsxs)(n.h3,{id:"debug",children:[(0,s.jsx)(n.code,{children:"debug"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#debug",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"function debug(options?: { message?: string; mapProps?: MapPropsFunction }): void;\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Pretty prints deeply rendered component passed to ",(0,s.jsx)(n.code,{children:"render"}),"."]}),"\n",(0,s.jsxs)(n.h4,{id:"debug-message-option",children:[(0,s.jsx)(n.code,{children:"message"})," option",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#debug-message-option",children:"#"})]}),"\n",(0,s.jsx)(n.p,{children:"You can provide a message that will be printed on top."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"await render();\nscreen.debug({ message: 'optional message' });\n"})}),"\n",(0,s.jsx)(n.p,{children:"logs optional message and colored JSX:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"optional message\n\n\n Press me\n\n"})}),"\n",(0,s.jsxs)(n.h4,{id:"debug-map-props-option",children:[(0,s.jsx)(n.code,{children:"mapProps"})," option",(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#debug-map-props-option",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"function debug({ mapProps: (props) => ({}) });\n"})}),"\n",(0,s.jsxs)(n.p,{children:["You can use the ",(0,s.jsx)(n.code,{children:"mapProps"})," option to transform the props that will be printed :"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"await render();\nscreen.debug({ mapProps: ({ style, ...props }) => ({ props }) });\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This will log the rendered JSX without the ",(0,s.jsx)(n.code,{children:"style"})," props."]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"children"})," prop cannot be filtered out so the following will print all rendered components with all props but ",(0,s.jsx)(n.code,{children:"children"})," filtered out."]}),"\n",(0,s.jsxs)(n.p,{children:["This option can be used to target specific props when debugging a query (for instance, keeping only the ",(0,s.jsx)(n.code,{children:"children"})," prop when debugging a ",(0,s.jsx)(n.code,{children:"getByText"})," query)."]}),"\n",(0,s.jsx)(n.p,{children:"You can also transform prop values so that they are more readable (e.g., flatten styles)."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"import { StyleSheet } from 'react-native';\n\nscreen.debug({ mapProps : {({ style, ...props })} => ({ style : StyleSheet.flatten(style), ...props }) });\n"})}),"\n",(0,s.jsx)(n.p,{children:"Or remove props that have little value when debugging tests, e.g. path prop for svgs"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"screen.debug({ mapProps: ({ path, ...props }) => ({ ...props }) });\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"tojson",children:[(0,s.jsx)(n.code,{children:"toJSON"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#tojson",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"function toJSON(): JsonElement | null;\n"})}),"\n",(0,s.jsx)(n.p,{children:"Get the rendered component JSON representation, e.g. for snapshot testing."}),"\n",(0,s.jsxs)(n.h3,{id:"container",children:[(0,s.jsx)(n.code,{children:"container"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#container",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"const container: HostElement;\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Returns a pseudo-element container whose children are the elements you asked to render. This is the root container element from ",(0,s.jsx)(n.a,{href:"https://github.com/mdjastrzebski/test-renderer",target:"_blank",rel:"noopener noreferrer",children:"Test Renderer"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"container"})," is safe to use and provides access to the entire rendered tree. It's useful when you need to query or manipulate the entire rendered output, similar to how ",(0,s.jsx)(n.code,{children:"container"})," works in ",(0,s.jsx)(n.a,{href:"https://testing-library.com/docs/react-testing-library/other#container-1",target:"_blank",rel:"noopener noreferrer",children:"React Testing Library"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"import { render, screen } from '@testing-library/react-native';\n\ntest('example', async () => {\n await render();\n // container contains the entire rendered tree\n const container = screen.container;\n expect(container).toBeTruthy();\n});\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"root",children:[(0,s.jsx)(n.code,{children:"root"}),(0,s.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#root",children:"#"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ts",children:"const root: HostElement | null;\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Returns the rendered root ",(0,s.jsx)(n.a,{href:"/docs/advanced/testing-env#host-and-composite-components",children:"host element"}),", or ",(0,s.jsx)(n.code,{children:"null"})," if nothing was rendered. This is the first child of the ",(0,s.jsx)(n.code,{children:"container"}),", which represents the actual root element you rendered."]}),"\n",(0,s.jsxs)(n.p,{children:["This API is primarily useful for component tests, as it allows you to access root host view without using ",(0,s.jsx)(n.code,{children:"*ByTestId"})," queries or similar methods."]}),"\n",(0,s.jsxs)(n.div,{className:"rspress-directive note",children:[(0,s.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,s.jsxs)(n.div,{className:"rspress-directive-content",children:["\n",(0,s.jsxs)(n.p,{children:["In rare cases where your root element is a ",(0,s.jsx)(n.code,{children:"React.Fragment"})," with multiple children, the ",(0,s.jsx)(n.code,{children:"container"})," will have more than one child, and ",(0,s.jsx)(n.code,{children:"root"})," will return only the first one. In such cases, use ",(0,s.jsx)(n.code,{children:"container.children"})," to access all rendered elements."]}),"\n"]})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-jsx",children:"import { render, screen } from '@testing-library/react-native';\n\ntest('example', async () => {\n await render(\n \n Hello\n \n );\n // root is the View element you rendered\n expect(screen.root.props.testID).toBe('root-view');\n});\n"})})]})}function o(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,t.ah)(),e.components);return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(i,{...e})}):i(e)}let a=o;o.__RSPRESS_PAGE_META={},o.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fapi%2Fscreen.mdx"]={toc:[{text:"`...queries`",id:"queries",depth:3},{text:"Example",id:"example",depth:4},{text:"`rerender`",id:"rerender",depth:3},{text:"`unmount`",id:"unmount",depth:3},{text:"`debug`",id:"debug",depth:3},{text:"`message` option",id:"debug-message-option",depth:4},{text:"`mapProps` option",id:"debug-map-props-option",depth:4},{text:"`toJSON`",id:"tojson",depth:3},{text:"`container`",id:"container",depth:3},{text:"`root`",id:"root",depth:3}],title:"`screen` object",headingTitle:"`screen` object",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/5263.45dcebf3.js b/static/js/async/5263.56b1ffda.js similarity index 56% rename from static/js/async/5263.45dcebf3.js rename to static/js/async/5263.56b1ffda.js index 32b72bfc..82cfa39e 100644 --- a/static/js/async/5263.45dcebf3.js +++ b/static/js/async/5263.56b1ffda.js @@ -1 +1 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["5263"],{8502:function(e,n,r){r.r(n),r.d(n,{default:()=>o});var t=r(5893),s=r(65);function i(e){let n=Object.assign({h1:"h1",code:"code",a:"a",h3:"h3",p:"p",pre:"pre",h4:"h4"},(0,s.ah)(),e.components);return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.h1,{id:"custom-render-function",children:["Custom ",(0,t.jsx)(n.code,{children:"render"})," function",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#custom-render-function",children:"#"})]}),"\n",(0,t.jsxs)(n.h3,{id:"summary",children:["Summary",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#summary",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["RNTL exposes the ",(0,t.jsx)(n.code,{children:"render"})," function as the primary entry point for tests. If you make complex, repeating setups for your tests, consider creating a custom render function. The idea is to encapsulate common setup steps and test wiring inside a render function suitable for your tests."]}),"\n",(0,t.jsxs)(n.h3,{id:"example",children:["Example",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#example",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",meta:"title=test-utils.ts",children:"// ...\n\ninterface RenderWithProvidersProps {\n user?: User | null;\n theme?: Theme;\n}\n\nexport async function renderWithProviders(\n ui: React.ReactElement,\n options?: RenderWithProvidersProps\n) {\n return await render(\n \n {ui}\n \n );\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",meta:"title=custom-render/index.test.tsx",children:"import { screen } from '@testing-library/react-native';\nimport { renderWithProviders } from '../test-utils';\n// ...\n\ntest('renders WelcomeScreen with user', async () => {\n await renderWithProviders(, { user: { name: 'Jar-Jar' } });\n expect(screen.getByText(/hello Jar-Jar/i)).toBeOnTheScreen();\n});\n\ntest('renders WelcomeScreen without user', async () => {\n await renderWithProviders(, { user: null });\n expect(screen.getByText(/hello stranger/i)).toBeOnTheScreen();\n});\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Example ",(0,t.jsx)(n.a,{href:"https://github.com/callstack/react-native-testing-library/tree/main/examples/cookbook/custom-render",target:"_blank",rel:"noopener noreferrer",children:"full source code"}),"."]}),"\n",(0,t.jsxs)(n.h3,{id:"more-info",children:["More info",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#more-info",children:"#"})]}),"\n",(0,t.jsxs)(n.h4,{id:"additional-params",children:["Additional params",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#additional-params",children:"#"})]}),"\n",(0,t.jsx)(n.p,{children:"A custom render function might accept additional parameters to allow for setting up different start conditions for a test, e.g., the initial state for global state management."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",meta:"title=SomeScreen.test.tsx",children:"test('renders SomeScreen for logged in user', () => {\n renderScreen(, { state: loggedInState });\n // ...\n});\n"})}),"\n",(0,t.jsxs)(n.h4,{id:"multiple-functions",children:["Multiple functions",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#multiple-functions",children:"#"})]}),"\n",(0,t.jsx)(n.p,{children:"Depending on the situation, you may declare more than one custom render function. For example, you have one function for testing application flows and a second for testing individual screens."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",meta:"title=test-utils.tsx",children:"function renderNavigator(ui, options);\nfunction renderScreen(ui, options);\n"})}),"\n",(0,t.jsxs)(n.h4,{id:"async-function",children:["Async function",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#async-function",children:"#"})]}),"\n",(0,t.jsx)(n.p,{children:"Make it async if you want to put some async setup in your custom render function."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",meta:"title=SomeScreen.test.tsx",children:"test('renders SomeScreen', async () => {\n await renderWithAsync();\n // ...\n});\n"})})]})}function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,s.ah)(),e.components);return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(i,{...e})}):i(e)}let o=a;a.__RSPRESS_PAGE_META={},a.__RSPRESS_PAGE_META["14.x%2Fcookbook%2Fbasics%2Fcustom-render.md"]={toc:[{text:"Summary",id:"summary",depth:3},{text:"Example",id:"example",depth:3},{text:"More info",id:"more-info",depth:3},{text:"Additional params",id:"additional-params",depth:4},{text:"Multiple functions",id:"multiple-functions",depth:4},{text:"Async function",id:"async-function",depth:4}],title:"Custom `render` function",headingTitle:"Custom `render` function",frontmatter:{}}}}]); \ No newline at end of file +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["5263"],{8502:function(e,n,r){r.r(n),r.d(n,{default:()=>o});var t=r(5893),a=r(65);function s(e){let n=Object.assign({h1:"h1",code:"code",a:"a",h3:"h3",p:"p",pre:"pre",h4:"h4"},(0,a.ah)(),e.components);return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.h1,{id:"custom-render-function",children:["Custom ",(0,t.jsx)(n.code,{children:"render"})," function",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#custom-render-function",children:"#"})]}),"\n",(0,t.jsxs)(n.h3,{id:"summary",children:["Summary",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#summary",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["RNTL exposes the ",(0,t.jsx)(n.code,{children:"render"})," function as the primary entry point for tests. If you make complex, repeating setups for your tests, consider creating a custom render function. The idea is to encapsulate common setup steps and test wiring inside a render function suitable for your tests."]}),"\n",(0,t.jsxs)(n.h3,{id:"example",children:["Example",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#example",children:"#"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",meta:"title=test-utils.ts",children:"// ...\n\ninterface RenderWithProvidersProps {\n user?: User | null;\n theme?: Theme;\n}\n\nexport async function renderWithProviders(\n ui: React.ReactElement,\n options?: RenderWithProvidersProps\n) {\n return await render(\n \n {ui}\n \n );\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",meta:"title=custom-render/index.test.tsx",children:"import { screen } from '@testing-library/react-native';\nimport { renderWithProviders } from '../test-utils';\n// ...\n\ntest('renders WelcomeScreen with user', async () => {\n await renderWithProviders(, { user: { name: 'Jar-Jar' } });\n expect(screen.getByText(/hello Jar-Jar/i)).toBeOnTheScreen();\n});\n\ntest('renders WelcomeScreen without user', async () => {\n await renderWithProviders(, { user: null });\n expect(screen.getByText(/hello stranger/i)).toBeOnTheScreen();\n});\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Example ",(0,t.jsx)(n.a,{href:"https://github.com/callstack/react-native-testing-library/tree/main/examples/cookbook/custom-render",target:"_blank",rel:"noopener noreferrer",children:"full source code"}),"."]}),"\n",(0,t.jsxs)(n.h3,{id:"more-info",children:["More info",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#more-info",children:"#"})]}),"\n",(0,t.jsxs)(n.h4,{id:"additional-params",children:["Additional params",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#additional-params",children:"#"})]}),"\n",(0,t.jsx)(n.p,{children:"A custom render function might accept additional parameters to allow for setting up different start conditions for a test, e.g., the initial state for global state management."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",meta:"title=SomeScreen.test.tsx",children:"test('renders SomeScreen for logged in user', async () => {\n await renderScreen(, { state: loggedInState });\n // ...\n});\n"})}),"\n",(0,t.jsxs)(n.h4,{id:"multiple-functions",children:["Multiple functions",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#multiple-functions",children:"#"})]}),"\n",(0,t.jsx)(n.p,{children:"Depending on the situation, you may declare more than one custom render function. For example, you have one function for testing application flows and a second for testing individual screens."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",meta:"title=test-utils.tsx",children:"function renderNavigator(ui, options);\nfunction renderScreen(ui, options);\n"})}),"\n",(0,t.jsxs)(n.h4,{id:"async-setup",children:["Async setup",(0,t.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#async-setup",children:"#"})]}),"\n",(0,t.jsxs)(n.p,{children:["Since ",(0,t.jsx)(n.code,{children:"render"})," is async, your custom render function should be marked as ",(0,t.jsx)(n.code,{children:"async"})," and use ",(0,t.jsx)(n.code,{children:"await render()"}),". This pattern also makes it easy to add additional async setup if needed:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tsx",meta:"title=SomeScreen.test.tsx",children:"async function renderWithData(ui: React.ReactElement) {\n const data = await fetchTestData();\n return await render({ui});\n}\n\ntest('renders SomeScreen', async () => {\n await renderWithData();\n // ...\n});\n"})})]})}function i(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,a.ah)(),e.components);return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(s,{...e})}):s(e)}let o=i;i.__RSPRESS_PAGE_META={},i.__RSPRESS_PAGE_META["14.x%2Fcookbook%2Fbasics%2Fcustom-render.md"]={toc:[{text:"Summary",id:"summary",depth:3},{text:"Example",id:"example",depth:3},{text:"More info",id:"more-info",depth:3},{text:"Additional params",id:"additional-params",depth:4},{text:"Multiple functions",id:"multiple-functions",depth:4},{text:"Async setup",id:"async-setup",depth:4}],title:"Custom `render` function",headingTitle:"Custom `render` function",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/5469.0ad2c8f8.js b/static/js/async/5469.0ad2c8f8.js deleted file mode 100644 index 97a12804..00000000 --- a/static/js/async/5469.0ad2c8f8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["5469"],{6495:function(e,n,s){s.r(n),s.d(n,{default:()=>a});var r=s(5893),i=s(65);function c(e){let n=Object.assign({h1:"h1",a:"a",h2:"h2",code:"code",pre:"pre",p:"p",div:"div",em:"em",ul:"ul",li:"li",strong:"strong"},(0,i.ah)(),e.components);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.h1,{id:"other-helpers",children:["Other helpers",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#other-helpers",children:"#"})]}),"\n",(0,r.jsxs)(n.h2,{id:"within",children:[(0,r.jsx)(n.code,{children:"within"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#within",children:"#"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:"function within(element: HostElement): Queries {}\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"within"})," performs ",(0,r.jsx)(n.a,{href:"/docs/api/queries",children:"queries"})," scoped to given element."]}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive note",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,r.jsx)(n.div,{className:"rspress-directive-content",children:(0,r.jsxs)(n.p,{children:["Please note that additional ",(0,r.jsx)(n.code,{children:"render"})," specific operations like ",(0,r.jsx)(n.code,{children:"rerender"}),", ",(0,r.jsx)(n.code,{children:"unmount"}),", ",(0,r.jsx)(n.code,{children:"debug"}),", ",(0,r.jsx)(n.code,{children:"toJSON"})," are ",(0,r.jsx)(n.em,{children:"not"})," included.\n"]})})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:"const detailsScreen = within(screen.getByA11yHint('Details Screen'));\nexpect(detailsScreen.getByText('Some Text')).toBeOnTheScreen();\nexpect(detailsScreen.getByDisplayValue('Some Value')).toBeOnTheScreen();\nexpect(detailsScreen.queryByLabelText('Some Label')).toBeOnTheScreen();\nawait expect(detailsScreen.findByA11yHint('Some Label')).resolves.toBeOnTheScreen();\n"})}),"\n",(0,r.jsx)(n.p,{children:"Use cases for scoped queries include:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"queries scoped to a single item inside a FlatList containing many items"}),"\n",(0,r.jsx)(n.li,{children:"queries scoped to a single screen in tests involving screen transitions (e.g. with react-navigation)"}),"\n"]}),"\n",(0,r.jsxs)(n.h2,{id:"act",children:[(0,r.jsx)(n.code,{children:"act"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#act",children:"#"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"function act(callback: () => T | Promise): Promise;\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Useful function to help testing components that use hooks API. By default any ",(0,r.jsx)(n.code,{children:"render"}),", ",(0,r.jsx)(n.code,{children:"rerender"}),", ",(0,r.jsx)(n.code,{children:"fireEvent"}),", and ",(0,r.jsx)(n.code,{children:"waitFor"})," calls are wrapped by this function, so there is no need to wrap it manually."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsxs)(n.strong,{children:["In v14, ",(0,r.jsx)(n.code,{children:"act"})," is now async by default and always returns a Promise"]}),", making it compatible with React 19, React Suspense, and ",(0,r.jsx)(n.code,{children:"React.use()"}),". This ensures all pending React updates are executed before the Promise resolves."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"import { act } from '@testing-library/react-native';\n\nit('should update state', async () => {\n await act(async () => {\n setState('new value');\n });\n expect(state).toBe('new value');\n});\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Note"}),": Even if your callback is synchronous, you should still use ",(0,r.jsx)(n.code,{children:"await act(async () => ...)"})," as ",(0,r.jsx)(n.code,{children:"act"})," now always returns a Promise."]}),"\n",(0,r.jsxs)(n.p,{children:["Consult our ",(0,r.jsx)(n.a,{href:"/docs/advanced/understanding-act",children:"Understanding Act function"})," document for more understanding of its intricacies."]}),"\n",(0,r.jsxs)(n.h2,{id:"cleanup",children:[(0,r.jsx)(n.code,{children:"cleanup"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#cleanup",children:"#"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"const cleanup: () => void;\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Unmounts React trees that were mounted with ",(0,r.jsx)(n.code,{children:"render"})," and clears ",(0,r.jsx)(n.code,{children:"screen"})," variable that holds latest ",(0,r.jsx)(n.code,{children:"render"})," output."]}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive info",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"INFO"}),(0,r.jsx)(n.div,{className:"rspress-directive-content",children:(0,r.jsxs)(n.p,{children:["Please note that this is done automatically if the testing framework you're using supports the ",(0,r.jsx)(n.code,{children:"afterEach"})," global (like mocha, Jest, and Jasmine). If not, you will need to do manual cleanups after each test.\n"]})})]}),"\n",(0,r.jsxs)(n.p,{children:["For example, if you're using the ",(0,r.jsx)(n.code,{children:"jest"})," testing framework, then you would need to use the ",(0,r.jsx)(n.code,{children:"afterEach"})," hook like so:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:"import { cleanup, render } from '@testing-library/react-native/pure';\nimport { View } from 'react-native';\n\nafterEach(cleanup);\n\nit('renders a view', () => {\n render();\n // ...\n});\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"afterEach(cleanup)"})," call also works in ",(0,r.jsx)(n.code,{children:"describe"})," blocks:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:"describe('when logged in', () => {\n afterEach(cleanup);\n\n it('renders the user', () => {\n render();\n // ...\n });\n});\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Failing to call ",(0,r.jsx)(n.code,{children:"cleanup"})," when you've called ",(0,r.jsx)(n.code,{children:"render"}),' could result in a memory leak and tests which are not "idempotent" (which can lead to difficult to debug errors in your tests).']})]})}function t(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,i.ah)(),e.components);return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}let a=t;t.__RSPRESS_PAGE_META={},t.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fapi%2Fmisc%2Fother.mdx"]={toc:[{text:"`within`",id:"within",depth:2},{text:"`act`",id:"act",depth:2},{text:"`cleanup`",id:"cleanup",depth:2}],title:"Other helpers",headingTitle:"Other helpers",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/5469.b9ad09f3.js b/static/js/async/5469.b9ad09f3.js new file mode 100644 index 00000000..4bd4a398 --- /dev/null +++ b/static/js/async/5469.b9ad09f3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["5469"],{6495:function(e,n,s){s.r(n),s.d(n,{default:()=>c});var r=s(5893),i=s(65);function t(e){let n=Object.assign({h1:"h1",a:"a",h2:"h2",code:"code",pre:"pre",p:"p",div:"div",em:"em",ul:"ul",li:"li",strong:"strong"},(0,i.ah)(),e.components);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.h1,{id:"other-helpers",children:["Other helpers",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#other-helpers",children:"#"})]}),"\n",(0,r.jsxs)(n.h2,{id:"within",children:[(0,r.jsx)(n.code,{children:"within"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#within",children:"#"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:"function within(element: HostElement): Queries {}\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"within"})," performs ",(0,r.jsx)(n.a,{href:"/docs/api/queries",children:"queries"})," scoped to given element."]}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive note",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"NOTE"}),(0,r.jsx)(n.div,{className:"rspress-directive-content",children:(0,r.jsxs)(n.p,{children:["Please note that additional ",(0,r.jsx)(n.code,{children:"render"})," specific operations like ",(0,r.jsx)(n.code,{children:"rerender"}),", ",(0,r.jsx)(n.code,{children:"unmount"}),", ",(0,r.jsx)(n.code,{children:"debug"}),", ",(0,r.jsx)(n.code,{children:"toJSON"})," are ",(0,r.jsx)(n.em,{children:"not"})," included.\n"]})})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:"const detailsScreen = within(screen.getByHintText('Details Screen'));\nexpect(detailsScreen.getByText('Some Text')).toBeOnTheScreen();\nexpect(detailsScreen.getByDisplayValue('Some Value')).toBeOnTheScreen();\nexpect(detailsScreen.queryByLabelText('Some Label')).toBeOnTheScreen();\nawait expect(detailsScreen.findByHintText('Some Label')).resolves.toBeOnTheScreen();\n"})}),"\n",(0,r.jsx)(n.p,{children:"Use cases for scoped queries include:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"queries scoped to a single item inside a FlatList containing many items"}),"\n",(0,r.jsx)(n.li,{children:"queries scoped to a single screen in tests involving screen transitions (e.g. with react-navigation)"}),"\n"]}),"\n",(0,r.jsxs)(n.h2,{id:"act",children:[(0,r.jsx)(n.code,{children:"act"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#act",children:"#"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"function act(callback: () => T | Promise): Promise;\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Wraps code that causes React state updates to ensure all updates are processed before assertions. By default any ",(0,r.jsx)(n.code,{children:"render"}),", ",(0,r.jsx)(n.code,{children:"rerender"}),", ",(0,r.jsx)(n.code,{children:"fireEvent"}),", and ",(0,r.jsx)(n.code,{children:"waitFor"})," calls are wrapped by this function, so there is no need to wrap it manually."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsxs)(n.strong,{children:["In v14, ",(0,r.jsx)(n.code,{children:"act"})," is now async by default and always returns a Promise"]}),", making it compatible with async React features like ",(0,r.jsx)(n.code,{children:"Suspense"})," boundary or ",(0,r.jsx)(n.code,{children:"use()"})," hook. This ensures all pending React updates are executed before the Promise resolves."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"import { act } from '@testing-library/react-native';\n\nit('should update state', async () => {\n await act(() => {\n setState('new value');\n });\n expect(state).toBe('new value');\n});\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Note"}),": Even if your callback is synchronous, you should still use ",(0,r.jsx)(n.code,{children:"await act(...)"})," as ",(0,r.jsx)(n.code,{children:"act"})," now always returns a Promise."]}),"\n",(0,r.jsxs)(n.p,{children:["Consult our ",(0,r.jsx)(n.a,{href:"/docs/advanced/understanding-act",children:"Understanding Act function"})," document for more understanding of its intricacies."]}),"\n",(0,r.jsxs)(n.h2,{id:"cleanup",children:[(0,r.jsx)(n.code,{children:"cleanup"}),(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#cleanup",children:"#"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ts",children:"function cleanup(): Promise;\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Unmounts React trees that were mounted with ",(0,r.jsx)(n.code,{children:"render"})," and clears ",(0,r.jsx)(n.code,{children:"screen"})," variable that holds latest ",(0,r.jsx)(n.code,{children:"render"})," output."]}),"\n",(0,r.jsxs)(n.div,{className:"rspress-directive info",children:[(0,r.jsx)(n.div,{className:"rspress-directive-title",children:"INFO"}),(0,r.jsx)(n.div,{className:"rspress-directive-content",children:(0,r.jsxs)(n.p,{children:["Please note that this is done automatically if the testing framework you're using supports the ",(0,r.jsx)(n.code,{children:"afterEach"})," global (like mocha, Jest, and Jasmine). If not, you will need to do manual cleanups after each test.\n"]})})]}),"\n",(0,r.jsxs)(n.p,{children:["For example, if you're using the ",(0,r.jsx)(n.code,{children:"jest"})," testing framework, then you would need to use the ",(0,r.jsx)(n.code,{children:"afterEach"})," hook like so:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:"import { cleanup, render } from '@testing-library/react-native/pure';\nimport { View } from 'react-native';\n\nafterEach(async () => {\n await cleanup();\n});\n\nit('renders a view', async () => {\n await render();\n // ...\n});\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"afterEach(cleanup)"})," call also works in ",(0,r.jsx)(n.code,{children:"describe"})," blocks:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-jsx",children:"describe('when logged in', () => {\n afterEach(async () => {\n await cleanup();\n });\n\n it('renders the user', async () => {\n await render();\n // ...\n });\n});\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Failing to call ",(0,r.jsx)(n.code,{children:"cleanup"})," when you've called ",(0,r.jsx)(n.code,{children:"render"}),' could result in a memory leak and tests which are not "idempotent" (which can lead to difficult to debug errors in your tests).']})]})}function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,i.ah)(),e.components);return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(t,{...e})}):t(e)}let c=a;a.__RSPRESS_PAGE_META={},a.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fapi%2Fmisc%2Fother.mdx"]={toc:[{text:"`within`",id:"within",depth:2},{text:"`act`",id:"act",depth:2},{text:"`cleanup`",id:"cleanup",depth:2}],title:"Other helpers",headingTitle:"Other helpers",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/5658.226b400a.js b/static/js/async/5658.226b400a.js deleted file mode 100644 index e9c9aad2..00000000 --- a/static/js/async/5658.226b400a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["5658"],{6413:function(t,e,n){n.r(e),n.d(e,{default:()=>r});var s=n(5893),a=n(65);function i(t){let e=Object.assign({h1:"h1",a:"a",h2:"h2",p:"p",pre:"pre",code:"code",div:"div"},(0,a.ah)(),t.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(e.h1,{id:"jotai",children:["Jotai",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#jotai",children:"#"})]}),"\n",(0,s.jsxs)(e.h2,{id:"introduction",children:["Introduction",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#introduction",children:"#"})]}),"\n",(0,s.jsx)(e.p,{children:"Jotai is a global state management library for React that uses an atomic approach to optimize\nrenders and solve issues like extra re-renders and the need for memoization. It scales from simple\nstate management to complex enterprise applications, offering utilities and extensions to enhance\nthe developer experience."}),"\n",(0,s.jsxs)(e.h2,{id:"task-list-example",children:["Task List Example",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#task-list-example",children:"#"})]}),"\n",(0,s.jsx)(e.p,{children:"Let's assume we have a simple task list component that uses Jotai for state management. The\ncomponent has a list of tasks, a text input for typing new task name and a button to add a new task to the list."}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-tsx",meta:"title=state-management/jotai/TaskList.tsx",children:"import * as React from 'react';\nimport { Pressable, Text, TextInput, View } from 'react-native';\nimport { useAtom } from 'jotai';\nimport { nanoid } from 'nanoid';\nimport { newTaskTitleAtom, tasksAtom } from './state';\n\nexport function TaskList() {\n const [tasks, setTasks] = useAtom(tasksAtom);\n const [newTaskTitle, setNewTaskTitle] = useAtom(newTaskTitleAtom);\n\n const handleAddTask = () => {\n setTasks((tasks) => [\n ...tasks,\n {\n id: nanoid(),\n title: newTaskTitle,\n },\n ]);\n setNewTaskTitle('');\n };\n\n return (\n \n {tasks.map((task) => (\n \n {task.title}\n \n ))}\n\n {!tasks.length ? No tasks, start by adding one... : null}\n\n setNewTaskTitle(text)}\n />\n\n \n Add Task\n \n \n );\n}\n"})}),"\n",(0,s.jsxs)(e.h2,{id:"starting-with-a-simple-test",children:["Starting with a Simple Test",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#starting-with-a-simple-test",children:"#"})]}),"\n",(0,s.jsxs)(e.p,{children:["We can test our ",(0,s.jsx)(e.code,{children:"TaskList"})," component using React Native Testing Library's (RNTL) regular ",(0,s.jsx)(e.code,{children:"render"}),"\nfunction. Although it is sufficient to test the empty state of the ",(0,s.jsx)(e.code,{children:"TaskList"})," component, it is not\nenough to test the component with initial tasks present in the list."]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-tsx",meta:"title=status-management/jotai/__tests__/TaskList.test.tsx",children:"import * as React from 'react';\nimport { render, screen, userEvent } from '@testing-library/react-native';\nimport { renderWithAtoms } from './test-utils';\nimport { TaskList } from './TaskList';\nimport { newTaskTitleAtom, tasksAtom } from './state';\nimport { Task } from './types';\n\njest.useFakeTimers();\n\ntest('renders an empty task list', () => {\n render();\n expect(screen.getByText(/no tasks, start by adding one/i)).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(e.h2,{id:"custom-render-function-to-populate-jotai-atoms-with-initial-values",children:["Custom Render Function to populate Jotai Atoms with Initial Values",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#custom-render-function-to-populate-jotai-atoms-with-initial-values",children:"#"})]}),"\n",(0,s.jsxs)(e.p,{children:["To test the ",(0,s.jsx)(e.code,{children:"TaskList"})," component with initial tasks, we need to be able to populate the ",(0,s.jsx)(e.code,{children:"tasksAtom"})," with\ninitial values. We can create a custom render function that uses Jotai's ",(0,s.jsx)(e.code,{children:"useHydrateAtoms"})," hook to\nhydrate the atoms with initial values. This function will accept the initial atoms and their\ncorresponding values as an argument."]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-tsx",meta:"title=status-management/jotai/test-utils.tsx",children:"import * as React from 'react';\nimport { render } from '@testing-library/react-native';\nimport { useHydrateAtoms } from 'jotai/utils';\nimport { PrimitiveAtom } from 'jotai/vanilla/atom';\n\n// Jotai types are not well exported, so we will make our life easier by using `any`.\nexport type AtomInitialValueTuple = [PrimitiveAtom, T];\n\nexport interface RenderWithAtomsOptions {\n initialValues: AtomInitialValueTuple[];\n}\n\n/**\n * Renders a React component with Jotai atoms for testing purposes.\n *\n * @param component - The React component to render.\n * @param options - The render options including the initial atom values.\n * @returns The render result from `@testing-library/react-native`.\n */\nexport const renderWithAtoms = (\n component: React.ReactElement,\n options: RenderWithAtomsOptions\n) => {\n return render(\n {component}\n );\n};\n\nexport type HydrateAtomsWrapperProps = React.PropsWithChildren<{\n initialValues: AtomInitialValueTuple[];\n}>;\n\n/**\n * A wrapper component that hydrates Jotai atoms with initial values.\n *\n * @param initialValues - The initial values for the Jotai atoms.\n * @param children - The child components to render.\n * @returns The rendered children.\n\n */\nfunction HydrateAtomsWrapper({ initialValues, children }: HydrateAtomsWrapperProps) {\n useHydrateAtoms(initialValues);\n return children;\n}\n"})}),"\n",(0,s.jsxs)(e.h2,{id:"testing-the-tasklist-component-with-initial-tasks",children:["Testing the ",(0,s.jsx)(e.code,{children:"TaskList"})," Component with initial tasks",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#testing-the-tasklist-component-with-initial-tasks",children:"#"})]}),"\n",(0,s.jsxs)(e.p,{children:["We can now use the ",(0,s.jsx)(e.code,{children:"renderWithAtoms"})," function to render the ",(0,s.jsx)(e.code,{children:"TaskList"})," component with initial tasks. The\n",(0,s.jsx)(e.code,{children:"initialValues"})," property will contain the ",(0,s.jsx)(e.code,{children:"tasksAtom"}),", ",(0,s.jsx)(e.code,{children:"newTaskTitleAtom"})," and their initial values. We can then test the component to ensure that the initial tasks are rendered correctly."]}),"\n",(0,s.jsxs)(e.div,{className:"rspress-directive info",children:[(0,s.jsx)(e.div,{className:"rspress-directive-title",children:"INFO"}),(0,s.jsx)(e.div,{className:"rspress-directive-content",children:(0,s.jsx)(e.p,{children:"In our test, we populated only one atom and its initial value, but you can add other Jotai atoms and their corresponding values to the initialValues array as needed."})})]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-tsx",meta:"title=status-management/jotai/__tests__/TaskList.test.tsx",children:"=======\nconst INITIAL_TASKS: Task[] = [{ id: '1', title: 'Buy bread' }];\n\ntest('renders a to do list with 1 items initially, and adds a new item', async () => {\n renderWithAtoms(, {\n initialValues: [\n [tasksAtom, INITIAL_TASKS],\n [newTaskTitleAtom, ''],\n ],\n });\n\n expect(screen.getByText(/buy bread/i)).toBeOnTheScreen();\n expect(screen.getAllByTestId('task-item')).toHaveLength(1);\n\n const user = userEvent.setup();\n await user.type(screen.getByPlaceholderText(/new task/i), 'Buy almond milk');\n await user.press(screen.getByRole('button', { name: /add task/i }));\n\n expect(screen.getByText(/buy almond milk/i)).toBeOnTheScreen();\n expect(screen.getAllByTestId('task-item')).toHaveLength(2);\n});\n"})}),"\n",(0,s.jsxs)(e.h2,{id:"modifying-atom-outside-of-react-components",children:["Modifying atom outside of React components",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#modifying-atom-outside-of-react-components",children:"#"})]}),"\n",(0,s.jsx)(e.p,{children:"In several cases, you might need to change an atom's state outside a React component. In our case,\nwe have a set of functions to get tasks and set tasks, which change the state of the task list atom."}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-tsx",meta:"title=state-management/jotai/state.ts",children:"import { atom, createStore } from 'jotai';\nimport { Task } from './types';\n\nexport const tasksAtom = atom([]);\nexport const newTaskTitleAtom = atom('');\n\n// Available for use outside React components\nexport const store = createStore();\n\n// Selectors\nexport function getAllTasks(): Task[] {\n return store.get(tasksAtom);\n}\n\n// Actions\nexport function addTask(task: Task) {\n store.set(tasksAtom, [...getAllTasks(), task]);\n}\n"})}),"\n",(0,s.jsxs)(e.h2,{id:"testing-atom-outside-of-react-components",children:["Testing atom outside of React components",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#testing-atom-outside-of-react-components",children:"#"})]}),"\n",(0,s.jsxs)(e.p,{children:["You can test the ",(0,s.jsx)(e.code,{children:"getAllTasks"})," and ",(0,s.jsx)(e.code,{children:"addTask"})," functions outside the React component's scope by setting\nthe initial to-do items in the store and then checking if the functions work as expected.\nNo special setup is required to test these functions, as ",(0,s.jsx)(e.code,{children:"store.set"})," is available by default by\nJotai."]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-tsx",meta:"title=state-management/jotai/__tests__/TaskList.test.tsx",children:"import { addTask, getAllTasks, store, tasksAtom } from './state';\n\n//...\n\ntest('modify store outside of React component', () => {\n // Set the initial to do items in the store\n store.set(tasksAtom, INITIAL_TASKS);\n expect(getAllTasks()).toEqual(INITIAL_TASKS);\n\n const NEW_TASK = { id: '2', title: 'Buy almond milk' };\n addTask(NEW_TASK);\n expect(getAllTasks()).toEqual([...INITIAL_TASKS, NEW_TASK]);\n});\n"})}),"\n",(0,s.jsxs)(e.h2,{id:"conclusion",children:["Conclusion",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#conclusion",children:"#"})]}),"\n",(0,s.jsxs)(e.p,{children:["Testing a component or a function that depends on Jotai atoms is straightforward with the help of\nthe ",(0,s.jsx)(e.code,{children:"useHydrateAtoms"})," hook. We've seen how to create a custom render function ",(0,s.jsx)(e.code,{children:"renderWithAtoms"})," that\nsets up atoms and their initial values for testing purposes. We've also seen how to test functions\nthat change the state of atoms outside React components. This approach allows us to test components\nin different states and scenarios, ensuring they behave as expected."]})]})}function o(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:e}=Object.assign({},(0,a.ah)(),t.components);return e?(0,s.jsx)(e,{...t,children:(0,s.jsx)(i,{...t})}):i(t)}let r=o;o.__RSPRESS_PAGE_META={},o.__RSPRESS_PAGE_META["14.x%2Fcookbook%2Fstate-management%2Fjotai.md"]={toc:[{text:"Introduction",id:"introduction",depth:2},{text:"Task List Example",id:"task-list-example",depth:2},{text:"Starting with a Simple Test",id:"starting-with-a-simple-test",depth:2},{text:"Custom Render Function to populate Jotai Atoms with Initial Values",id:"custom-render-function-to-populate-jotai-atoms-with-initial-values",depth:2},{text:"Testing the `TaskList` Component with initial tasks",id:"testing-the-tasklist-component-with-initial-tasks",depth:2},{text:"Modifying atom outside of React components",id:"modifying-atom-outside-of-react-components",depth:2},{text:"Testing atom outside of React components",id:"testing-atom-outside-of-react-components",depth:2},{text:"Conclusion",id:"conclusion",depth:2}],title:"Jotai",headingTitle:"Jotai",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/5658.743a1577.js b/static/js/async/5658.743a1577.js new file mode 100644 index 00000000..bd17228e --- /dev/null +++ b/static/js/async/5658.743a1577.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["5658"],{6413:function(t,e,n){n.r(e),n.d(e,{default:()=>r});var s=n(5893),a=n(65);function i(t){let e=Object.assign({h1:"h1",a:"a",h2:"h2",p:"p",pre:"pre",code:"code",div:"div"},(0,a.ah)(),t.components);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(e.h1,{id:"jotai",children:["Jotai",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#jotai",children:"#"})]}),"\n",(0,s.jsxs)(e.h2,{id:"introduction",children:["Introduction",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#introduction",children:"#"})]}),"\n",(0,s.jsx)(e.p,{children:"Jotai is a global state management library for React that uses an atomic approach to optimize\nrenders and solve issues like extra re-renders and the need for memoization. It scales from simple\nstate management to complex enterprise applications, offering utilities and extensions to enhance\nthe developer experience."}),"\n",(0,s.jsxs)(e.h2,{id:"task-list-example",children:["Task List Example",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#task-list-example",children:"#"})]}),"\n",(0,s.jsx)(e.p,{children:"Let's assume we have a simple task list component that uses Jotai for state management. The\ncomponent has a list of tasks, a text input for typing new task name and a button to add a new task to the list."}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-tsx",meta:"title=state-management/jotai/TaskList.tsx",children:"import * as React from 'react';\nimport { Pressable, Text, TextInput, View } from 'react-native';\nimport { useAtom } from 'jotai';\nimport { nanoid } from 'nanoid';\nimport { newTaskTitleAtom, tasksAtom } from './state';\n\nexport function TaskList() {\n const [tasks, setTasks] = useAtom(tasksAtom);\n const [newTaskTitle, setNewTaskTitle] = useAtom(newTaskTitleAtom);\n\n const handleAddTask = () => {\n setTasks((tasks) => [\n ...tasks,\n {\n id: nanoid(),\n title: newTaskTitle,\n },\n ]);\n setNewTaskTitle('');\n };\n\n return (\n \n {tasks.map((task) => (\n \n {task.title}\n \n ))}\n\n {!tasks.length ? No tasks, start by adding one... : null}\n\n setNewTaskTitle(text)}\n />\n\n \n Add Task\n \n \n );\n}\n"})}),"\n",(0,s.jsxs)(e.h2,{id:"starting-with-a-simple-test",children:["Starting with a Simple Test",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#starting-with-a-simple-test",children:"#"})]}),"\n",(0,s.jsxs)(e.p,{children:["We can test our ",(0,s.jsx)(e.code,{children:"TaskList"})," component using React Native Testing Library's (RNTL) regular ",(0,s.jsx)(e.code,{children:"render"}),"\nfunction. Although it is sufficient to test the empty state of the ",(0,s.jsx)(e.code,{children:"TaskList"})," component, it is not\nenough to test the component with initial tasks present in the list."]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-tsx",meta:"title=state-management/jotai/__tests__/TaskList.test.tsx",children:"import * as React from 'react';\nimport { render, screen, userEvent } from '@testing-library/react-native';\nimport { renderWithAtoms } from './test-utils';\nimport { TaskList } from '../TaskList';\nimport { newTaskTitleAtom, tasksAtom } from '../state';\nimport { Task } from '../types';\n\njest.useFakeTimers();\n\ntest('renders an empty task list', async () => {\n await render();\n expect(screen.getByText(/no tasks, start by adding one/i)).toBeOnTheScreen();\n});\n"})}),"\n",(0,s.jsxs)(e.h2,{id:"custom-render-function-to-populate-jotai-atoms-with-initial-values",children:["Custom Render Function to populate Jotai Atoms with Initial Values",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#custom-render-function-to-populate-jotai-atoms-with-initial-values",children:"#"})]}),"\n",(0,s.jsxs)(e.p,{children:["To test the ",(0,s.jsx)(e.code,{children:"TaskList"})," component with initial tasks, we need to be able to populate the ",(0,s.jsx)(e.code,{children:"tasksAtom"})," with\ninitial values. We can create a custom render function that uses Jotai's ",(0,s.jsx)(e.code,{children:"useHydrateAtoms"})," hook to\nhydrate the atoms with initial values. This function will accept the initial atoms and their\ncorresponding values as an argument."]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-tsx",meta:"title=state-management/jotai/__tests__/test-utils.tsx",children:"import * as React from 'react';\nimport { render } from '@testing-library/react-native';\nimport { useHydrateAtoms } from 'jotai/utils';\nimport { PrimitiveAtom } from 'jotai/vanilla/atom';\n\n// Jotai types are not well exported, so we will make our life easier by using `any`.\nexport type AtomInitialValueTuple = [PrimitiveAtom, T];\n\nexport interface RenderWithAtomsOptions {\n initialValues: AtomInitialValueTuple[];\n}\n\n/**\n * Renders a React component with Jotai atoms for testing purposes.\n *\n * @param component - The React component to render.\n * @param options - The render options including the initial atom values.\n * @returns The render result from `@testing-library/react-native`.\n */\nexport async function renderWithAtoms(\n component: React.ReactElement,\n options: RenderWithAtomsOptions\n) {\n return await render(\n {component}\n );\n}\n\nexport type HydrateAtomsWrapperProps = React.PropsWithChildren<{\n initialValues: AtomInitialValueTuple[];\n}>;\n\n/**\n * A wrapper component that hydrates Jotai atoms with initial values.\n *\n * @param initialValues - The initial values for the Jotai atoms.\n * @param children - The child components to render.\n * @returns The rendered children.\n\n */\nfunction HydrateAtomsWrapper({ initialValues, children }: HydrateAtomsWrapperProps) {\n useHydrateAtoms(initialValues);\n return children;\n}\n"})}),"\n",(0,s.jsxs)(e.h2,{id:"testing-the-tasklist-component-with-initial-tasks",children:["Testing the ",(0,s.jsx)(e.code,{children:"TaskList"})," Component with initial tasks",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#testing-the-tasklist-component-with-initial-tasks",children:"#"})]}),"\n",(0,s.jsxs)(e.p,{children:["We can now use the ",(0,s.jsx)(e.code,{children:"renderWithAtoms"})," function to render the ",(0,s.jsx)(e.code,{children:"TaskList"})," component with initial tasks. The\n",(0,s.jsx)(e.code,{children:"initialValues"})," property will contain the ",(0,s.jsx)(e.code,{children:"tasksAtom"}),", ",(0,s.jsx)(e.code,{children:"newTaskTitleAtom"})," and their initial values. We can then test the component to ensure that the initial tasks are rendered correctly."]}),"\n",(0,s.jsxs)(e.div,{className:"rspress-directive info",children:[(0,s.jsx)(e.div,{className:"rspress-directive-title",children:"INFO"}),(0,s.jsx)(e.div,{className:"rspress-directive-content",children:(0,s.jsx)(e.p,{children:"In our test, we populated only one atom and its initial value, but you can add other Jotai atoms and their corresponding values to the initialValues array as needed."})})]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-tsx",meta:"title=state-management/jotai/__tests__/TaskList.test.tsx",children:"const INITIAL_TASKS: Task[] = [{ id: '1', title: 'Buy bread' }];\n\ntest('renders a to do list with 1 items initially, and adds a new item', async () => {\n await renderWithAtoms(, {\n initialValues: [\n [tasksAtom, INITIAL_TASKS],\n [newTaskTitleAtom, ''],\n ],\n });\n\n expect(screen.getByText(/buy bread/i)).toBeOnTheScreen();\n expect(screen.getAllByTestId('task-item')).toHaveLength(1);\n\n const user = userEvent.setup();\n await user.type(screen.getByPlaceholderText(/new task/i), 'Buy almond milk');\n await user.press(screen.getByRole('button', { name: /add task/i }));\n\n expect(screen.getByText(/buy almond milk/i)).toBeOnTheScreen();\n expect(screen.getAllByTestId('task-item')).toHaveLength(2);\n});\n"})}),"\n",(0,s.jsxs)(e.h2,{id:"modifying-atom-outside-of-react-components",children:["Modifying atom outside of React components",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#modifying-atom-outside-of-react-components",children:"#"})]}),"\n",(0,s.jsx)(e.p,{children:"In several cases, you might need to change an atom's state outside a React component. In our case,\nwe have a set of functions to get tasks and set tasks, which change the state of the task list atom."}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-tsx",meta:"title=state-management/jotai/state.ts",children:"import { atom, createStore } from 'jotai';\nimport { Task } from './types';\n\nexport const tasksAtom = atom([]);\nexport const newTaskTitleAtom = atom('');\n\n// Available for use outside React components\nexport const store = createStore();\n\n// Selectors\nexport function getAllTasks(): Task[] {\n return store.get(tasksAtom);\n}\n\n// Actions\nexport function addTask(task: Task) {\n store.set(tasksAtom, [...getAllTasks(), task]);\n}\n"})}),"\n",(0,s.jsxs)(e.h2,{id:"testing-atom-outside-of-react-components",children:["Testing atom outside of React components",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#testing-atom-outside-of-react-components",children:"#"})]}),"\n",(0,s.jsxs)(e.p,{children:["You can test the ",(0,s.jsx)(e.code,{children:"getAllTasks"})," and ",(0,s.jsx)(e.code,{children:"addTask"})," functions outside the React component's scope by setting\nthe initial to-do items in the store and then checking if the functions work as expected.\nNo special setup is required to test these functions, as ",(0,s.jsx)(e.code,{children:"store.set"})," is available by default by\nJotai."]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-tsx",meta:"title=state-management/jotai/__tests__/TaskList.test.tsx",children:"import { addTask, getAllTasks, store, tasksAtom } from '../state';\n\n//...\n\ntest('modify store outside of React component', () => {\n // Set the initial to do items in the store\n store.set(tasksAtom, INITIAL_TASKS);\n expect(getAllTasks()).toEqual(INITIAL_TASKS);\n\n const NEW_TASK = { id: '2', title: 'Buy almond milk' };\n addTask(NEW_TASK);\n expect(getAllTasks()).toEqual([...INITIAL_TASKS, NEW_TASK]);\n});\n"})}),"\n",(0,s.jsxs)(e.h2,{id:"conclusion",children:["Conclusion",(0,s.jsx)(e.a,{className:"header-anchor","aria-hidden":"true",href:"#conclusion",children:"#"})]}),"\n",(0,s.jsxs)(e.p,{children:["Testing a component or a function that depends on Jotai atoms is straightforward with the help of\nthe ",(0,s.jsx)(e.code,{children:"useHydrateAtoms"})," hook. We've seen how to create a custom render function ",(0,s.jsx)(e.code,{children:"renderWithAtoms"})," that\nsets up atoms and their initial values for testing purposes. We've also seen how to test functions\nthat change the state of atoms outside React components. This approach allows us to test components\nin different states and scenarios, ensuring they behave as expected."]})]})}function o(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:e}=Object.assign({},(0,a.ah)(),t.components);return e?(0,s.jsx)(e,{...t,children:(0,s.jsx)(i,{...t})}):i(t)}let r=o;o.__RSPRESS_PAGE_META={},o.__RSPRESS_PAGE_META["14.x%2Fcookbook%2Fstate-management%2Fjotai.md"]={toc:[{text:"Introduction",id:"introduction",depth:2},{text:"Task List Example",id:"task-list-example",depth:2},{text:"Starting with a Simple Test",id:"starting-with-a-simple-test",depth:2},{text:"Custom Render Function to populate Jotai Atoms with Initial Values",id:"custom-render-function-to-populate-jotai-atoms-with-initial-values",depth:2},{text:"Testing the `TaskList` Component with initial tasks",id:"testing-the-tasklist-component-with-initial-tasks",depth:2},{text:"Modifying atom outside of React components",id:"modifying-atom-outside-of-react-components",depth:2},{text:"Testing atom outside of React components",id:"testing-atom-outside-of-react-components",depth:2},{text:"Conclusion",id:"conclusion",depth:2}],title:"Jotai",headingTitle:"Jotai",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/5820.39680a91.js b/static/js/async/5820.39680a91.js new file mode 100644 index 00000000..60bdbb6a --- /dev/null +++ b/static/js/async/5820.39680a91.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["5820"],{9136:function(e,n,t){t.r(n),t.d(n,{default:()=>l});var r=t(5893),i=t(65),s=t(5552);function a(e){let n=Object.assign({h1:"h1",a:"a",h2:"h2",p:"p",h3:"h3",code:"code",pre:"pre"},(0,i.ah)(),e.components);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.h1,{id:"quick-start",children:["Quick Start",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#quick-start",children:"#"})]}),"\n",(0,r.jsxs)(n.h2,{id:"installation",children:["Installation",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#installation",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"Open a Terminal in your project's folder and run:"}),"\n",(0,r.jsx)(s.SU,{command:{npm:"npm install -D @testing-library/react-native",yarn:"yarn add -D @testing-library/react-native",pnpm:"pnpm add -D @testing-library/react-native",bun:"bun add -D @testing-library/react-native"}}),"\n",(0,r.jsxs)(n.p,{children:["This library has a peer dependency on ",(0,r.jsx)(n.a,{href:"https://github.com/mdjastrzebski/test-renderer",target:"_blank",rel:"noopener noreferrer",children:"Test Renderer"}),". Make sure to install it:"]}),"\n",(0,r.jsx)(s.SU,{command:{npm:"npm install -D test-renderer",yarn:"yarn add -D test-renderer",pnpm:"pnpm add -D test-renderer",bun:"bun add -D test-renderer"}}),"\n",(0,r.jsxs)(n.p,{children:["Test Renderer provides better compatibility with React 19 and improved type safety compared to the deprecated ",(0,r.jsx)(n.a,{href:"https://reactjs.org/docs/test-renderer.html",target:"_blank",rel:"noopener noreferrer",children:"React Test Renderer"}),"."]}),"\n",(0,r.jsxs)(n.h3,{id:"jest-matchers",children:["Jest matchers",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#jest-matchers",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["RNTL automatically extends Jest with React Native-specific matchers. The only thing you need to do is to import anything from ",(0,r.jsx)(n.code,{children:"@testing-library/react-native"})," which you already need to do to access the ",(0,r.jsx)(n.code,{children:"render"})," function."]}),"\n",(0,r.jsxs)(n.h3,{id:"eslint-plugin",children:["ESLint plugin",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#eslint-plugin",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["We recommend setting up ",(0,r.jsx)(n.a,{href:"https://github.com/testing-library/eslint-plugin-testing-library",target:"_blank",rel:"noopener noreferrer",children:(0,r.jsx)(n.code,{children:"eslint-plugin-testing-library"})})," package to help you avoid common Testing Library mistakes and bad practices."]}),"\n",(0,r.jsxs)(n.p,{children:["Install the plugin (assuming you already have ",(0,r.jsx)(n.code,{children:"eslint"})," installed & configured):"]}),"\n",(0,r.jsx)(s.SU,{command:{npm:"npm install -D eslint-plugin-testing-library",yarn:"yarn add -D eslint-plugin-testing-library",pnpm:"pnpm add -D eslint-plugin-testing-library",bun:"bun add -D eslint-plugin-testing-library"}}),"\n",(0,r.jsxs)(n.p,{children:["Then, add relevant entry to your ESLint config (e.g., ",(0,r.jsx)(n.code,{children:".eslintrc.js"}),"). We recommend extending the ",(0,r.jsx)(n.code,{children:"react"})," plugin:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",meta:"title=.eslintrc.js",children:"module.exports = {\n overrides: [\n {\n // Test files only\n files: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)'],\n extends: ['plugin:testing-library/react'],\n },\n ],\n};\n"})})]})}function d(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,i.ah)(),e.components);return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}let l=d;d.__RSPRESS_PAGE_META={},d.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fstart%2Fquick-start.mdx"]={toc:[{text:"Installation",id:"installation",depth:2},{text:"Jest matchers",id:"jest-matchers",depth:3},{text:"ESLint plugin",id:"eslint-plugin",depth:3}],title:"Quick Start",headingTitle:"Quick Start",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/5820.a37ee32a.js b/static/js/async/5820.a37ee32a.js deleted file mode 100644 index 13292a93..00000000 --- a/static/js/async/5820.a37ee32a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["5820"],{9136:function(e,n,t){t.r(n),t.d(n,{default:()=>d});var r=t(5893),i=t(65),s=t(5552);function a(e){let n=Object.assign({h1:"h1",a:"a",h2:"h2",p:"p",code:"code",h3:"h3",pre:"pre"},(0,i.ah)(),e.components);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.h1,{id:"quick-start",children:["Quick Start",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#quick-start",children:"#"})]}),"\n",(0,r.jsxs)(n.h2,{id:"installation",children:["Installation",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#installation",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"Open a Terminal in your project's folder and run:"}),"\n",(0,r.jsx)(s.SU,{command:{yarn:"yarn add -D @testing-library/react-native",npm:"npm install -D @testing-library/react-native"}}),"\n",(0,r.jsxs)(n.p,{children:["This library uses ",(0,r.jsx)(n.a,{href:"https://github.com/mdjastrzebski/test-renderer",target:"_blank",rel:"noopener noreferrer",children:"Test Renderer"})," as its underlying rendering engine. Test Renderer is automatically installed as a dependency and provides better compatibility with React 19 and improved type safety compared to the deprecated ",(0,r.jsx)(n.code,{children:"react-test-renderer"})," package."]}),"\n",(0,r.jsxs)(n.h3,{id:"jest-matchers",children:["Jest matchers",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#jest-matchers",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["RNTL v13 automatically extends Jest with React Native-specific matchers. The only thing you need to do is to import anything from ",(0,r.jsx)(n.code,{children:"@testing-library/react-native"})," which you already need to do to access the ",(0,r.jsx)(n.code,{children:"render"})," function."]}),"\n",(0,r.jsxs)(n.h3,{id:"eslint-plugin",children:["ESLint plugin",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#eslint-plugin",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["We recommend setting up ",(0,r.jsx)(n.a,{href:"https://github.com/testing-library/eslint-plugin-testing-library",target:"_blank",rel:"noopener noreferrer",children:(0,r.jsx)(n.code,{children:"eslint-plugin-testing-library"})})," package to help you avoid common Testing Library mistakes and bad practices."]}),"\n",(0,r.jsxs)(n.p,{children:["Install the plugin (assuming you already have ",(0,r.jsx)(n.code,{children:"eslint"})," installed & configured):"]}),"\n",(0,r.jsx)(s.SU,{command:{yarn:"yarn add -D eslint-plugin-testing-library",npm:"npm install -D eslint-plugin-testing-library"}}),"\n",(0,r.jsxs)(n.p,{children:["Then, add relevant entry to your ESLint config (e.g., ",(0,r.jsx)(n.code,{children:".eslintrc.js"}),"). We recommend extending the ",(0,r.jsx)(n.code,{children:"react"})," plugin:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",meta:"title=.eslintrc.js",children:"module.exports = {\n overrides: [\n {\n // Test files only\n files: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)'],\n extends: ['plugin:testing-library/react'],\n },\n ],\n};\n"})})]})}function l(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,i.ah)(),e.components);return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}let d=l;l.__RSPRESS_PAGE_META={},l.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fstart%2Fquick-start.mdx"]={toc:[{text:"Installation",id:"installation",depth:2},{text:"Jest matchers",id:"jest-matchers",depth:3},{text:"ESLint plugin",id:"eslint-plugin",depth:3}],title:"Quick Start",headingTitle:"Quick Start",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/5828.0039d489.js b/static/js/async/5828.0039d489.js deleted file mode 100644 index 92c15802..00000000 --- a/static/js/async/5828.0039d489.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["5828"],{268:function(e,t,r){r.r(t),r.d(t,{default:()=>o});var n=r(5893),s=r(65);function i(e){let t=Object.assign({h1:"h1",a:"a",p:"p",code:"code",h2:"h2",pre:"pre",div:"div"},(0,s.ah)(),e.components);return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(t.h1,{id:"migration-to-9x",children:["Migration to 9.x",(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#migration-to-9x",children:"#"})]}),"\n",(0,n.jsxs)(t.p,{children:["Version 7.0 brought React Native Testing Library into the ",(0,n.jsx)(t.code,{children:"@testing-library"})," family. Since it has been implemented independently from its web counterpart – the React Testing Library – there are some differences in the API and behavior. Version 9.0 solves several of these problems."]}),"\n",(0,n.jsxs)(t.h2,{id:"support-for-text-match-options-aka-string-precision-api",children:["Support for text match options a.k.a string precision API",(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#support-for-text-match-options-aka-string-precision-api",children:"#"})]}),"\n",(0,n.jsx)(t.p,{children:"This is a backward compatible change."}),"\n",(0,n.jsxs)(t.p,{children:["When querying text, it is now possible to pass a ",(0,n.jsx)(t.a,{href:"/docs/api/queries#textmatch",children:(0,n.jsx)(t.code,{children:"TextMatch"})})," to most text based queries, which lets you configure how ",(0,n.jsx)(t.code,{children:"@testing-library/react-native"})," should match your text. For instance, passing ",(0,n.jsx)(t.code,{children:"exact: false"})," will allow matching substrings and will ignore case:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-jsx",children:"const { getByText } = render(Hello World);\n\ngetByText('Hello World'); // Matches\ngetByText('Hello'); // Doesn't match\ngetByText('hello', { exact: false }); // ignore case-sensitivity and does partial matching\n"})}),"\n",(0,n.jsxs)(t.p,{children:["Please note that the ",(0,n.jsx)(t.code,{children:"findBy*"})," queries used to take a ",(0,n.jsx)(t.code,{children:"waitForOptions"})," parameter as a second argument, which has now been moved to the third argument:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-diff",children:"-findByText('Hello world', { timeout: 3000 }); // old findBy* API\n+findByText('Hello world', {}, { timeout: 3000 }); // new findBy* API\n"})}),"\n",(0,n.jsxs)(t.p,{children:["For backward compatibility RNTL v9 can still read ",(0,n.jsx)(t.code,{children:"waitForOptions"})," from the second argument but will print a deprecation warning."]}),"\n",(0,n.jsxs)(t.h2,{id:"reverted-matching-text-across-several-nodes",children:["Reverted matching text across several nodes",(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#reverted-matching-text-across-several-nodes",children:"#"})]}),"\n",(0,n.jsxs)(t.div,{className:"rspress-directive caution",children:[(0,n.jsx)(t.div,{className:"rspress-directive-title",children:"CAUTION"}),(0,n.jsx)(t.div,{className:"rspress-directive-content",children:(0,n.jsx)(t.p,{children:"This is a breaking change."})})]}),"\n",(0,n.jsx)(t.p,{children:"In v1.14 we've introduced a feature allowing to match text when it's spread across several nodes:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tsx",children:"const { getByText } = render(\n \n Hello world\n \n);\ngetByText('Hello world'); // matches\n"})}),"\n",(0,n.jsx)(t.p,{children:"However this behavior was different than the web one, and wouldn't always be straightforward to reason about. For instance it could match text nodes far from each other on the screen. It also prevented us from implementing the string precision API. From v9, this type of match will not work."}),"\n",(0,n.jsxs)(t.p,{children:["A work around is to use ",(0,n.jsx)(t.code,{children:"within"}),":"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tsx",children:"import { Text } from 'react-native'\nimport { render, within } from '@testing-library/react-native'\n\nconst { getByText } = render(Hello world)\n\nwithin(getByText('Hello', {exact: false})).getByText('world')\n"})}),"\n",(0,n.jsxs)(t.h2,{id:"future-plans",children:["Future plans",(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#future-plans",children:"#"})]}),"\n",(0,n.jsx)(t.p,{children:"This release changes a lot of internal logic in the library, paving the way for more improvements to bring us closer to our web counterpart, with a possibly better story for accessibility queries."}),"\n",(0,n.jsxs)(t.p,{children:["We're also ",(0,n.jsx)(t.a,{href:"https://github.com/callstack/react-native-testing-library/issues/877",target:"_blank",rel:"noopener noreferrer",children:"migrating the codebase to TypeScript"}),". Please let us know if you're interested in helping us with this effort."]}),"\n",(0,n.jsx)(t.p,{children:"Stay safe!"})]})}function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:t}=Object.assign({},(0,s.ah)(),e.components);return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(i,{...e})}):i(e)}let o=a;a.__RSPRESS_PAGE_META={},a.__RSPRESS_PAGE_META["14.x%2Fdocs%2Fmigration%2Fprevious%2Fv9.mdx"]={toc:[{text:"Support for text match options a.k.a string precision API",id:"support-for-text-match-options-aka-string-precision-api",depth:2},{text:"Reverted matching text across several nodes",id:"reverted-matching-text-across-several-nodes",depth:2},{text:"Future plans",id:"future-plans",depth:2}],title:"Migration to 9.x",headingTitle:"Migration to 9.x",frontmatter:{}}}}]); \ No newline at end of file diff --git a/static/js/async/6096.ce7732dc.js b/static/js/async/6096.2960907a.js similarity index 58% rename from static/js/async/6096.ce7732dc.js rename to static/js/async/6096.2960907a.js index f91a93b8..a45f3149 100644 --- a/static/js/async/6096.ce7732dc.js +++ b/static/js/async/6096.2960907a.js @@ -1 +1 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["6096"],{6665:function(e,t,s){s.r(t),s.d(t,{default:()=>r});var n=s(5893),i=s(65);function a(e){let t=Object.assign({h1:"h1",a:"a",p:"p",h2:"h2",code:"code",h3:"h3",pre:"pre",div:"div",ul:"ul",li:"li"},(0,i.ah)(),e.components);return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(t.h1,{id:"jest-matchers",children:["Jest matchers",(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#jest-matchers",children:"#"})]}),"\n",(0,n.jsx)(t.p,{children:"This guide describes built-in Jest matchers, we recommend using these matchers as they provide readable tests, accessibility support, and a better developer experience."}),"\n",(0,n.jsxs)(t.h2,{id:"setup",children:["Setup",(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#setup",children:"#"})]}),"\n",(0,n.jsxs)(t.p,{children:["There is no need to set up the built-in matchers; they are automatically available in your tests when you import anything from ",(0,n.jsx)(t.code,{children:"@testing-library/react-native"}),", e.g., ",(0,n.jsx)(t.code,{children:"render"}),"."]}),"\n",(0,n.jsxs)(t.h2,{id:"migration-from-legacy-jest-native-matchers",children:["Migration from legacy Jest Native matchers.",(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#migration-from-legacy-jest-native-matchers",children:"#"})]}),"\n",(0,n.jsxs)(t.p,{children:["If you are already using legacy Jest Native matchers we have a ",(0,n.jsx)(t.a,{href:"/docs/migration/jest-matchers",children:"migration guide"})," for moving to the built-in matchers."]}),"\n",(0,n.jsxs)(t.h2,{id:"checking-element-existence",children:["Checking element existence",(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#checking-element-existence",children:"#"})]}),"\n",(0,n.jsxs)(t.h3,{id:"tobeonthescreen",children:[(0,n.jsx)(t.code,{children:"toBeOnTheScreen()"}),(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#tobeonthescreen",children:"#"})]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-ts",children:"expect(element).toBeOnTheScreen();\n"})}),"\n",(0,n.jsx)(t.p,{children:"This allows you to assert whether an element is attached to the element tree or not. If you hold a reference to an element and it gets unmounted during the test it will no longer pass this assertion."}),"\n",(0,n.jsxs)(t.h2,{id:"element-content",children:["Element Content",(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#element-content",children:"#"})]}),"\n",(0,n.jsxs)(t.h3,{id:"tohavetextcontent",children:[(0,n.jsx)(t.code,{children:"toHaveTextContent()"}),(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#tohavetextcontent",children:"#"})]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-ts",children:"expect(element).toHaveTextContent(\n text: string | RegExp,\n options?: {\n exact?: boolean;\n normalizer?: (text: string) => string;\n },\n)\n"})}),"\n",(0,n.jsxs)(t.p,{children:["This allows you to assert whether the given element has the given text content or not. It accepts either ",(0,n.jsx)(t.code,{children:"string"})," or ",(0,n.jsx)(t.code,{children:"RegExp"})," matchers, as well as ",(0,n.jsx)(t.a,{href:"/docs/api/queries#text-match-options",children:"text match options"})," of ",(0,n.jsx)(t.code,{children:"exact"})," and ",(0,n.jsx)(t.code,{children:"normalizer"}),"."]}),"\n",(0,n.jsxs)(t.h3,{id:"tocontainelement",children:[(0,n.jsx)(t.code,{children:"toContainElement()"}),(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#tocontainelement",children:"#"})]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-ts",children:"expect(container).toContainElement(\n element: HostElement | null,\n)\n"})}),"\n",(0,n.jsx)(t.p,{children:"This allows you to assert whether the given container element does contain another host element."}),"\n",(0,n.jsxs)(t.h3,{id:"tobeemptyelement",children:[(0,n.jsx)(t.code,{children:"toBeEmptyElement()"}),(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#tobeemptyelement",children:"#"})]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-ts",children:"expect(element).toBeEmptyElement();\n"})}),"\n",(0,n.jsx)(t.p,{children:"This allows you to assert whether the given element does not have any host child elements or text content."}),"\n",(0,n.jsxs)(t.h2,{id:"checking-element-state",children:["Checking element state",(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#checking-element-state",children:"#"})]}),"\n",(0,n.jsxs)(t.h3,{id:"tohavedisplayvalue",children:[(0,n.jsx)(t.code,{children:"toHaveDisplayValue()"}),(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#tohavedisplayvalue",children:"#"})]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-ts",children:"expect(element).toHaveDisplayValue(\n value: string | RegExp,\n options?: {\n exact?: boolean;\n normalizer?: (text: string) => string;\n },\n)\n"})}),"\n",(0,n.jsxs)(t.p,{children:["This allows you to assert whether the given ",(0,n.jsx)(t.code,{children:"TextInput"})," element has a specified display value. It accepts either ",(0,n.jsx)(t.code,{children:"string"})," or ",(0,n.jsx)(t.code,{children:"RegExp"})," matchers, as well as ",(0,n.jsx)(t.a,{href:"/docs/api/queries#text-match-options",children:"text match options"})," of ",(0,n.jsx)(t.code,{children:"exact"})," and ",(0,n.jsx)(t.code,{children:"normalizer"}),"."]}),"\n",(0,n.jsxs)(t.h3,{id:"tohaveaccessibilityvalue",children:[(0,n.jsx)(t.code,{children:"toHaveAccessibilityValue()"}),(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#tohaveaccessibilityvalue",children:"#"})]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-ts",children:"expect(element).toHaveAccessibilityValue(\n value: {\n min?: number;\n max?: number;\n now?: number;\n text?: string | RegExp;\n },\n)\n"})}),"\n",(0,n.jsx)(t.p,{children:"This allows you to assert whether the given element has a specified accessible value."}),"\n",(0,n.jsxs)(t.p,{children:["This matcher will assert accessibility value based on ",(0,n.jsx)(t.code,{children:"aria-valuemin"}),", ",(0,n.jsx)(t.code,{children:"aria-valuemax"}),", ",(0,n.jsx)(t.code,{children:"aria-valuenow"}),", ",(0,n.jsx)(t.code,{children:"aria-valuetext"})," and ",(0,n.jsx)(t.code,{children:"accessibilityValue"})," props. Only defined value entries will be used in the assertion, the element might have additional accessibility value entries and still be matched."]}),"\n",(0,n.jsxs)(t.p,{children:["When querying by ",(0,n.jsx)(t.code,{children:"text"})," entry a string or ",(0,n.jsx)(t.code,{children:"RegExp"})," might be used."]}),"\n",(0,n.jsxs)(t.h3,{id:"tobeenabled",children:[(0,n.jsx)(t.code,{children:"toBeEnabled()"})," / ",(0,n.jsx)(t.code,{children:"toBeDisabled"}),(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#tobeenabled",children:"#"})]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-ts",children:"expect(element).toBeEnabled();\nexpect(element).toBeDisabled();\n"})}),"\n",(0,n.jsxs)(t.p,{children:["These allow you to assert whether the given element is enabled or disabled from the user's perspective. It relies on the accessibility disabled state as set by ",(0,n.jsx)(t.code,{children:"aria-disabled"})," or ",(0,n.jsx)(t.code,{children:"accessibilityState.disabled"})," props. It will consider a given element disabled when it or any of its ancestors is disabled."]}),"\n",(0,n.jsxs)(t.div,{className:"rspress-directive note",children:[(0,n.jsx)(t.div,{className:"rspress-directive-title",children:"NOTE"}),(0,n.jsx)(t.div,{className:"rspress-directive-content",children:(0,n.jsx)(t.p,{children:"These matchers are the negation of each other, and both are provided to avoid double negations in your assertions."})})]}),"\n",(0,n.jsxs)(t.h3,{id:"tobeselected",children:[(0,n.jsx)(t.code,{children:"toBeSelected()"}),(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#tobeselected",children:"#"})]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-ts",children:"expect(element).toBeSelected();\n"})}),"\n",(0,n.jsxs)(t.p,{children:["This allows you to assert whether the given element is selected from the user's perspective. It relies on the accessibility selected state as set by ",(0,n.jsx)(t.code,{children:"aria-selected"})," or ",(0,n.jsx)(t.code,{children:"accessibilityState.selected"})," props."]}),"\n",(0,n.jsxs)(t.h3,{id:"tobechecked",children:[(0,n.jsx)(t.code,{children:"toBeChecked()"})," / ",(0,n.jsx)(t.code,{children:"toBePartiallyChecked()"}),(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#tobechecked",children:"#"})]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-ts",children:"expect(element).toBeChecked();\nexpect(element).toBePartiallyChecked();\n"})}),"\n",(0,n.jsxs)(t.p,{children:["These allow you to assert whether the given element is checked or partially checked from the user's perspective. It relies on the accessibility checked state as set by ",(0,n.jsx)(t.code,{children:"aria-checked"})," or ",(0,n.jsx)(t.code,{children:"accessibilityState.checked"})," props."]}),"\n",(0,n.jsxs)(t.div,{className:"rspress-directive note",children:[(0,n.jsx)(t.div,{className:"rspress-directive-title",children:"NOTE"}),(0,n.jsxs)(t.div,{className:"rspress-directive-content",children:["\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"toBeChecked()"})," matcher works only on ",(0,n.jsx)(t.code,{children:"Switch"})," host elements and accessibility elements with ",(0,n.jsx)(t.code,{children:"checkbox"}),", ",(0,n.jsx)(t.code,{children:"radio"})," or ",(0,n.jsx)(t.code,{children:"switch"})," role."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"toBePartiallyChecked()"})," matcher works only on elements with ",(0,n.jsx)(t.code,{children:"checkbox"})," role."]}),"\n"]}),"\n"]})]}),"\n",(0,n.jsxs)(t.h3,{id:"tobeexpanded",children:[(0,n.jsx)(t.code,{children:"toBeExpanded()"})," / ",(0,n.jsx)(t.code,{children:"toBeCollapsed()"}),(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#tobeexpanded",children:"#"})]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-ts",children:"expect(element).toBeExpanded();\nexpect(element).toBeCollapsed();\n"})}),"\n",(0,n.jsxs)(t.p,{children:["These allows you to assert whether the given element is expanded or collapsed from the user's perspective. It relies on the accessibility disabled state as set by ",(0,n.jsx)(t.code,{children:"aria-expanded"})," or ",(0,n.jsx)(t.code,{children:"accessibilityState.expanded"})," props."]}),"\n",(0,n.jsxs)(t.div,{className:"rspress-directive note",children:[(0,n.jsx)(t.div,{className:"rspress-directive-title",children:"NOTE"}),(0,n.jsx)(t.div,{className:"rspress-directive-content",children:(0,n.jsxs)(t.p,{children:["These matchers are the negation of each other for expandable elements (elements with explicit ",(0,n.jsx)(t.code,{children:"aria-expanded"})," or ",(0,n.jsx)(t.code,{children:"accessibilityState.expanded"})," props). However, both won't pass for non-expandable elements (ones without explicit ",(0,n.jsx)(t.code,{children:"aria-expanded"})," or ",(0,n.jsx)(t.code,{children:"accessibilityState.expanded"})," props).\n"]})})]}),"\n",(0,n.jsxs)(t.h3,{id:"tobebusy",children:[(0,n.jsx)(t.code,{children:"toBeBusy()"}),(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#tobebusy",children:"#"})]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-ts",children:"expect(element).toBeBusy();\n"})}),"\n",(0,n.jsxs)(t.p,{children:["This allows you to assert whether the given element is busy from the user's perspective. It relies on the accessibility selected state as set by ",(0,n.jsx)(t.code,{children:"aria-busy"})," or ",(0,n.jsx)(t.code,{children:"accessibilityState.busy"})," props."]}),"\n",(0,n.jsxs)(t.h2,{id:"checking-element-style",children:["Checking element style",(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#checking-element-style",children:"#"})]}),"\n",(0,n.jsxs)(t.h3,{id:"tobevisible",children:[(0,n.jsx)(t.code,{children:"toBeVisible()"}),(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#tobevisible",children:"#"})]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-ts",children:"expect(element).toBeVisible();\n"})}),"\n",(0,n.jsx)(t.p,{children:"This allows you to assert whether the given element is visible from the user's perspective."}),"\n",(0,n.jsxs)(t.p,{children:["The element is considered invisible when itself or any of its ancestors has ",(0,n.jsx)(t.code,{children:"display: none"})," or ",(0,n.jsx)(t.code,{children:"opacity: 0"})," styles, as well as when it's hidden from accessibility."]}),"\n",(0,n.jsxs)(t.h3,{id:"tohavestyle",children:[(0,n.jsx)(t.code,{children:"toHaveStyle()"}),(0,n.jsx)(t.a,{className:"header-anchor","aria-hidden":"true",href:"#tohavestyle",children:"#"})]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-ts",children:"expect(element).toHaveStyle(\n style: StyleProp