diff --git a/examples/basic/__tests__/App.test.tsx b/examples/basic/__tests__/App.test.tsx
index 671fb2071..ecf09a946 100644
--- a/examples/basic/__tests__/App.test.tsx
+++ b/examples/basic/__tests__/App.test.tsx
@@ -9,9 +9,11 @@ test('renders correctly', () => {
// Idiom: no need to capture render output, as we will use `screen` for queries.
render();
- // Idiom: `getByXxx` is a predicate by itself, but we will use it with `expect().toBeTruthy()`
+ // Idiom: `getBy*` queries are predicates by themselves, but we will use it with `expect().toBeTruthy()`
// to clarify our intent.
- expect(screen.getByText('Sign in to Example App')).toBeTruthy();
+ expect(
+ screen.getByRole('header', { name: 'Sign in to Example App' })
+ ).toBeTruthy();
});
/**
@@ -23,30 +25,34 @@ test('User can sign in successully with correct credentials', async () => {
// Idiom: no need to capture render output, as we will use `screen` for queries.
render();
- // Idiom: `getByXxx` is a predicate by itself, but we will use it with `expect().toBeTruthy()` to
- // clarify our intent.
+ // Idiom: `getBy*` queries are predicates by themselves, but we will use it with `expect().toBeTruthy()`
+ // to clarify our intent.
// Note: `.toBeTruthy()` is the preferred matcher for checking that elements are present.
- expect(screen.getByText('Sign in to Example App')).toBeTruthy();
- expect(screen.getByText('Username')).toBeTruthy();
- expect(screen.getByText('Password')).toBeTruthy();
+ expect(
+ screen.getByRole('header', { name: 'Sign in to Example App' })
+ ).toBeTruthy();
- // Hint: we can use `getByLabelText` to find our text inputs in accessibility-friendly way.
+ // Hint: we can use `getByLabelText` to find our text inputs using their labels.
fireEvent.changeText(screen.getByLabelText('Username'), 'admin');
fireEvent.changeText(screen.getByLabelText('Password'), 'admin1');
- // Hint: we can use `getByText` to find our button by its text.
- fireEvent.press(screen.getByText('Sign In'));
+ // Hint: we can use `getByRole` to find our button with given text.
+ fireEvent.press(screen.getByRole('button', { name: 'Sign In' }));
- // Idiom: since pressing button triggers async operation we need to use `findBy` query to wait
+ // Idiom: since pressing button triggers async operation we need to use `findBy*` query to wait
// for the action to complete.
- // Hint: subsequent queries do not need to use `findBy`, because they are used after the async action
+ // Hint: subsequent queries do not need to use `findBy*`, because they are used after the async action
// already finished
- expect(await screen.findByText('Welcome admin!')).toBeTruthy();
-
- // Idiom: use `queryByXxx` with `expect().toBeFalsy()` to assess that element is not present.
- expect(screen.queryByText('Sign in to Example App')).toBeFalsy();
- expect(screen.queryByText('Username')).toBeFalsy();
- expect(screen.queryByText('Password')).toBeFalsy();
+ expect(
+ await screen.findByRole('header', { name: 'Welcome admin!' })
+ ).toBeTruthy();
+
+ // Idiom: use `queryBy*` with `expect().toBeFalsy()` to assess that element is not present.
+ expect(
+ screen.queryByRole('header', { name: 'Sign in to Example App' })
+ ).toBeFalsy();
+ expect(screen.queryByLabelText('Username')).toBeFalsy();
+ expect(screen.queryByLabelText('Password')).toBeFalsy();
});
/**
@@ -56,7 +62,7 @@ test('User can sign in successully with correct credentials', async () => {
* that is not directly reflected in the UI.
*
* For this reason prefer quries that correspond to things directly observable by the user like:
- * `getByText`, `getByLabelText`, `getByPlaceholderText, `getByDisplayValue`, `getByRole`, etc.
+ * `getByRole`, `getByText`, `getByLabelText`, `getByPlaceholderText, `getByDisplayValue`, etc.
* over `getByTestId` which is not directly observable by the user.
*
* Note: that some times you will have to resort to `getByTestId`, but treat it as a last resort.
@@ -64,22 +70,24 @@ test('User can sign in successully with correct credentials', async () => {
test('User will see errors for incorrect credentials', async () => {
render();
- expect(screen.getByText('Sign in to Example App')).toBeTruthy();
- expect(screen.getByText('Username')).toBeTruthy();
- expect(screen.getByText('Password')).toBeTruthy();
+ expect(
+ screen.getByRole('header', { name: 'Sign in to Example App' })
+ ).toBeTruthy();
fireEvent.changeText(screen.getByLabelText('Username'), 'admin');
fireEvent.changeText(screen.getByLabelText('Password'), 'qwerty123');
- fireEvent.press(screen.getByText('Sign In'));
+ fireEvent.press(screen.getByRole('button', { name: 'Sign In' }));
// Hint: you can use custom Jest Native matcher to check text content.
- expect(await screen.findByLabelText('Error')).toHaveTextContent(
+ expect(await screen.findByRole('alert')).toHaveTextContent(
'Incorrect username or password'
);
- expect(screen.getByText('Sign in to Example App')).toBeTruthy();
- expect(screen.getByText('Username')).toBeTruthy();
- expect(screen.getByText('Password')).toBeTruthy();
+ expect(
+ screen.getByRole('header', { name: 'Sign in to Example App' })
+ ).toBeTruthy();
+ expect(screen.getByLabelText('Username')).toBeTruthy();
+ expect(screen.getByLabelText('Password')).toBeTruthy();
});
/**
@@ -88,23 +96,25 @@ test('User will see errors for incorrect credentials', async () => {
test('User can sign in after incorrect attempt', async () => {
render();
- expect(screen.getByText('Sign in to Example App')).toBeTruthy();
- expect(screen.getByText('Username')).toBeTruthy();
- expect(screen.getByText('Password')).toBeTruthy();
+ expect(
+ screen.getByRole('header', { name: 'Sign in to Example App' })
+ ).toBeTruthy();
fireEvent.changeText(screen.getByLabelText('Username'), 'admin');
fireEvent.changeText(screen.getByLabelText('Password'), 'qwerty123');
- fireEvent.press(screen.getByText('Sign In'));
+ fireEvent.press(screen.getByRole('button', { name: 'Sign In' }));
- expect(await screen.findByLabelText('Error')).toHaveTextContent(
+ expect(await screen.findByRole('alert')).toHaveTextContent(
'Incorrect username or password'
);
fireEvent.changeText(screen.getByLabelText('Password'), 'admin1');
- fireEvent.press(screen.getByText('Sign In'));
+ fireEvent.press(screen.getByRole('button', { name: 'Sign In' }));
expect(await screen.findByText('Welcome admin!')).toBeTruthy();
- expect(screen.queryByText('Sign in to Example App')).toBeFalsy();
- expect(screen.queryByText('Username')).toBeFalsy();
- expect(screen.queryByText('Password')).toBeFalsy();
+ expect(
+ screen.queryByRole('header', { name: 'Sign in to Example App' })
+ ).toBeFalsy();
+ expect(screen.queryByLabelText('Username')).toBeFalsy();
+ expect(screen.queryByLabelText('Password')).toBeFalsy();
});
diff --git a/examples/basic/components/Home.tsx b/examples/basic/components/Home.tsx
index 74317d50d..d1cc588e6 100644
--- a/examples/basic/components/Home.tsx
+++ b/examples/basic/components/Home.tsx
@@ -8,7 +8,9 @@ type Props = {
export function Home({ user }: Props) {
return (
- Welcome {user}!
+
+ Welcome {user}!
+
);
}
diff --git a/examples/basic/components/LoginForm.tsx b/examples/basic/components/LoginForm.tsx
index dc3961e48..191509ea1 100644
--- a/examples/basic/components/LoginForm.tsx
+++ b/examples/basic/components/LoginForm.tsx
@@ -4,7 +4,7 @@ import {
View,
Text,
TextInput,
- TouchableOpacity,
+ Pressable,
ActivityIndicator,
} from 'react-native';
@@ -34,7 +34,9 @@ export function LoginForm({ onLoginSuccess }: Props) {
return (
- Sign in to Example App
+
+ Sign in to Example App
+
Username
{error && (
-
+
{error}
)}
-
+
{isLoading ? (
) : (
Sign In
)}
-
+
);
}
diff --git a/examples/basic/package.json b/examples/basic/package.json
index 3a196bb25..95f620c48 100644
--- a/examples/basic/package.json
+++ b/examples/basic/package.json
@@ -6,25 +6,26 @@
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject",
- "test": "jest"
+ "test": "jest",
+ "typecheck": "tsc --noEmit"
},
"dependencies": {
- "expo": "^46.0.0",
- "expo-status-bar": "~1.4.0",
- "react": "18.0.0",
- "react-dom": "18.0.0",
- "react-native": "0.69.4",
+ "expo": "^47.0.0",
+ "expo-status-bar": "~1.4.2",
+ "react": "18.1.0",
+ "react-dom": "18.1.0",
+ "react-native": "0.70.5",
"react-native-web": "~0.18.7"
},
"devDependencies": {
- "@babel/core": "^7.18.6",
- "@testing-library/jest-native": "^5.0.0",
- "@testing-library/react-native": "^11.0.0",
- "@types/react": "~18.0.0",
- "@types/react-native": "~0.69.1",
- "jest": "^28.0.0",
- "react-test-renderer": "18.0.0",
- "typescript": "^4.6.3"
+ "@babel/core": "^7.19.3",
+ "@testing-library/jest-native": "^5.1.2",
+ "@testing-library/react-native": "^11.4.0",
+ "@types/react": "~18.0.24",
+ "@types/react-native": "~0.70.6",
+ "jest": "^29.3.0",
+ "react-test-renderer": "18.1.0",
+ "typescript": "^4.8.4"
},
"private": true
}