From d5590df7b49e5ffa27a3572075c1c1c5035db2b7 Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Tue, 21 Feb 2023 10:35:06 +0100 Subject: [PATCH] fix: toBeOnTheScreen() with RNTL v12 (#151) --- README.md | 3 +++ package.json | 10 +++++----- src/__tests__/to-be-visible.tsx | 16 ++++++++-------- src/__tests__/to-have-text-content.tsx | 22 +++++++++++----------- src/to-be-on-the-screen.ts | 6 +++--- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index eaef945..1740010 100644 --- a/README.md +++ b/README.md @@ -239,6 +239,9 @@ You can check that an already captured element has not been removed from the ele > **Note**
This matcher requires React Native Testing Library v10.1 or later, as it includes > the `screen` object. +> +> **Note**
If you're using React Native Testing Library v12 or later, you need to install Jest +> Native v5.4.2 or later. #### Examples diff --git a/package.json b/package.json index 5473032..0b8352a 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "@babel/runtime": "^7.18.9", "@callstack/eslint-config": "^13.0.1", "@relmify/jest-serializer-strip-ansi": "^1.0.2", - "@testing-library/react-native": "^11.0.0", + "@testing-library/react-native": "^12.0.0-rc.0", "@types/jest": "^29.0.1", "@types/react": "^18.0.19", "@types/react-native": "^0.71.0", @@ -52,12 +52,12 @@ "eslint": "^8.21.0", "husky": "^8.0.1", "jest": "^29.0.1", - "metro-react-native-babel-preset": "^0.72.3", + "metro-react-native-babel-preset": "0.73.7", "prettier": "^2.7.1", "pretty-quick": "^3.1.3", - "react": "18.1.0", - "react-native": "^0.70.6", - "react-test-renderer": "18.1.0", + "react": "18.2.0", + "react-native": "0.71.3", + "react-test-renderer": "18.2.0", "semantic-release": "^19.0.3", "typescript": "^4.8.3" }, diff --git a/src/__tests__/to-be-visible.tsx b/src/__tests__/to-be-visible.tsx index 281c02a..651e2fc 100644 --- a/src/__tests__/to-be-visible.tsx +++ b/src/__tests__/to-be-visible.tsx @@ -20,7 +20,7 @@ describe('.toBeVisible', () => { test('handles view with display "none"', () => { const { getByTestId } = render(); - expect(getByTestId('test')).not.toBeVisible(); + expect(getByTestId('test', { includeHiddenElements: true })).not.toBeVisible(); }); test('handles ancestor view with 0 opacity', () => { @@ -31,7 +31,7 @@ describe('.toBeVisible', () => { , ); - expect(getByTestId('test')).not.toBeVisible(); + expect(getByTestId('test', { includeHiddenElements: true })).not.toBeVisible(); }); test('handles ancestor view with display "none"', () => { @@ -42,7 +42,7 @@ describe('.toBeVisible', () => { , ); - expect(getByTestId('test')).not.toBeVisible(); + expect(getByTestId('test', { includeHiddenElements: true })).not.toBeVisible(); }); test('handles empty modal', () => { @@ -77,12 +77,12 @@ describe('.toBeVisible', () => { test('handles not visible modal', () => { const { getByTestId } = render(); - expect(getByTestId('test')).not.toBeVisible(); + expect(getByTestId('test', { includeHiddenElements: true })).not.toBeVisible(); }); test('handles inaccessible view (iOS)', () => { const { getByTestId, update } = render(); - expect(getByTestId('test')).not.toBeVisible(); + expect(getByTestId('test', { includeHiddenElements: true })).not.toBeVisible(); update(); expect(getByTestId('test')).toBeVisible(); @@ -96,14 +96,14 @@ describe('.toBeVisible', () => { , ); - expect(getByTestId('test')).not.toBeVisible(); + expect(getByTestId('test', { includeHiddenElements: true })).not.toBeVisible(); }); test('handles inaccessible view (Android)', () => { const { getByTestId, update } = render( , ); - expect(getByTestId('test')).not.toBeVisible(); + expect(getByTestId('test', { includeHiddenElements: true })).not.toBeVisible(); update(); expect(getByTestId('test')).toBeVisible(); @@ -117,7 +117,7 @@ describe('.toBeVisible', () => { , ); - expect(getByTestId('test')).not.toBeVisible(); + expect(getByTestId('test', { includeHiddenElements: true })).not.toBeVisible(); }); test('handles null elements', () => { diff --git a/src/__tests__/to-have-text-content.tsx b/src/__tests__/to-have-text-content.tsx index 3770d56..b43861a 100644 --- a/src/__tests__/to-have-text-content.tsx +++ b/src/__tests__/to-have-text-content.tsx @@ -74,7 +74,7 @@ describe('.toHaveTextContent', () => { test('can handle multiple levels with no explicit children prop', () => { const NoChildren = ({ text }: { text: string }) => {text}; const answer = 'Answer'; - const { container } = render( + const { root } = render( {answer} @@ -86,27 +86,27 @@ describe('.toHaveTextContent', () => { , ); - expect(container).toHaveTextContent(/^Answer: 42$/); + expect(root).toHaveTextContent(/^Answer: 42$/); }); test('throws when no match is found', () => { - const { container } = render(Should succeed); + const { root } = render(Should succeed); expect(() => { - expect(container).toHaveTextContent('Should fail'); + expect(root).toHaveTextContent('Should fail'); }).toThrow(); }); test('does not throw error with empty content', () => { - const { container } = render(); - expect(container).toHaveTextContent(''); + const { root } = render(); + expect(root).toHaveTextContent(''); }); test('is case-sensitive', () => { - const { container } = render(Sensitive text); + const { root } = render(Sensitive text); - expect(container).toHaveTextContent('Sensitive text'); - expect(container).not.toHaveTextContent('sensitive text'); + expect(root).toHaveTextContent('Sensitive text'); + expect(root).not.toHaveTextContent('sensitive text'); }); test('can handle conditional rendering', () => { @@ -124,8 +124,8 @@ describe('.toHaveTextContent', () => { test('can handle text with an interpolated variable', () => { const variable = 'variable'; - const { container } = render(With a {variable}); + const { root } = render(With a {variable}); - expect(container).toHaveTextContent('With a variable'); + expect(root).toHaveTextContent('With a variable'); }); }); diff --git a/src/to-be-on-the-screen.ts b/src/to-be-on-the-screen.ts index 35d824c..9d6a2a1 100644 --- a/src/to-be-on-the-screen.ts +++ b/src/to-be-on-the-screen.ts @@ -7,7 +7,7 @@ export function toBeOnTheScreen(this: jest.MatcherContext, element: ReactTestIns checkReactElement(element, toBeOnTheScreen, this); } - const pass = element === null ? false : getScreen().container === getRootElement(element); + const pass = element === null ? false : getScreenRoot() === getRootElement(element); const errorFound = () => { return `expected element tree not to contain element but found:\n${printElement(element)}`; @@ -37,7 +37,7 @@ function getRootElement(element: ReactTestInstance) { return root; } -function getScreen() { +function getScreenRoot() { try { // eslint-disable-next-line import/no-extraneous-dependencies const { screen } = require('@testing-library/react-native'); @@ -45,7 +45,7 @@ function getScreen() { throw new Error('screen is undefined'); } - return screen; + return screen.UNSAFE_root ?? screen.container; } catch (error) { throw new Error( 'Could not import `screen` object from @testing-library/react-native.\n\n' +