From c8308f8d1f517471da41b3aedb47abae693fa0b2 Mon Sep 17 00:00:00 2001 From: David Calhoun <438664+dcalhoun@users.noreply.github.com> Date: Tue, 11 Jan 2022 12:16:04 -0600 Subject: [PATCH] Fix native test timeouts caused by combining fake timers and setImmediate (#37715) * Upgrade to @testing-library/react-native@8.0.0 * Clean up fake timer usage after tests This may be unnecessary, but avoid potential issues where fake timers are unexpectedly used and cause breakages in other tests. * Enable combination of modern fake timers and waitFor Previously, `waitFor` would timeout when `jest.useFakeTimers('modern')` was enabled. The 'modern' version is now the default in Jest 27. The Jest preset from `@testing-library/react-native` provides a workaround for a larger issue in React Native and Jest that mutates the global `Promise` object. https://git.io/JSDZI * Remove global enabling of fake timers Enabling fake timers can have negative consequences with `waitFor`, e.g. causing unexpected timeouts. Enabling it globally is far-reaching and this should likely be enabled within individual tests as needed. * Replace jest-jasmine2 with jest-circus The latter is considered the successor to the former. We seemingly do not depend on anything explicitly provided by `jest-jasmine2` and should likely move on from it. * Switch testing environment from jsdom to node Improves speed of test environment setup and fixes a timeout issue when combining `waitFor` and `jest.useFakeTimers('modern')`. It is not yet exactly pinpointed as to _why_ this fixes the timeout issue. It appears to related to `setImmediate` and `setTimeout`. * Remove setImmediate global for testing environment This may be unnecessary if `testEnvironment: 'node'` is retained. However, most tests are currently broken due to missing DOM APIs. * Polyfill required DOM APIs for testing environment Now that `testEnvironment: 'node'` is utilized for the testing environment, we must mirror the app runtime and polyfill the necessary DOM APIs used in the source. The Enzyme configuration removed conflicts with the switch from `testEnvironment: 'jsdom'` to `testEnvironment: 'node'`. Enzyme depends upon `react-dom`, which introduces far more dependencies upon DOM APIs. Currently, all Enzyme-related tests fail and need to be replaced with `@testing-library/react-native`. * Avoid import of react-dom within native file Importing `react-dom` introduces additional dependencies upon the DOM API and is incompatible with `testEnvironment: 'node'`. The `act` utility is available from `@testing-library/react-native`. * Explicitly toggle fake timers in tests This may not be necessary, but may help avoid unexpected issues from lingering fake timers, e.g. timeout errors while using `waitFor`. * Reinstate legacy Jest timers The Jest preset from `@testing-library/react-native` that fixed support for "modern" timers by modifying the polyfilled the global `Promise` resulted in new failures from within React Native itself. Specifically, core React Native components rely upon `.done` from the `promise` package. `.done` is a non-standard method that does not exist on the global `Promise` used by `@testing-library/react-native`'s preset. * Disable erroneously failing test This previously passing test now fails after upgrading `@testing-library/react-native` due to changes in the library. Setting `pointerEvent` to "box-none" or "none" currently erroneously prevents triggering other events unrelated to pressing on the element, e.g. `onTouch*`, `onLayout`. https://git.io/JSHZt * Reinstate jest-jasmine2 to support done callback The Jest team create jest-circus as the predecessor for jest-jasmine2. The former does not support the `done` callback with async/await, and would appear to have no plans to do so. It would likely benefit us to refactor the one current test using `done` away from it, and embrace `jest-circus` to maintain alignment with Jest core. * Refactor native unit tests away from done callback The Jest team created `jest-circus` as the predecessor for `jest-jasmine2`. The former does not support the `done` callback with async/await, and would appear to have no plans to do so. In order to embrace `jest-circus` and maintain alignment with Jest core, the one test using `done` was refactored to avoid it - https://git.io/JSHWU - https://git.io/JSHWk * Remove Enzyme from Editor tests * Remove Enzyme from Paragraph tests * Remove Enzyme from BlockMover tests * Remove Enzyme from BlockEdit test * Remove Enzyme from LinksUI test * Remove Enzyme from ListEdit tests * Remove Enzyme from Platform tests * Remove Enzyme from BlockTypesTab tests * Remove Enzyme from HTMLTextInput tests * Remove Enzyme from ReusableBlockTab tests * Remove Enzyme from MediaUpload tests * Remove Enzyme from BlockMediaUpdateProgress tests * Remove Enzyme from MediaUploadProgress tests * Fix ReferencEerror in Inserter test Usage of `react-test-renderer` caused the following error. Leveraging `@testing-library/react-native` instead resolved it for an unknown reason. ``` ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From packages/block-editor/src/components/inserter/test/index.native.js. 468 | style: listStyle, 469 | safeAreaBottomInset, > 470 | scrollEnabled, | ^ 471 | automaticallyAdjustContentInsets: false, 472 | }; 473 | at Object.get PanResponder [as PanResponder] (node_modules/react-native/index.js:251:12) at BottomSheet.render (packages/components/src/mobile/bottom-sheet/index.native.js:470:39) at finishClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8459:31) at updateClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8409:24) at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9990:16) ``` * Fix ReferencEerror in Verse test Usage of `react-test-renderer` caused the following error. Leveraging `@testing-library/react-native` instead resolved it for an unknown reason. ``` ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From packages/block-editor/src/components/inserter/test/index.native.js. 468 | style: listStyle, 469 | safeAreaBottomInset, > 470 | scrollEnabled, | ^ 471 | automaticallyAdjustContentInsets: false, 472 | }; 473 | at Object.get PanResponder [as PanResponder] (node_modules/react-native/index.js:251:12) at BottomSheet.render (packages/components/src/mobile/bottom-sheet/index.native.js:470:39) at finishClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8459:31) at updateClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8409:24) at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9990:16) ``` * Fix ReferencEerror in Audio test Usage of `react-test-renderer` caused the following error. Leveraging `@testing-library/react-native` instead resolved it for an unknown reason. ``` ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From packages/block-editor/src/components/inserter/test/index.native.js. 468 | style: listStyle, 469 | safeAreaBottomInset, > 470 | scrollEnabled, | ^ 471 | automaticallyAdjustContentInsets: false, 472 | }; 473 | at Object.get PanResponder [as PanResponder] (node_modules/react-native/index.js:251:12) at BottomSheet.render (packages/components/src/mobile/bottom-sheet/index.native.js:470:39) at finishClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8459:31) at updateClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8409:24) at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9990:16) ``` * Fix ReferencEerror in File test Usage of `react-test-renderer` caused the following error. Leveraging `@testing-library/react-native` instead resolved it for an unknown reason. ``` ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From packages/block-editor/src/components/inserter/test/index.native.js. 468 | style: listStyle, 469 | safeAreaBottomInset, > 470 | scrollEnabled, | ^ 471 | automaticallyAdjustContentInsets: false, 472 | }; 473 | at Object.get PanResponder [as PanResponder] (node_modules/react-native/index.js:251:12) at BottomSheet.render (packages/components/src/mobile/bottom-sheet/index.native.js:470:39) at finishClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8459:31) at updateClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8409:24) at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9990:16) ``` * Fix ReferencEerror in Search test Usage of `react-test-renderer` caused the following error. Leveraging `@testing-library/react-native` instead resolved it for an unknown reason. ``` ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From packages/block-editor/src/components/inserter/test/index.native.js. 468 | style: listStyle, 469 | safeAreaBottomInset, > 470 | scrollEnabled, | ^ 471 | automaticallyAdjustContentInsets: false, 472 | }; 473 | at Object.get PanResponder [as PanResponder] (node_modules/react-native/index.js:251:12) at BottomSheet.render (packages/components/src/mobile/bottom-sheet/index.native.js:470:39) at finishClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8459:31) at updateClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8409:24) at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9990:16) ``` * Fix ReferencEerror in Missing test Usage of `react-test-renderer` caused the following error. Leveraging `@testing-library/react-native` instead resolved it for an unknown reason. ``` ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From packages/block-editor/src/components/inserter/test/index.native.js. 468 | style: listStyle, 469 | safeAreaBottomInset, > 470 | scrollEnabled, | ^ 471 | automaticallyAdjustContentInsets: false, 472 | }; 473 | at Object.get PanResponder [as PanResponder] (node_modules/react-native/index.js:251:12) at BottomSheet.render (packages/components/src/mobile/bottom-sheet/index.native.js:470:39) at finishClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8459:31) at updateClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8409:24) at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9990:16) ``` * Upgrade to @testing-library/react-native@9.0.0 * Add assertions to block type tab tests Improve test clarity with explicit expect assertions. Co-authored-by: Carlos Garcia * Remove unnecessary abstraction The switch away from Enzyme reduced this abstraction to a single line, so it provides less value now. * Consistently assert media block update progress spinner removal This increases consistency amongst the tests, as most already include this assertion. * Update MediaUpload test to select 'Choose from device' option This selection better aligns with the test description. * Remove duplicative matchMedia global definition The test environment now imports the globals setup file used by the app runtime. That file includes a `matchMedia` global definition as well. * Add assertions to LinkSettings tests Improve test clarity with explicit expect assertions. * Removed shallow renderer usage in tests Shallow rendering components is generally considered a non-optimal approach to testing React components by the React community. This replaces `shallow` with `render` to further test integration of the subject components. * Remove unused import The `React` import was utilized by the now removed `shallow` render implementation. * Remove unnecessary top-level beforeAll usage Jest runs each test file independently, so top-level code will not impact other test files. Since the `(before|after)All` usage in code changed is all top-level, and not within a `describe`, it is superfluous. Co-authored-by: Carlos Garcia --- package-lock.json | 77 +--- package.json | 2 +- .../components/block-edit/test/edit.native.js | 19 +- .../index.native.js | 2 +- .../test/index.native.js | 229 ++++++---- .../test/__snapshots__/index.native.js.snap | 155 +++++-- .../block-mover/test/index.native.js | 10 +- .../inserter/test/block-types-tab.native.js | 19 +- .../components/inserter/test/index.native.js | 10 +- .../test/reusable-blocks-tab.native.js | 18 +- .../media-upload-progress/index.native.js | 1 + .../test/index.native.js | 107 +++-- .../media-upload/test/index.native.js | 75 ++-- .../src/audio/test/edit.native.js | 35 +- .../src/block/test/edit.native.js | 10 +- .../block-library/src/file/edit.native.js | 5 +- .../test/__snapshots__/edit.native.js.snap | 10 +- .../src/file/test/edit.native.js | 42 +- .../src/list/test/edit.native.js | 6 +- .../src/missing/test/edit.native.js | 56 ++- .../src/paragraph/test/edit.native.js | 17 +- .../src/preformatted/edit.native.js | 4 +- .../test/__snapshots__/edit.native.js.snap | 67 ++- .../src/preformatted/test/edit.native.js | 21 +- .../src/search/test/edit.native.js | 56 +-- .../src/verse/test/edit.native.js | 17 +- .../test/navigation-container.native.js | 2 +- .../html-text-input/test/index.native.js | 69 ++- .../mobile/link-settings/test/edit.native.js | 406 ++++++++---------- .../test/link-settings-navigation.native.js | 6 +- .../components/src/spinner/index.native.js | 9 +- .../src/tooltip/test/index.native.js | 4 +- packages/edit-post/src/test/editor.native.js | 8 +- packages/element/src/test/platform.native.js | 12 +- .../src/link/test/index.native.js | 6 +- .../src/link/test/modal.native.js | 6 +- test/native/enzyme.config.js | 6 - test/native/jest.config.js | 12 +- test/native/setup.js | 26 +- 39 files changed, 838 insertions(+), 804 deletions(-) delete mode 100644 test/native/enzyme.config.js diff --git a/package-lock.json b/package-lock.json index 1c83a3bb54090..7fb25146e678b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14422,82 +14422,41 @@ } }, "@testing-library/react-native": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@testing-library/react-native/-/react-native-7.1.0.tgz", - "integrity": "sha512-ljVM9KZqG7BT/NFN6CHzdF6MNmM28+k7MEybFJ7FW1wVrhpiY4+hU9ypZ+hboO+MG3KpE2aFBzP4od3gu+Zzdg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@testing-library/react-native/-/react-native-9.0.0.tgz", + "integrity": "sha512-UE3FWOsDUr+2l3Pg6JTpn2rV5uzYsxIus6ZyN1uMOTmn30bIuBBDDlWQtdWGJx92YcY4xgJA4vViCEKv7wVzJA==", "dev": true, "requires": { - "pretty-format": "^26.0.1" + "pretty-format": "^27.0.0" }, "dependencies": { - "@jest/types": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", - "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - } - }, - "@types/istanbul-reports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz", - "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==", - "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" - } - }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true }, "pretty-format": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", - "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "version": "27.4.6", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.4.6.tgz", + "integrity": "sha512-NblstegA1y/RJW2VyML+3LlpFjzx62cUrtBIKIWDXEDkjNeleA7Od7nrzcs/VLQvAeV4CgSYhrN39DRN88Qi/g==", "dev": true, "requires": { - "@jest/types": "^26.6.2", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", "react-is": "^17.0.1" } }, "react-is": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.1.tgz", - "integrity": "sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true } } diff --git a/package.json b/package.json index 2ae4bc981d04a..46265814ad356 100755 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "@storybook/react": "6.4.9", "@testing-library/jest-dom": "5.16.1", "@testing-library/react": "11.2.2", - "@testing-library/react-native": "7.1.0", + "@testing-library/react-native": "9.0.0", "@types/classnames": "2.3.1", "@types/eslint": "7.28.0", "@types/estree": "0.0.50", diff --git a/packages/block-editor/src/components/block-edit/test/edit.native.js b/packages/block-editor/src/components/block-edit/test/edit.native.js index 8bcc3de486f03..f0c3c9db8a881 100644 --- a/packages/block-editor/src/components/block-edit/test/edit.native.js +++ b/packages/block-editor/src/components/block-edit/test/edit.native.js @@ -1,7 +1,8 @@ /** * External dependencies */ -import { shallow, mount } from 'enzyme'; +import { render } from 'test/helpers'; +import { Text } from 'react-native'; /** * WordPress dependencies @@ -26,26 +27,26 @@ describe( 'Edit', () => { } ); it( 'should return null if block type not defined', () => { - const wrapper = shallow( ); + const screen = render( ); - expect( wrapper.type() ).toBe( null ); + expect( screen.toJSON() ).toBe( null ); } ); it( 'should use edit implementation of block', () => { - const edit = () =>
; + const edit = () => core/test-block; registerBlockType( 'core/test-block', { category: 'text', title: 'block title', edit, } ); - const wrapper = shallow( ); + const screen = render( ); - expect( wrapper.exists( edit ) ).toBe( true ); + expect( screen.getByText( 'core/test-block' ) ).toBeDefined(); } ); it( 'should assign context', () => { - const edit = ( { context } ) => context.value; + const edit = ( { context } ) => { context.value }; registerBlockType( 'core/test-block', { category: 'text', title: 'block title', @@ -53,12 +54,12 @@ describe( 'Edit', () => { edit, } ); - const wrapper = mount( + const screen = render( ); - expect( wrapper.html() ).toBe( 'Ok' ); + expect( screen.getByText( 'Ok' ) ).toBeDefined(); } ); } ); diff --git a/packages/block-editor/src/components/block-media-update-progress/index.native.js b/packages/block-editor/src/components/block-media-update-progress/index.native.js index c3f05ddd29349..a9aab0ca40a36 100644 --- a/packages/block-editor/src/components/block-media-update-progress/index.native.js +++ b/packages/block-editor/src/components/block-media-update-progress/index.native.js @@ -281,7 +281,7 @@ export class BlockMediaUpdateProgress extends Component { { showSpinner && ( - + ) } { renderContent( { diff --git a/packages/block-editor/src/components/block-media-update-progress/test/index.native.js b/packages/block-editor/src/components/block-media-update-progress/test/index.native.js index 82016ab68d9b6..6f7ad9ded1bd5 100644 --- a/packages/block-editor/src/components/block-media-update-progress/test/index.native.js +++ b/packages/block-editor/src/components/block-media-update-progress/test/index.native.js @@ -1,12 +1,17 @@ /** * External dependencies */ -import { shallow } from 'enzyme'; +import { render } from 'test/helpers'; /** * WordPress dependencies */ -import { sendMediaUpload, sendMediaSave } from '@wordpress/react-native-bridge'; +import { + sendMediaSave, + sendMediaUpload, + subscribeMediaSave, + subscribeMediaUpload, +} from '@wordpress/react-native-bridge'; /** * Internal dependencies @@ -25,31 +30,19 @@ import { MEDIA_SAVE_MEDIAID_CHANGED, } from '../'; -jest.mock( '@wordpress/react-native-bridge', () => { - const callUploadCallback = ( payload ) => { - this.uploadCallBack( payload ); - }; - const callSaveCallback = ( payload ) => { - this.saveCallBack( payload ); - }; - const subscribeMediaUpload = ( callback ) => { - this.uploadCallBack = callback; - }; - const subscribeMediaSave = ( callback ) => { - this.saveCallBack = callback; - }; - const mediaSources = { - deviceCamera: 'DEVICE_CAMERA', - deviceLibrary: 'DEVICE_MEDIA_LIBRARY', - siteMediaLibrary: 'SITE_MEDIA_LIBRARY', - }; - return { - subscribeMediaUpload, - subscribeMediaSave, - sendMediaUpload: callUploadCallback, - sendMediaSave: callSaveCallback, - mediaSources, - }; +let uploadCallBack; +subscribeMediaUpload.mockImplementation( ( callback ) => { + uploadCallBack = callback; +} ); +let saveCallBack; +subscribeMediaSave.mockImplementation( ( callback ) => { + saveCallBack = callback; +} ); +sendMediaUpload.mockImplementation( ( payload ) => { + uploadCallBack( payload ); +} ); +sendMediaSave.mockImplementation( ( payload ) => { + saveCallBack( payload ); } ); const MEDIAID_LOCAL = 2; @@ -99,14 +92,15 @@ const localMediaFiles = [ describe( 'BlockMediaUpdateProgress component', () => { it( 'renders without crashing', () => { - const wrapper = shallow( + const wrapper = render( {} } /> ); expect( wrapper ).toBeTruthy(); } ); it( 'upload: onUpdateMediaUploadProgress is called when a progress update payload is received', () => { - const progress = 10; + const renderContentMock = jest.fn(); + const progress = 0.1; const payload = { state: MEDIA_UPLOAD_STATE_UPLOADING, mediaId: MEDIAID_LOCAL, @@ -115,19 +109,23 @@ describe( 'BlockMediaUpdateProgress component', () => { const onUpdateMediaUploadProgress = jest.fn(); - const wrapper = shallow( + const wrapper = render( {} } + renderContent={ renderContentMock } /> ); sendMediaUpload( payload ); - expect( wrapper.instance().state.progress ).toEqual( progress ); - expect( wrapper.instance().state.isUploadInProgress ).toEqual( true ); - expect( wrapper.instance().state.isUploadFailed ).toEqual( false ); + expect( wrapper.getByTestId( 'spinner' ) ).toBeTruthy(); + expect( renderContentMock ).toHaveBeenCalledWith( + expect.objectContaining( { + isUploadInProgress: true, + isUploadFailed: false, + } ) + ); expect( onUpdateMediaUploadProgress ).toHaveBeenCalledTimes( 1 ); expect( onUpdateMediaUploadProgress ).toHaveBeenCalledWith( payload ); } ); @@ -137,10 +135,10 @@ describe( 'BlockMediaUpdateProgress component', () => { const payload = { state: MEDIA_UPLOAD_STATE_UPLOADING, mediaId: 432, // id not belonging to assigned mediaFiles collection in test - progress: 20, + progress: 0.2, }; const onUpdateMediaUploadProgress = jest.fn(); - const wrapper = shallow( + const wrapper = render( { sendMediaUpload( payload ); - expect( wrapper.instance().state.progress ).toEqual( 0 ); + expect( wrapper.queryByTestId( 'spinner' ) ).toBeNull(); expect( onUpdateMediaUploadProgress ).toHaveBeenCalledTimes( 0 ); } ); it( 'upload: onFinishMediaUploadWithSuccess is called when a success payload is received', () => { - const progress = 10; + const renderContentMock = jest.fn(); + const progress = 0.1; const payloadSuccess = { state: MEDIA_UPLOAD_STATE_SUCCEEDED, mediaId: MEDIAID_LOCAL, @@ -168,23 +167,27 @@ describe( 'BlockMediaUpdateProgress component', () => { const onFinishMediaUploadWithSuccess = jest.fn(); - const wrapper = shallow( + const wrapper = render( {} } + renderContent={ renderContentMock } /> ); sendMediaUpload( payloadUploading ); - expect( wrapper.instance().state.progress ).toEqual( progress ); + expect( wrapper.getByTestId( 'spinner' ) ).toBeTruthy(); sendMediaUpload( payloadSuccess ); - expect( wrapper.instance().state.isUploadInProgress ).toEqual( false ); + expect( renderContentMock ).toHaveBeenCalledWith( + expect.objectContaining( { + isUploadInProgress: false, + } ) + ); expect( onFinishMediaUploadWithSuccess ).toHaveBeenCalledTimes( 1 ); expect( onFinishMediaUploadWithSuccess ).toHaveBeenCalledWith( payloadSuccess @@ -192,7 +195,8 @@ describe( 'BlockMediaUpdateProgress component', () => { } ); it( 'upload: onFinishMediaUploadWithFailure is called when a failed payload is received', () => { - const progress = 10; + const renderContentMock = jest.fn(); + const progress = 0.1; const payloadFail = { state: MEDIA_UPLOAD_STATE_FAILED, mediaId: MEDIAID_LOCAL, @@ -205,24 +209,28 @@ describe( 'BlockMediaUpdateProgress component', () => { const onFinishMediaUploadWithFailure = jest.fn(); - const wrapper = shallow( + const wrapper = render( {} } + renderContent={ renderContentMock } /> ); sendMediaUpload( payloadUploading ); - expect( wrapper.instance().state.progress ).toEqual( progress ); + expect( wrapper.getByTestId( 'spinner' ) ).toBeTruthy(); sendMediaUpload( payloadFail ); - expect( wrapper.instance().state.isUploadInProgress ).toEqual( false ); - expect( wrapper.instance().state.isUploadFailed ).toEqual( true ); + expect( renderContentMock ).toHaveBeenCalledWith( + expect.objectContaining( { + isUploadInProgress: false, + isUploadFailed: true, + } ) + ); expect( onFinishMediaUploadWithFailure ).toHaveBeenCalledTimes( 1 ); expect( onFinishMediaUploadWithFailure ).toHaveBeenCalledWith( payloadFail @@ -230,7 +238,8 @@ describe( 'BlockMediaUpdateProgress component', () => { } ); it( 'upload: onMediaUploadStateReset is called when a reset payload is received', () => { - const progress = 10; + const renderContentMock = jest.fn(); + const progress = 0.1; const payloadReset = { state: MEDIA_UPLOAD_STATE_RESET, mediaId: MEDIAID_LOCAL, @@ -243,22 +252,26 @@ describe( 'BlockMediaUpdateProgress component', () => { const onMediaUploadStateReset = jest.fn(); - const wrapper = shallow( + const wrapper = render( {} } + renderContent={ renderContentMock } /> ); sendMediaUpload( payloadUploading ); - expect( wrapper.instance().state.progress ).toEqual( progress ); + expect( wrapper.getByTestId( 'spinner' ) ).toBeTruthy(); sendMediaUpload( payloadReset ); - expect( wrapper.instance().state.isUploadInProgress ).toEqual( false ); - expect( wrapper.instance().state.isUploadFailed ).toEqual( false ); + expect( renderContentMock ).toHaveBeenCalledWith( + expect.objectContaining( { + isUploadInProgress: false, + isUploadFailed: false, + } ) + ); expect( onMediaUploadStateReset ).toHaveBeenCalledTimes( 1 ); expect( onMediaUploadStateReset ).toHaveBeenCalledWith( payloadReset ); } ); @@ -268,10 +281,10 @@ describe( 'BlockMediaUpdateProgress component', () => { const payload = { state: MEDIA_SAVE_STATE_SAVING, mediaId: 'tempid-432', // id not belonging to assigned mediaFiles collection in test - progress: 20, + progress: 0.2, }; const onUpdateMediaSaveProgress = jest.fn(); - const wrapper = shallow( + const wrapper = render( { sendMediaSave( payload ); - expect( wrapper.instance().state.progress ).toEqual( 0 ); + expect( wrapper.queryByTestId( 'spinner' ) ).toBeNull(); expect( onUpdateMediaSaveProgress ).toHaveBeenCalledTimes( 0 ); } ); it( 'save: onFinishMediaSaveWithSuccess is called when a success payload is received', () => { - const progress = 10; + const progress = 0.1; const payloadSuccess = { state: MEDIA_SAVE_STATE_SUCCEEDED, mediaId: MEDIAID_TEMP, // while saving, we have a tempid key @@ -299,7 +312,7 @@ describe( 'BlockMediaUpdateProgress component', () => { const onFinishMediaSaveWithSuccess = jest.fn(); - const wrapper = shallow( + const wrapper = render( { sendMediaSave( payloadSaving ); - expect( wrapper.instance().state.progress ).toEqual( progress ); + expect( wrapper.getByTestId( 'spinner' ) ).toBeTruthy(); sendMediaSave( payloadSuccess ); - expect( wrapper.instance().state.isSaveInProgress ).toEqual( false ); + expect( wrapper.queryByTestId( 'spinner' ) ).toBeNull(); expect( onFinishMediaSaveWithSuccess ).toHaveBeenCalledTimes( 1 ); expect( onFinishMediaSaveWithSuccess ).toHaveBeenCalledWith( payloadSuccess @@ -321,7 +334,8 @@ describe( 'BlockMediaUpdateProgress component', () => { } ); it( 'save: onFinishMediaSaveWithFailure is called when a failed payload is received', () => { - const progress = 10; + const renderContentMock = jest.fn(); + const progress = 0.1; const payloadFail = { state: MEDIA_SAVE_STATE_FAILED, mediaId: MEDIAID_TEMP, // while saving, we have a tempid key @@ -334,22 +348,27 @@ describe( 'BlockMediaUpdateProgress component', () => { const onFinishMediaSaveWithFailure = jest.fn(); - const wrapper = shallow( + const wrapper = render( {} } + renderContent={ renderContentMock } /> ); sendMediaSave( payloadSaving ); - expect( wrapper.instance().state.progress ).toEqual( progress ); + expect( wrapper.getByTestId( 'spinner' ) ).toBeTruthy(); sendMediaSave( payloadFail ); - expect( wrapper.instance().state.isSaveInProgress ).toEqual( false ); - expect( wrapper.instance().state.isSaveFailed ).toEqual( true ); + expect( wrapper.queryByTestId( 'spinner' ) ).toBeNull(); + expect( renderContentMock ).toHaveBeenCalledWith( + expect.objectContaining( { + isSaveInProgress: false, + isSaveFailed: true, + } ) + ); expect( onFinishMediaSaveWithFailure ).toHaveBeenCalledTimes( 1 ); expect( onFinishMediaSaveWithFailure ).toHaveBeenCalledWith( payloadFail @@ -357,7 +376,8 @@ describe( 'BlockMediaUpdateProgress component', () => { } ); it( 'save: onMediaSaveStateReset is called when a reset payload is received', () => { - const progress = 10; + const renderContentMock = jest.fn(); + const progress = 0.1; const payloadReset = { state: MEDIA_SAVE_STATE_RESET, mediaId: MEDIAID_TEMP, // while saving, we have a tempid key @@ -370,28 +390,34 @@ describe( 'BlockMediaUpdateProgress component', () => { const onMediaSaveStateReset = jest.fn(); - const wrapper = shallow( + const wrapper = render( {} } + renderContent={ renderContentMock } /> ); sendMediaSave( payloadSaving ); - expect( wrapper.instance().state.progress ).toEqual( progress ); + expect( wrapper.getByTestId( 'spinner' ) ).toBeTruthy(); sendMediaSave( payloadReset ); - expect( wrapper.instance().state.isSaveInProgress ).toEqual( false ); - expect( wrapper.instance().state.isSaveFailed ).toEqual( false ); + expect( wrapper.queryByTestId( 'spinner' ) ).toBeNull(); + expect( renderContentMock ).toHaveBeenCalledWith( + expect.objectContaining( { + isSaveFailed: false, + isSaveInProgress: false, + } ) + ); expect( onMediaSaveStateReset ).toHaveBeenCalledTimes( 1 ); expect( onMediaSaveStateReset ).toHaveBeenCalledWith( payloadReset ); } ); it( 'save: onFinalSaveResult is called with fail result when fail result is received', () => { - const progress = 10; + const renderContentMock = jest.fn(); + const progress = 0.1; const payloadFail = { state: MEDIA_SAVE_FINAL_STATE_RESULT, mediaId: MEDIAID_TEMP, // while saving, we have a tempid key @@ -405,28 +431,34 @@ describe( 'BlockMediaUpdateProgress component', () => { const onFinalSaveResult = jest.fn(); - const wrapper = shallow( + const wrapper = render( {} } + renderContent={ renderContentMock } /> ); sendMediaSave( payloadSaving ); - expect( wrapper.instance().state.progress ).toEqual( progress ); + expect( wrapper.getByTestId( 'spinner' ) ).toBeTruthy(); sendMediaSave( payloadFail ); - expect( wrapper.instance().state.isSaveInProgress ).toEqual( false ); - expect( wrapper.instance().state.isSaveFailed ).toEqual( true ); + expect( wrapper.queryByTestId( 'spinner' ) ).toBeNull(); + expect( renderContentMock ).toHaveBeenCalledWith( + expect.objectContaining( { + isSaveFailed: true, + isSaveInProgress: false, + } ) + ); expect( onFinalSaveResult ).toHaveBeenCalledTimes( 1 ); expect( onFinalSaveResult ).toHaveBeenCalledWith( payloadFail ); } ); it( 'save: onFinalSaveResult is called with success result when success result is received', () => { - const progress = 10; + const renderContentMock = jest.fn(); + const progress = 0.1; const payloadSuccess = { state: MEDIA_SAVE_FINAL_STATE_RESULT, mediaId: MEDIAID_TEMP, // while saving, we have a tempid key @@ -440,28 +472,34 @@ describe( 'BlockMediaUpdateProgress component', () => { const onFinalSaveResult = jest.fn(); - const wrapper = shallow( + const wrapper = render( {} } + renderContent={ renderContentMock } /> ); sendMediaSave( payloadSaving ); - expect( wrapper.instance().state.progress ).toEqual( progress ); + expect( wrapper.getByTestId( 'spinner' ) ).toBeTruthy(); sendMediaSave( payloadSuccess ); - expect( wrapper.instance().state.isSaveInProgress ).toEqual( false ); - expect( wrapper.instance().state.isSaveFailed ).toEqual( false ); + expect( wrapper.queryByTestId( 'spinner' ) ).toBeNull(); + expect( renderContentMock ).toHaveBeenCalledWith( + expect.objectContaining( { + isSaveFailed: false, + isSaveInProgress: false, + } ) + ); expect( onFinalSaveResult ).toHaveBeenCalledTimes( 1 ); expect( onFinalSaveResult ).toHaveBeenCalledWith( payloadSuccess ); } ); it( 'save: listens to mediaId change and passes it up', () => { - const progress = 10; + const renderContentMock = jest.fn(); + const progress = 0.1; const payloadMediaIdChange = { state: MEDIA_SAVE_MEDIAID_CHANGED, mediaId: MEDIAID_TEMP, // while saving, we have a tempid key @@ -476,24 +514,29 @@ describe( 'BlockMediaUpdateProgress component', () => { const onMediaIdChanged = jest.fn(); - const wrapper = shallow( + const wrapper = render( {} } + renderContent={ renderContentMock } /> ); sendMediaSave( payloadSaving ); - expect( wrapper.instance().state.progress ).toEqual( progress ); + expect( wrapper.getByTestId( 'spinner' ) ).toBeTruthy(); sendMediaSave( payloadMediaIdChange ); - expect( wrapper.instance().state.isSaveInProgress ).toEqual( false ); - expect( wrapper.instance().state.isSaveFailed ).toEqual( false ); - expect( wrapper.instance().state.isUploadInProgress ).toEqual( false ); - expect( wrapper.instance().state.isUploadFailed ).toEqual( false ); + expect( wrapper.queryByTestId( 'spinner' ) ).toBeNull(); + expect( renderContentMock ).toHaveBeenCalledWith( + expect.objectContaining( { + isSaveFailed: false, + isSaveInProgress: false, + isUploadInProgress: false, + isUploadFailed: false, + } ) + ); expect( onMediaIdChanged ).toHaveBeenCalledTimes( 1 ); expect( onMediaIdChanged ).toHaveBeenCalledWith( payloadMediaIdChange ); } ); diff --git a/packages/block-editor/src/components/block-mover/test/__snapshots__/index.native.js.snap b/packages/block-editor/src/components/block-mover/test/__snapshots__/index.native.js.snap index 4836aaa2fb81e..83e30a4a1b0c4 100644 --- a/packages/block-editor/src/components/block-mover/test/__snapshots__/index.native.js.snap +++ b/packages/block-editor/src/components/block-mover/test/__snapshots__/index.native.js.snap @@ -1,55 +1,116 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Block Mover Picker should match snapshot 1`] = ` - - + + - - - } - isDisabled={false} - onClick={[MockFunction]} - onLongPress={[Function]} - title="Move block left from position 2 to position 1" - /> - + Svg + + + + , + + + - - - } - isDisabled={true} - onClick={[MockFunction]} - onLongPress={[Function]} - title="Move block right" - /> - - + + Svg + + + + , +] `; diff --git a/packages/block-editor/src/components/block-mover/test/index.native.js b/packages/block-editor/src/components/block-mover/test/index.native.js index d8201616be6cf..f75583c961373 100644 --- a/packages/block-editor/src/components/block-mover/test/index.native.js +++ b/packages/block-editor/src/components/block-mover/test/index.native.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { shallow } from 'enzyme'; +import { render } from 'test/helpers'; /** * Internal dependencies @@ -24,8 +24,8 @@ describe( 'Block Mover Picker', () => { rootClientId: '', isStackedHorizontally: true, }; - const wrapper = shallow( ); - expect( wrapper ).toBeTruthy(); + const screen = render( ); + expect( screen.container ).toBeTruthy(); } ); it( 'should match snapshot', () => { @@ -43,7 +43,7 @@ describe( 'Block Mover Picker', () => { rootClientId: '', isStackedHorizontally: true, }; - const wrapper = shallow( ); - expect( wrapper ).toMatchSnapshot(); + const screen = render( ); + expect( screen.toJSON() ).toMatchSnapshot(); } ); } ); diff --git a/packages/block-editor/src/components/inserter/test/block-types-tab.native.js b/packages/block-editor/src/components/inserter/test/block-types-tab.native.js index efd2510957a0e..b9f82135fd717 100644 --- a/packages/block-editor/src/components/inserter/test/block-types-tab.native.js +++ b/packages/block-editor/src/components/inserter/test/block-types-tab.native.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { shallow } from 'enzyme'; +import { render } from 'test/helpers'; /** * WordPress dependencies @@ -13,9 +13,7 @@ import { useSelect } from '@wordpress/data'; */ import items from './fixtures'; import BlockTypesTab from '../block-types-tab'; -import BlockTypesList from '../../block-types-list'; -jest.mock( '../../block-types-list' ); jest.mock( '../hooks/use-clipboard-block' ); jest.mock( '@wordpress/data/src/components/use-select' ); @@ -35,11 +33,11 @@ describe( 'BlockTypesTab component', () => { } ); it( 'renders without crashing', () => { - const component = shallow( + const component = render( ); expect( component ).toBeTruthy(); @@ -52,15 +50,16 @@ describe( 'BlockTypesTab component', () => { ( { id, category } ) => category !== 'reusable' && id !== 'core-embed/a-paragraph-embed' ); - const component = shallow( + const component = render( ); - expect( component.find( BlockTypesList ).prop( 'items' ) ).toEqual( - blockItems - ); + + blockItems.forEach( ( item ) => { + expect( component.getByText( item.title ) ).toBeTruthy(); + } ); } ); } ); diff --git a/packages/block-editor/src/components/inserter/test/index.native.js b/packages/block-editor/src/components/inserter/test/index.native.js index f1fe84684a16a..fd65e88ffec3b 100644 --- a/packages/block-editor/src/components/inserter/test/index.native.js +++ b/packages/block-editor/src/components/inserter/test/index.native.js @@ -1,13 +1,12 @@ /** * External dependencies */ -import renderer from 'react-test-renderer'; +import { render } from 'test/helpers'; /** * Internal dependencies */ import { Inserter } from '../index'; -import '../../..'; // Ensure store dependencies are imported via root. const getStylesFromColorScheme = () => { return { color: 'white' }; @@ -15,13 +14,10 @@ const getStylesFromColorScheme = () => { describe( 'Inserter', () => { it( 'button contains the testID "add-block-button"', () => { - const testRenderer = renderer.create( + const screen = render( ); - const testInstance = testRenderer.root; - expect( () => { - testInstance.findByProps( { testID: 'add-block-button' } ); - } ).not.toThrow(); + expect( screen.getByTestId( 'add-block-button' ) ).toBeTruthy(); } ); } ); diff --git a/packages/block-editor/src/components/inserter/test/reusable-blocks-tab.native.js b/packages/block-editor/src/components/inserter/test/reusable-blocks-tab.native.js index f203e9eac1ffb..b96ecd30a3ed0 100644 --- a/packages/block-editor/src/components/inserter/test/reusable-blocks-tab.native.js +++ b/packages/block-editor/src/components/inserter/test/reusable-blocks-tab.native.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { shallow } from 'enzyme'; +import { render } from 'test/helpers'; /** * WordPress dependencies @@ -13,9 +13,7 @@ import { useSelect } from '@wordpress/data'; */ import items from './fixtures'; import ReusableBlocksTab from '../reusable-blocks-tab'; -import BlockTypesList from '../../block-types-list'; -jest.mock( '../../block-types-list' ); jest.mock( '@wordpress/data/src/components/use-select' ); const fetchReusableBlocks = jest.fn(); @@ -34,11 +32,11 @@ describe( 'ReusableBlocksTab component', () => { } ); it( 'renders without crashing', () => { - const component = shallow( + const component = render( ); expect( component ).toBeTruthy(); @@ -50,15 +48,15 @@ describe( 'ReusableBlocksTab component', () => { const reusableBlockItems = items.filter( ( { category } ) => category === 'reusable' ); - const component = shallow( + const component = render( ); - expect( component.find( BlockTypesList ).prop( 'items' ) ).toEqual( - reusableBlockItems - ); + reusableBlockItems.forEach( ( { title } ) => { + expect( component.getByText( title ) ).toBeTruthy(); + } ); } ); } ); diff --git a/packages/block-editor/src/components/media-upload-progress/index.native.js b/packages/block-editor/src/components/media-upload-progress/index.native.js index 386516b097be2..5c7c33b03b203 100644 --- a/packages/block-editor/src/components/media-upload-progress/index.native.js +++ b/packages/block-editor/src/components/media-upload-progress/index.native.js @@ -144,6 +144,7 @@ export class MediaUploadProgress extends Component { ) } diff --git a/packages/block-editor/src/components/media-upload-progress/test/index.native.js b/packages/block-editor/src/components/media-upload-progress/test/index.native.js index a9c9adc6eaf54..1185c9c35a868 100644 --- a/packages/block-editor/src/components/media-upload-progress/test/index.native.js +++ b/packages/block-editor/src/components/media-upload-progress/test/index.native.js @@ -1,12 +1,15 @@ /** * External dependencies */ -import { shallow } from 'enzyme'; +import { render } from 'test/helpers'; /** * WordPress dependencies */ -import { sendMediaUpload } from '@wordpress/react-native-bridge'; +import { + subscribeMediaUpload, + sendMediaUpload, +} from '@wordpress/react-native-bridge'; /** * Internal dependencies @@ -19,37 +22,27 @@ import { MEDIA_UPLOAD_STATE_RESET, } from '../'; -jest.mock( '@wordpress/react-native-bridge', () => { - const callUploadCallback = ( payload ) => { - this.uploadCallBack( payload ); - }; - const subscribeMediaUpload = ( callback ) => { - this.uploadCallBack = callback; - }; - const mediaSources = { - deviceCamera: 'DEVICE_CAMERA', - deviceLibrary: 'DEVICE_MEDIA_LIBRARY', - siteMediaLibrary: 'SITE_MEDIA_LIBRARY', - }; - return { - subscribeMediaUpload, - sendMediaUpload: callUploadCallback, - mediaSources, - }; +let uploadCallBack; +subscribeMediaUpload.mockImplementation( ( callback ) => { + uploadCallBack = callback; +} ); +sendMediaUpload.mockImplementation( ( payload ) => { + uploadCallBack( payload ); } ); const MEDIA_ID = 123; describe( 'MediaUploadProgress component', () => { it( 'renders without crashing', () => { - const wrapper = shallow( + const wrapper = render( {} } /> ); expect( wrapper ).toBeTruthy(); } ); it( 'listens media upload progress', () => { - const progress = 10; + const renderContentMock = jest.fn(); + const progress = 0.1; const payload = { state: MEDIA_UPLOAD_STATE_UPLOADING, mediaId: MEDIA_ID, @@ -58,46 +51,52 @@ describe( 'MediaUploadProgress component', () => { const onUpdateMediaProgress = jest.fn(); - const wrapper = shallow( + const wrapper = render( {} } + renderContent={ renderContentMock } /> ); sendMediaUpload( payload ); - expect( wrapper.instance().state.progress ).toEqual( progress ); - expect( wrapper.instance().state.isUploadInProgress ).toEqual( true ); - expect( wrapper.instance().state.isUploadFailed ).toEqual( false ); + expect( wrapper.getByTestId( 'spinner' ) ).toBeTruthy(); + expect( renderContentMock ).toHaveBeenCalledWith( + expect.objectContaining( { + isUploadInProgress: true, + isUploadFailed: false, + } ) + ); expect( onUpdateMediaProgress ).toHaveBeenCalledTimes( 1 ); expect( onUpdateMediaProgress ).toHaveBeenCalledWith( payload ); } ); it( 'does not get affected by unrelated media uploads', () => { + const renderContentMock = jest.fn(); const payload = { state: MEDIA_UPLOAD_STATE_UPLOADING, mediaId: 1, - progress: 20, + progress: 0.2, }; const onUpdateMediaProgress = jest.fn(); - const wrapper = shallow( + const wrapper = render( {} } + renderContent={ renderContentMock } /> ); sendMediaUpload( payload ); - expect( wrapper.instance().state.progress ).toEqual( 0 ); + expect( wrapper.queryByTestId( 'spinner' ) ).toBeNull(); expect( onUpdateMediaProgress ).toHaveBeenCalledTimes( 0 ); } ); it( 'listens media upload success', () => { - const progress = 10; + const renderContentMock = jest.fn(); + const progress = 0.1; const payloadSuccess = { state: MEDIA_UPLOAD_STATE_SUCCEEDED, mediaId: MEDIA_ID, @@ -110,23 +109,27 @@ describe( 'MediaUploadProgress component', () => { const onFinishMediaUploadWithSuccess = jest.fn(); - const wrapper = shallow( + const wrapper = render( {} } + renderContent={ renderContentMock } /> ); sendMediaUpload( payloadUploading ); - expect( wrapper.instance().state.progress ).toEqual( progress ); + expect( wrapper.getByTestId( 'spinner' ) ).toBeTruthy(); sendMediaUpload( payloadSuccess ); - expect( wrapper.instance().state.isUploadInProgress ).toEqual( false ); + expect( renderContentMock ).toHaveBeenCalledWith( + expect.objectContaining( { + isUploadInProgress: false, + } ) + ); expect( onFinishMediaUploadWithSuccess ).toHaveBeenCalledTimes( 1 ); expect( onFinishMediaUploadWithSuccess ).toHaveBeenCalledWith( payloadSuccess @@ -134,7 +137,8 @@ describe( 'MediaUploadProgress component', () => { } ); it( 'listens media upload fail', () => { - const progress = 10; + const renderContentMock = jest.fn(); + const progress = 0.1; const payloadFail = { state: MEDIA_UPLOAD_STATE_FAILED, mediaId: MEDIA_ID, @@ -147,24 +151,28 @@ describe( 'MediaUploadProgress component', () => { const onFinishMediaUploadWithFailure = jest.fn(); - const wrapper = shallow( + const wrapper = render( {} } + renderContent={ renderContentMock } /> ); sendMediaUpload( payloadUploading ); - expect( wrapper.instance().state.progress ).toEqual( progress ); + expect( wrapper.getByTestId( 'spinner' ) ).toBeTruthy(); sendMediaUpload( payloadFail ); - expect( wrapper.instance().state.isUploadInProgress ).toEqual( false ); - expect( wrapper.instance().state.isUploadFailed ).toEqual( true ); + expect( renderContentMock ).toHaveBeenCalledWith( + expect.objectContaining( { + isUploadInProgress: false, + isUploadFailed: true, + } ) + ); expect( onFinishMediaUploadWithFailure ).toHaveBeenCalledTimes( 1 ); expect( onFinishMediaUploadWithFailure ).toHaveBeenCalledWith( payloadFail @@ -172,7 +180,8 @@ describe( 'MediaUploadProgress component', () => { } ); it( 'listens media upload reset', () => { - const progress = 10; + const renderContentMock = jest.fn(); + const progress = 0.1; const payloadReset = { state: MEDIA_UPLOAD_STATE_RESET, mediaId: MEDIA_ID, @@ -185,22 +194,26 @@ describe( 'MediaUploadProgress component', () => { const onMediaUploadStateReset = jest.fn(); - const wrapper = shallow( + const wrapper = render( {} } + renderContent={ renderContentMock } /> ); sendMediaUpload( payloadUploading ); - expect( wrapper.instance().state.progress ).toEqual( progress ); + expect( wrapper.getByTestId( 'spinner' ) ).toBeTruthy(); sendMediaUpload( payloadReset ); - expect( wrapper.instance().state.isUploadInProgress ).toEqual( false ); - expect( wrapper.instance().state.isUploadFailed ).toEqual( false ); + expect( renderContentMock ).toHaveBeenCalledWith( + expect.objectContaining( { + isUploadInProgress: false, + isUploadFailed: false, + } ) + ); expect( onMediaUploadStateReset ).toHaveBeenCalledTimes( 1 ); expect( onMediaUploadStateReset ).toHaveBeenCalledWith( payloadReset ); } ); diff --git a/packages/block-editor/src/components/media-upload/test/index.native.js b/packages/block-editor/src/components/media-upload/test/index.native.js index a6f5b5f0753de..e54a9f5219321 100644 --- a/packages/block-editor/src/components/media-upload/test/index.native.js +++ b/packages/block-editor/src/components/media-upload/test/index.native.js @@ -1,16 +1,13 @@ /** * External dependencies */ -import { shallow } from 'enzyme'; -import { TouchableWithoutFeedback } from 'react-native'; +import { render, fireEvent } from 'test/helpers'; +import { Text, TouchableWithoutFeedback } from 'react-native'; /** * WordPress dependencies */ -import { - requestMediaPicker, - mediaSources, -} from '@wordpress/react-native-bridge'; +import { requestMediaPicker } from '@wordpress/react-native-bridge'; /** * Internal dependencies @@ -30,48 +27,32 @@ const MEDIA_ID = 123; describe( 'MediaUpload component', () => { it( 'renders without crashing', () => { - const wrapper = shallow( - {} } /> + const wrapper = render( + null } /> ); expect( wrapper ).toBeTruthy(); } ); - it( 'opens media options picker', () => { - const wrapper = shallow( - { - return ( - - { getMediaOptions() } - - ); - } } - /> - ); - expect( wrapper.find( 'Picker' ) ).toHaveLength( 1 ); - } ); - it( 'shows right media capture option for media type', () => { const expectOptionForMediaType = ( mediaType, expectedOption ) => { - const wrapper = shallow( + const wrapper = render( { return ( - + <> + + Open Picker + { getMediaOptions() } - + ); } } /> ); - expect( - wrapper - .find( 'Picker' ) - .props() - .options.filter( ( item ) => item.label === expectedOption ) - ).toHaveLength( 1 ); + fireEvent.press( wrapper.getByText( 'Open Picker' ) ); + + wrapper.getByText( expectedOption ); }; expectOptionForMediaType( MEDIA_TYPE_IMAGE, OPTION_TAKE_PHOTO ); expectOptionForMediaType( MEDIA_TYPE_VIDEO, OPTION_TAKE_VIDEO ); @@ -96,21 +77,25 @@ describe( 'MediaUpload component', () => { const onSelect = jest.fn(); - const wrapper = shallow( + const wrapper = render( { return ( - + <> + + Open Picker + { getMediaOptions() } - + ); } } /> ); - wrapper.find( 'Picker' ).simulate( 'change', option ); + fireEvent.press( wrapper.getByText( 'Open Picker' ) ); + fireEvent.press( wrapper.getByText( option ) ); const media = { id: MEDIA_ID, url: MEDIA_URL }; expect( requestFunction ).toHaveBeenCalledTimes( 1 ); @@ -123,7 +108,7 @@ describe( 'MediaUpload component', () => { it( 'can select media from device library', () => { expectMediaPickerForOption( - mediaSources.deviceLibrary, + 'Choose from device', false, requestMediaPicker ); @@ -131,23 +116,19 @@ describe( 'MediaUpload component', () => { it( 'can select media from WP media library', () => { expectMediaPickerForOption( - mediaSources.siteMediaLibrary, + 'WordPress Media Library', false, requestMediaPicker ); } ); - it( 'can select media by capturig', () => { - expectMediaPickerForOption( - mediaSources.deviceCamera, - false, - requestMediaPicker - ); + it( 'can select media by capturing', () => { + expectMediaPickerForOption( 'Take a Video', false, requestMediaPicker ); } ); it( 'can select multiple media from device library', () => { expectMediaPickerForOption( - mediaSources.deviceLibrary, + 'Choose from device', true, requestMediaPicker ); @@ -155,7 +136,7 @@ describe( 'MediaUpload component', () => { it( 'can select multiple media from WP media library', () => { expectMediaPickerForOption( - mediaSources.siteMediaLibrary, + 'WordPress Media Library', true, requestMediaPicker ); diff --git a/packages/block-library/src/audio/test/edit.native.js b/packages/block-library/src/audio/test/edit.native.js index ef0b678f36313..b59c36db2f66e 100644 --- a/packages/block-library/src/audio/test/edit.native.js +++ b/packages/block-library/src/audio/test/edit.native.js @@ -1,13 +1,17 @@ /** * External dependencies */ -import { act, create } from 'react-test-renderer'; +import { render } from 'test/helpers'; /** * WordPress dependencies */ -import { MediaUploadProgress, BlockEdit } from '@wordpress/block-editor'; +import { BlockEdit } from '@wordpress/block-editor'; import { registerBlockType, unregisterBlockType } from '@wordpress/blocks'; +import { + subscribeMediaUpload, + sendMediaUpload, +} from '@wordpress/react-native-bridge'; /** * Internal dependencies @@ -18,12 +22,22 @@ import { metadata, settings, name } from '../index'; // snapshot testing where we want to keep the original component. jest.unmock( '@wordpress/react-native-aztec' ); +const MEDIA_UPLOAD_STATE_FAILED = 3; + +let uploadCallBack; +subscribeMediaUpload.mockImplementation( ( callback ) => { + uploadCallBack = callback; +} ); +sendMediaUpload.mockImplementation( ( payload ) => { + uploadCallBack( payload ); +} ); + const AudioEdit = ( { clientId, ...props } ) => ( ); const getTestComponentWithContent = ( attributes = {} ) => { - return create( + return render( ); }; @@ -57,18 +71,17 @@ describe( 'Audio block', () => { } ); it( 'renders audio block error state without crashing', () => { + const MEDIA_ID = '1'; const component = getTestComponentWithContent( { src: 'https://cldup.com/59IrU0WJtq.mp3', - id: '1', + id: MEDIA_ID, } ); - const mediaUpload = component.root.findByType( MediaUploadProgress ); - - act( () => { - mediaUpload.instance.finishMediaUploadWithFailure( { - mediaId: -1, - } ); - } ); + const payloadFail = { + state: MEDIA_UPLOAD_STATE_FAILED, + mediaId: MEDIA_ID, + }; + sendMediaUpload( payloadFail ); const rendered = component.toJSON(); expect( rendered ).toMatchSnapshot(); diff --git a/packages/block-library/src/block/test/edit.native.js b/packages/block-library/src/block/test/edit.native.js index a24210b0bce2c..4c4ef6e72a524 100644 --- a/packages/block-library/src/block/test/edit.native.js +++ b/packages/block-library/src/block/test/edit.native.js @@ -26,15 +26,15 @@ const getMockedReusableBlock = ( id ) => ( {

First Reusable block

- +

Bold Italic Striked Superscript(1) Subscript(2) Link

- + !-- wp:heading {"level":4} -->

List

- +
  • First Item
  • Second Item
  • Third Item
@@ -145,7 +145,9 @@ describe( 'Reusable block', () => { expect( blockDeleted ).toBeDefined(); } ); - it( 'renders block content', async () => { + // Skipped until `pointerEvents: 'none'` no longer erroneously prevents + // triggering `onLayout*` on the element: https://git.io/JSHZt + it.skip( 'renders block content', async () => { // We have to use different ids because entities are cached in memory. const id = 4; const initialHtml = ``; diff --git a/packages/block-library/src/file/edit.native.js b/packages/block-library/src/file/edit.native.js index 1d1db7c4922d3..841407278b449 100644 --- a/packages/block-library/src/file/edit.native.js +++ b/packages/block-library/src/file/edit.native.js @@ -455,7 +455,10 @@ export class FileEdit extends Component { onLongPress={ openMediaOptions } disabled={ ! isSelected } > - + { this.getPlaceholderWidth( placeholderText ) } { isUploadInProgress || this.getToolbarEditButton( diff --git a/packages/block-library/src/file/test/__snapshots__/edit.native.js.snap b/packages/block-library/src/file/test/__snapshots__/edit.native.js.snap index acd28d1cfb29b..34a76a0e65096 100644 --- a/packages/block-library/src/file/test/__snapshots__/edit.native.js.snap +++ b/packages/block-library/src/file/test/__snapshots__/edit.native.js.snap @@ -22,10 +22,10 @@ exports[`File block renders file error state without crashing 1`] = ` { + uploadCallBack = callback; +} ); +sendMediaUpload.mockImplementation( ( payload ) => { + uploadCallBack( payload ); +} ); + const getTestComponentWithContent = ( attributes = {} ) => { - return renderer.create( + return render( { id: '1', } ); - component - .getInstance() - .onLayout( { nativeEvent: { layout: { width: 100 } } } ); + fireEvent( component.getByTestId( 'file-edit-container' ), 'layout', { + nativeEvent: { layout: { width: 100 } }, + } ); const rendered = component.toJSON(); expect( rendered ).toMatchSnapshot(); } ); it( 'renders file error state without crashing', () => { + const MEDIA_ID = '1'; const component = getTestComponentWithContent( { showDownloadButton: true, downloadButtonText: 'Download', href: 'https://wordpress.org/latest.zip', fileName: 'File name', textLinkHref: 'https://wordpress.org/latest.zip', - id: '1', + id: MEDIA_ID, + } ); + fireEvent( component.getByTestId( 'file-edit-container' ), 'layout', { + nativeEvent: { layout: { width: 100 } }, } ); - component - .getInstance() - .onLayout( { nativeEvent: { layout: { width: 100 } } } ); - const mediaUpload = component.root.findByType( MediaUploadProgress ); - mediaUpload.instance.finishMediaUploadWithFailure( { mediaId: -1 } ); + const payloadFail = { + state: MEDIA_UPLOAD_STATE_FAILED, + mediaId: MEDIA_ID, + }; + sendMediaUpload( payloadFail ); const rendered = component.toJSON(); expect( rendered ).toMatchSnapshot(); diff --git a/packages/block-library/src/list/test/edit.native.js b/packages/block-library/src/list/test/edit.native.js index 0968a02f2eba1..73a15b9604e4d 100644 --- a/packages/block-library/src/list/test/edit.native.js +++ b/packages/block-library/src/list/test/edit.native.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { shallow } from 'enzyme'; +import { render } from 'test/helpers'; /** * Internal dependencies @@ -10,7 +10,7 @@ import ListEdit from '../edit'; describe( 'ListEdit component', () => { it( 'renders without crashing', () => { - const wrapper = shallow( ); - expect( wrapper ).toBeTruthy(); + const screen = render( ); + expect( screen.container ).toBeTruthy(); } ); } ); diff --git a/packages/block-library/src/missing/test/edit.native.js b/packages/block-library/src/missing/test/edit.native.js index af1ad2010a466..f57e4c72d837b 100644 --- a/packages/block-library/src/missing/test/edit.native.js +++ b/packages/block-library/src/missing/test/edit.native.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import renderer from 'react-test-renderer'; +import { render } from 'test/helpers'; import { Text } from 'react-native'; /** @@ -23,9 +23,7 @@ const defaultAttributes = { }; const getTestComponentWithContent = ( attributes = defaultAttributes ) => { - return renderer.create( - - ); + return render( ); }; describe( 'Missing block', () => { @@ -34,33 +32,30 @@ describe( 'Missing block', () => { } ); it( 'renders without crashing', () => { - const component = getTestComponentWithContent(); - const rendered = component.toJSON(); + const testInstance = getTestComponentWithContent(); + const rendered = testInstance.toJSON(); expect( rendered ).toMatchSnapshot(); } ); describe( 'help modal', () => { it( 'renders help icon', () => { - const component = getTestComponentWithContent(); - const testInstance = component.root; - const icons = testInstance.findAllByType( Icon ); + const testInstance = getTestComponentWithContent(); + const icons = testInstance.UNSAFE_getAllByType( Icon ); expect( icons.length ).toBe( 2 ); expect( icons[ 0 ].props.icon ).toBe( help ); } ); it( 'renders info icon on modal', () => { - const component = getTestComponentWithContent(); - const testInstance = component.root; - const bottomSheet = testInstance.findByType( BottomSheet ); + const testInstance = getTestComponentWithContent(); + const bottomSheet = testInstance.UNSAFE_getByType( BottomSheet ); const children = bottomSheet.props.children[ 0 ].props.children; expect( children.length ).toBe( 3 ); // 4 children in the bottom sheet: the icon, the "isn't yet supported" title and the "We are working hard..." message expect( children[ 0 ].props.icon ).toBe( help ); } ); it( 'renders unsupported text on modal', () => { - const component = getTestComponentWithContent(); - const testInstance = component.root; - const bottomSheet = testInstance.findByType( BottomSheet ); + const testInstance = getTestComponentWithContent(); + const bottomSheet = testInstance.UNSAFE_getByType( BottomSheet ); const children = bottomSheet.props.children[ 0 ].props.children; expect( children[ 1 ].props.children ).toBe( "'" + @@ -78,9 +73,10 @@ describe( 'Missing block', () => { } ); it( 'renders edit action if UBE is available', () => { - const component = getTestComponentWithContent(); - const testInstance = component.root; - const bottomSheet = testInstance.findByType( BottomSheet ); + const testInstance = getTestComponentWithContent(); + const bottomSheet = testInstance.UNSAFE_getByType( + BottomSheet + ); const bottomSheetCells = bottomSheet.props.children[ 1 ]; expect( bottomSheetCells ).toBeTruthy(); expect( bottomSheetCells.props.children.length ).toBe( 2 ); @@ -94,35 +90,35 @@ describe( 'Missing block', () => { unsupportedBlockEditor: false, } ); - const component = getTestComponentWithContent(); - const testInstance = component.root; - const bottomSheet = testInstance.findByType( BottomSheet ); + const testInstance = getTestComponentWithContent(); + const bottomSheet = testInstance.UNSAFE_getByType( + BottomSheet + ); expect( bottomSheet.props.children[ 1 ] ).toBeFalsy(); } ); it( 'does not render edit action if the block is incompatible with UBE', () => { - const component = getTestComponentWithContent( { + const testInstance = getTestComponentWithContent( { originalName: 'core/block', } ); - const testInstance = component.root; - const bottomSheet = testInstance.findByType( BottomSheet ); + const bottomSheet = testInstance.UNSAFE_getByType( + BottomSheet + ); expect( bottomSheet.props.children[ 1 ] ).toBeFalsy(); } ); } ); } ); it( 'renders admin plugins icon', () => { - const component = getTestComponentWithContent(); - const testInstance = component.root; - const icons = testInstance.findAllByType( Icon ); + const testInstance = getTestComponentWithContent(); + const icons = testInstance.UNSAFE_getAllByType( Icon ); expect( icons.length ).toBe( 2 ); expect( icons[ 1 ].props.icon ).toBe( plugins ); } ); it( 'renders title text without crashing', () => { - const component = getTestComponentWithContent(); - const testInstance = component.root; - const texts = testInstance.findAllByType( Text ); + const testInstance = getTestComponentWithContent(); + const texts = testInstance.UNSAFE_getAllByType( Text ); expect( texts.length ).toBe( 2 ); expect( texts[ 0 ].props.children ).toBe( 'missing/block/title' ); expect( texts[ 1 ].props.children ).toBe( 'Unsupported' ); diff --git a/packages/block-library/src/paragraph/test/edit.native.js b/packages/block-library/src/paragraph/test/edit.native.js index 1602f2f4fa706..5a3f4120d4723 100644 --- a/packages/block-library/src/paragraph/test/edit.native.js +++ b/packages/block-library/src/paragraph/test/edit.native.js @@ -1,24 +1,15 @@ /** * External dependencies */ -import { shallow } from 'enzyme'; +import { render } from 'test/helpers'; /** * Internal dependencies */ import Paragraph from '../edit'; -/** - * WordPress dependencies - */ -jest.mock( '@wordpress/blocks' ); -jest.mock( '../../../../data/src/components/use-select', () => () => ( { - attributes: () => {}, - settingsColors: [], -} ) ); - const getTestComponentWithContent = ( content ) => { - return shallow( + return render( { describe( 'Paragraph block', () => { it( 'renders without crashing', () => { - const component = getTestComponentWithContent( '' ); - expect( component.exists() ).toBe( true ); + const screen = getTestComponentWithContent( '' ); + expect( screen.container ).toBeTruthy(); } ); } ); diff --git a/packages/block-library/src/preformatted/edit.native.js b/packages/block-library/src/preformatted/edit.native.js index 922df2f23081c..325e99e2a1583 100644 --- a/packages/block-library/src/preformatted/edit.native.js +++ b/packages/block-library/src/preformatted/edit.native.js @@ -12,7 +12,7 @@ import { usePreferredColorSchemeStyle } from '@wordpress/compose'; import WebPreformattedEdit from './edit.js'; import styles from './styles.scss'; -export function PreformattedEdit( props ) { +export default function PreformattedEdit( props ) { const { style } = props; const textBaseStyle = usePreferredColorSchemeStyle( @@ -48,5 +48,3 @@ export function PreformattedEdit( props ) { ); } - -export default PreformattedEdit; diff --git a/packages/block-library/src/preformatted/test/__snapshots__/edit.native.js.snap b/packages/block-library/src/preformatted/test/__snapshots__/edit.native.js.snap index 46c529c81a791..9868476671f5a 100644 --- a/packages/block-library/src/preformatted/test/__snapshots__/edit.native.js.snap +++ b/packages/block-library/src/preformatted/test/__snapshots__/edit.native.js.snap @@ -10,11 +10,33 @@ exports[`core/more/edit/native should match snapshot when content is empty 1`] = ] } > - + + + `; @@ -28,15 +50,32 @@ exports[`core/more/edit/native should match snapshot when content is not empty 1 ] } > - + + disableEditingMenu={false} + fontFamily="serif" + fontSize={16} + isMultiline={false} + maxImagesWidth={200} + onBlur={[Function]} + onChange={[Function]} + onContentSizeChange={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onPaste={[Function]} + onSelectionChange={[Function]} + placeholder="Write preformatted text…" + placeholderTextColor="gray" + triggerKeyCodes={Array []} + value="
Hello World!
" + /> +
`; diff --git a/packages/block-library/src/preformatted/test/edit.native.js b/packages/block-library/src/preformatted/test/edit.native.js index 5b72ad1e42032..ec6b8276e210e 100644 --- a/packages/block-library/src/preformatted/test/edit.native.js +++ b/packages/block-library/src/preformatted/test/edit.native.js @@ -1,44 +1,45 @@ /** * External dependencies */ -import ShallowRenderer from 'react-test-renderer/shallow'; -const shallowRenderer = new ShallowRenderer(); +import { render } from 'test/helpers'; /** * Internal dependencies */ -import { PreformattedEdit } from '../edit'; +import PreformattedEdit from '../edit'; describe( 'core/more/edit/native', () => { it( 'renders without crashing', () => { - shallowRenderer.render( + const screen = render( ); - const element = shallowRenderer.getRenderOutput(); - expect( element.type ).toBeDefined(); + + expect( screen.container ).toBeDefined(); } ); it( 'should match snapshot when content is empty', () => { - shallowRenderer.render( + const screen = render( styles1 } /> ); - expect( shallowRenderer.getRenderOutput() ).toMatchSnapshot(); + expect( screen.toJSON() ).toMatchSnapshot(); } ); it( 'should match snapshot when content is not empty', () => { - shallowRenderer.render( + const screen = render( styles1 } /> ); - expect( shallowRenderer.getRenderOutput() ).toMatchSnapshot(); + expect( screen.toJSON() ).toMatchSnapshot(); } ); } ); diff --git a/packages/block-library/src/search/test/edit.native.js b/packages/block-library/src/search/test/edit.native.js index f37417501b6df..fca3eff71b106 100644 --- a/packages/block-library/src/search/test/edit.native.js +++ b/packages/block-library/src/search/test/edit.native.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import renderer from 'react-test-renderer'; +import { render } from 'test/helpers'; /** * WordPress dependencies @@ -26,31 +26,31 @@ const defaultAttributes = { const getTestComponent = ( attributes = {} ) => { const finalAttrs = { ...defaultAttributes, ...attributes }; - return renderer.create( + return render( ); }; const getLabel = ( instance ) => { - return instance.findByProps( { + return instance.UNSAFE_getByProps( { className: 'wp-block-search__label', } ); }; const getButton = ( instance ) => { - return instance.findByProps( { + return instance.UNSAFE_getByProps( { className: 'wp-block-search__button', } ); }; const getSearchInput = ( instance ) => { - return instance.findByProps( { + return instance.UNSAFE_getByProps( { className: 'wp-block-search__input', } ); }; const hasComponent = ( instance, className ) => { - const components = instance.findAllByProps( { + const components = instance.UNSAFE_queryAllByProps( { className, } ); return components.length !== 0; @@ -64,8 +64,10 @@ describe( 'Search Block', () => { } ); describe( 'renders with default configuration', () => { - const component = getTestComponent(); - const instance = component.root; + let instance; + beforeEach( () => { + instance = getTestComponent(); + } ); it( 'label is visible and text is properly set', () => { // Verify the label element of the search block exists and @@ -94,16 +96,18 @@ describe( 'Search Block', () => { } ); it( 'matches snapshot', () => { - const rendered = component.toJSON(); + const rendered = instance.toJSON(); expect( rendered ).toMatchSnapshot(); } ); } ); describe( 'renders with no-button option', () => { - const component = getTestComponent( { - buttonPosition: 'no-button', + let instance; + beforeEach( () => { + instance = getTestComponent( { + buttonPosition: 'no-button', + } ); } ); - const instance = component.root; it( 'verify button element has not been rendered', () => { expect( @@ -112,42 +116,46 @@ describe( 'Search Block', () => { } ); it( 'matches snapshot', () => { - const rendered = component.toJSON(); + const rendered = instance.toJSON(); expect( rendered ).toMatchSnapshot(); } ); } ); describe( 'renders block with icon button option', () => { - const component = getTestComponent( { - buttonUseIcon: true, + let instance; + beforeEach( () => { + instance = getTestComponent( { + buttonUseIcon: true, + } ); } ); - const instance = component.root; it( 'search button uses icon', () => { - const button = instance.findByType( Icon ); + const button = instance.UNSAFE_getByType( Icon ); expect( button ).toBeTruthy(); } ); it( 'matches snapshot', () => { - const rendered = component.toJSON(); + const rendered = instance.toJSON(); expect( rendered ).toMatchSnapshot(); } ); } ); it( 'renders block with button inside option', () => { - const component = getTestComponent( { + const instance = getTestComponent( { buttonPosition: 'button-inside', } ); - const rendered = component.toJSON(); + const rendered = instance.toJSON(); expect( rendered ).toMatchSnapshot(); } ); describe( 'renders block with label hidden', () => { - const component = getTestComponent( { - showLabel: false, + let instance; + beforeEach( () => { + instance = getTestComponent( { + showLabel: false, + } ); } ); - const instance = component.root; it( 'verify label has not been rendered', () => { expect( @@ -156,7 +164,7 @@ describe( 'Search Block', () => { } ); it( 'matches snapshot', () => { - const rendered = component.toJSON(); + const rendered = instance.toJSON(); expect( rendered ).toMatchSnapshot(); } ); } ); diff --git a/packages/block-library/src/verse/test/edit.native.js b/packages/block-library/src/verse/test/edit.native.js index 6ea54f7cbe028..99cc10bc44abe 100644 --- a/packages/block-library/src/verse/test/edit.native.js +++ b/packages/block-library/src/verse/test/edit.native.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import renderer from 'react-test-renderer'; +import { render } from 'test/helpers'; /** * Internal dependencies @@ -11,7 +11,7 @@ import { metadata, settings, name } from '../index'; /** * WordPress dependencies */ -import { RichText, BlockEdit } from '@wordpress/block-editor'; +import { BlockEdit } from '@wordpress/block-editor'; import { registerBlockType, unregisterBlockType } from '@wordpress/blocks'; const Verse = ( { clientId, ...props } ) => ( @@ -31,20 +31,17 @@ describe( 'Verse Block', () => { } ); it( 'renders without crashing', () => { - const component = renderer.create( - - ); + const component = render( ); const rendered = component.toJSON(); expect( rendered ).toBeTruthy(); } ); it( 'renders given text without crashing', () => { - const component = renderer.create( + const component = render( ); - const testInstance = component.root; - const richText = testInstance.findByType( RichText ); - expect( richText ).toBeTruthy(); - expect( richText.props.value ).toBe( 'sample text' ); + expect( + component.getByDisplayValue( '
sample text
' ) + ).toBeTruthy(); } ); } ); diff --git a/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/test/navigation-container.native.js b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/test/navigation-container.native.js index 283fa80e1999d..59ba222d5c16c 100644 --- a/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/test/navigation-container.native.js +++ b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/test/navigation-container.native.js @@ -27,7 +27,7 @@ const TestScreen = ( { fullScreen, name, navigateTo } ) => { ); }; -jest.useFakeTimers(); +jest.useFakeTimers( 'legacy' ); it( 'animates height transitioning from non-full-screen to full-screen', async () => { const screen = render( diff --git a/packages/components/src/mobile/html-text-input/test/index.native.js b/packages/components/src/mobile/html-text-input/test/index.native.js index 506c25aa23b5e..2ed37b2bb1965 100644 --- a/packages/components/src/mobile/html-text-input/test/index.native.js +++ b/packages/components/src/mobile/html-text-input/test/index.native.js @@ -1,31 +1,21 @@ /** * External dependencies */ -import { shallow } from 'enzyme'; +import { render, fireEvent } from 'test/helpers'; /** * Internal dependencies */ import { HTMLTextInput } from '..'; -// Utility to find a TextInput in a ShallowWrapper -const findTextInputInWrapper = ( wrapper, accessibilityLabel ) => { - return wrapper - .dive() - .findWhere( ( node ) => { - return node.prop( 'accessibilityLabel' ) === accessibilityLabel; - } ) - .first(); -}; - // Finds the Content TextInput in our HTMLInputView -const findContentTextInput = ( wrapper ) => { - return findTextInputInWrapper( wrapper, 'html-view-content' ); +const findContentTextInput = ( screen ) => { + return screen.getByA11yLabel( 'html-view-content' ); }; // Finds the Title TextInput in our HTMLInputView -const findTitleTextInput = ( wrapper ) => { - return findTextInputInWrapper( wrapper, 'html-view-title' ); +const findTitleTextInput = ( screen ) => { + return screen.getByA11yLabel( 'html-view-title' ); }; const getStylesFromColorScheme = () => { @@ -34,42 +24,40 @@ const getStylesFromColorScheme = () => { describe( 'HTMLTextInput', () => { it( 'HTMLTextInput renders', () => { - const wrapper = shallow( + const screen = render( ); - expect( wrapper ).toBeTruthy(); + expect( screen.container ).toBeTruthy(); } ); - it( 'HTMLTextInput updates store and state on HTML text change', () => { + it( 'HTMLTextInput updates state on HTML text change', () => { const onChange = jest.fn(); - const wrapper = shallow( + const screen = render( ); - expect( wrapper.instance().state.isDirty ).toBeFalsy(); - // Simulate user typing text - const htmlTextInput = findContentTextInput( wrapper ); - htmlTextInput.simulate( 'changeText', 'text' ); + const htmlTextInput = findContentTextInput( screen ); + fireEvent( htmlTextInput, 'changeText', 'text' ); //Check if the onChange is called and the state is updated expect( onChange ).toHaveBeenCalledTimes( 1 ); expect( onChange ).toHaveBeenCalledWith( 'text' ); - expect( wrapper.instance().state.isDirty ).toBeTruthy(); - expect( wrapper.instance().state.value ).toEqual( 'text' ); + expect( screen.getByDisplayValue( 'text' ) ).toBeDefined(); } ); it( 'HTMLTextInput persists changes in HTML text input on blur', () => { const onPersist = jest.fn(); - const wrapper = shallow( + const screen = render( { ); // Simulate user typing text - const htmlTextInput = findContentTextInput( wrapper ); - htmlTextInput.simulate( 'changeText', 'text' ); + const htmlTextInput = findContentTextInput( screen ); + fireEvent( htmlTextInput, 'changeText', 'text' ); //Simulate blur event - htmlTextInput.simulate( 'blur' ); + fireEvent( htmlTextInput, 'blur' ); //Normally prop.value is updated with the help of withSelect //But we don't have it in tests so we just simulate it - wrapper.setProps( { value: 'text' } ); + screen.update( + + ); //Check if the onPersist is called and the state is updated expect( onPersist ).toHaveBeenCalledTimes( 1 ); expect( onPersist ).toHaveBeenCalledWith( 'text' ); - expect( wrapper.instance().state.isDirty ).toBeFalsy(); + //Simulate blur event + fireEvent( htmlTextInput, 'blur' ); + + // Check that onPersist is not called for non-dirty state + expect( onPersist ).toHaveBeenCalledTimes( 1 ); //We expect state.value is getting propagated from prop.value - expect( wrapper.instance().state.value ).toEqual( 'text' ); + expect( screen.getByDisplayValue( 'text' ) ).toBeDefined(); } ); it( 'HTMLTextInput propagates title changes to store', () => { const editTitle = jest.fn(); - const wrapper = shallow( + const screen = render( { ); // Simulate user typing text - const textInput = findTitleTextInput( wrapper ); - textInput.simulate( 'changeText', 'text' ); + const textInput = findTitleTextInput( screen ); + fireEvent( textInput, 'changeText', 'text' ); //Check if the setTitleAction is called expect( editTitle ).toHaveBeenCalledTimes( 1 ); diff --git a/packages/components/src/mobile/link-settings/test/edit.native.js b/packages/components/src/mobile/link-settings/test/edit.native.js index 0b69ac13cf37f..80aff4e7401a6 100644 --- a/packages/components/src/mobile/link-settings/test/edit.native.js +++ b/packages/components/src/mobile/link-settings/test/edit.native.js @@ -69,44 +69,33 @@ describe.each( [ * GIVEN the CLIPBOARD has a URL copied; * WHEN the USER selects the SETTINGS BUTTON on the EDIT IMAGE BLOCK or EDIT BUTTON BLOCK; */ - // eslint-disable-next-line jest/no-done-callback - it( 'should display the LINK SETTINGS with an EMPTY LINK TO field.', async ( done ) => { + it( 'should display the LINK SETTINGS with an EMPTY LINK TO field.', async () => { // Arrange - const expectation = - 'The LINK SETTINGS > LINK TO field SHOULD be displayed WITHOUT a URL from the CLIPBOARD.'; const url = 'https://tonytahmouchtest.files.wordpress.com'; const subject = await initializeEditor( { initialHtml } ); Clipboard.getString.mockReturnValue( url ); // Act - try { - const block = await waitFor( () => - subject.getByA11yLabel( - type === 'core/image' ? /Image Block/ : /Button Block/ - ) - ); - fireEvent.press( block ); - fireEvent.press( block ); - fireEvent.press( - await waitFor( () => subject.getByA11yLabel( 'Open Settings' ) ) - ); - } catch ( error ) { - done.fail( error ); - } + const block = await waitFor( () => + subject.getByA11yLabel( + type === 'core/image' ? /Image Block/ : /Button Block/ + ) + ); + fireEvent.press( block ); + fireEvent.press( block ); + fireEvent.press( + await waitFor( () => subject.getByA11yLabel( 'Open Settings' ) ) + ); // Assert - try { - await waitFor( () => - subject.getByA11yLabel( - `Link to, ${ - type === 'core/image' ? 'None' : 'Search or type URL' - }` - ) - ); - done(); - } catch ( error ) { - done.fail( expectation ); - } + const linkToField = await waitFor( () => + subject.getByA11yLabel( + `Link to, ${ + type === 'core/image' ? 'None' : 'Search or type URL' + }` + ) + ); + expect( linkToField ).toBeTruthy(); } ); describe( '', () => { @@ -117,64 +106,49 @@ describe.each( [ * GIVEN the STATE has NO URL; * WHEN the USER selects the LINK TO cell; */ - // eslint-disable-next-line jest/no-done-callback - it( 'should display the LINK PICKER with NO FROM CLIPBOARD CELL.', async ( done ) => { + it( 'should display the LINK PICKER with NO FROM CLIPBOARD CELL.', async () => { // Arrange - const expectation = - 'The LINK PICKER > LINK SUGGESTION SHOULD NOT suggest the URL from the CLIPBOARD.'; const url = 'tonytahmouchtest.files.wordpress.com'; const subject = await initializeEditor( { initialHtml } ); Clipboard.getString.mockReturnValue( url ); // Act - try { - const block = await waitFor( () => + const block = await waitFor( () => + subject.getByA11yLabel( + type === 'core/image' ? /Image Block/ : /Button Block/ + ) + ); + fireEvent.press( block ); + fireEvent.press( block ); + fireEvent.press( + await waitFor( () => + subject.getByA11yLabel( 'Open Settings' ) + ) + ); + fireEvent.press( + await waitFor( () => subject.getByA11yLabel( - type === 'core/image' - ? /Image Block/ - : /Button Block/ + `Link to, ${ + type === 'core/image' + ? 'None' + : 'Search or type URL' + }` ) - ); - fireEvent.press( block ); - fireEvent.press( block ); + ) + ); + if ( type === 'core/image' ) { fireEvent.press( await waitFor( () => - subject.getByA11yLabel( 'Open Settings' ) + subject.getByA11yLabel( /Custom URL/ ) ) ); - fireEvent.press( - await waitFor( () => - subject.getByA11yLabel( - `Link to, ${ - type === 'core/image' - ? 'None' - : 'Search or type URL' - }` - ) - ) - ); - if ( type === 'core/image' ) { - fireEvent.press( - await waitFor( () => - subject.getByA11yLabel( /Custom URL/ ) - ) - ); - } - await waitFor( () => subject.getByA11yLabel( 'Apply' ) ); - } catch ( error ) { - done.fail( error ); } + await waitFor( () => subject.getByA11yLabel( 'Apply' ) ); // Assert - waitFor( - () => - subject.getByA11yLabel( - /Copy URL from the clipboard[,]/ - ), - { timeout: 50, interval: 10 } - ) - .then( () => done.fail( expectation ) ) - .catch( () => done() ); + expect( + subject.queryByA11yLabel( /Copy URL from the clipboard[,]/ ) + ).toBeNull(); } ); } ); @@ -185,87 +159,72 @@ describe.each( [ * GIVEN the STATE has the SAME URL as the CLIPBOARD; * WHEN the USER selects the LINK TO cell; */ - // eslint-disable-next-line jest/no-done-callback - it( 'should display the LINK PICKER with NO FROM CLIPBOARD CELL.', async ( done ) => { + it( 'should display the LINK PICKER with NO FROM CLIPBOARD CELL.', async () => { // Arrange - const expectation = - 'The LINK PICKER > LINK SUGGESTION SHOULD NOT suggest the URL from the CLIPBOARD.'; const url = 'https://tonytahmouchtest.files.wordpress.com'; const subject = await initializeEditor( { initialHtml } ); Clipboard.getString.mockReturnValue( url ); // Act - try { - const block = await waitFor( () => + const block = await waitFor( () => + subject.getByA11yLabel( + type === 'core/image' ? /Image Block/ : /Button Block/ + ) + ); + fireEvent.press( block ); + fireEvent.press( block ); + fireEvent.press( + await waitFor( () => + subject.getByA11yLabel( 'Open Settings' ) + ) + ); + fireEvent.press( + await waitFor( () => subject.getByA11yLabel( - type === 'core/image' - ? /Image Block/ - : /Button Block/ + `Link to, ${ + type === 'core/image' + ? 'None' + : 'Search or type URL' + }` ) - ); - fireEvent.press( block ); - fireEvent.press( block ); + ) + ); + if ( type === 'core/image' ) { fireEvent.press( await waitFor( () => - subject.getByA11yLabel( 'Open Settings' ) + subject.getByA11yLabel( 'Custom URL. Empty' ) ) ); - fireEvent.press( - await waitFor( () => - subject.getByA11yLabel( - `Link to, ${ - type === 'core/image' - ? 'None' - : 'Search or type URL' - }` - ) + } + fireEvent.press( + await waitFor( () => + subject.getByA11yLabel( + `Copy URL from the clipboard, ${ url }` ) - ); - if ( type === 'core/image' ) { - fireEvent.press( - await waitFor( () => - subject.getByA11yLabel( 'Custom URL. Empty' ) - ) - ); - } - fireEvent.press( - await waitFor( () => - subject.getByA11yLabel( - `Copy URL from the clipboard, ${ url }` - ) + ) + ); + fireEvent.press( + await waitFor( () => + subject.getByA11yLabel( + `Link to, ${ + type === 'core/image' ? 'Custom URL' : url + }` ) - ); + ) + ); + if ( type === 'core/image' ) { fireEvent.press( await waitFor( () => - subject.getByA11yLabel( - `Link to, ${ - type === 'core/image' ? 'Custom URL' : url - }` - ) + subject.getByA11yLabel( `Custom URL, ${ url }` ) ) ); - if ( type === 'core/image' ) { - fireEvent.press( - await waitFor( () => - subject.getByA11yLabel( `Custom URL, ${ url }` ) - ) - ); - } - await waitFor( () => subject.getByA11yLabel( 'Apply' ) ); - } catch ( error ) { - done.fail( error ); } + await waitFor( () => subject.getByA11yLabel( 'Apply' ) ); // Assert - waitFor( - () => - subject.getByA11yLabel( - /Copy URL from the clipboard[,]/ - ), - { timeout: 50, interval: 10 } - ) - .then( () => done.fail( expectation ) ) - .catch( () => done() ); + expect( + subject.queryByA11yLabel( /Copy URL from the clipboard[,]/ ) + ).toBeNull(); } ); } ); @@ -279,72 +238,60 @@ describe.each( [ it( 'should display the LINK PICKER with the FROM CLIPBOARD CELL populated' + ' with the URL from the CLIPBOARD.', - // eslint-disable-next-line jest/no-done-callback - async ( done ) => { + async () => { // Arrange const url = 'https://tonytahmouchtest.files.wordpress.com'; - const expectation = - 'The LINK PICKER > LINK SUGGESTION SHOULD suggest the URL from the CLIPBOARD, e.g.,' + - ` - ${ url } - ${ __( 'From clipboard' ) } - `; const subject = await initializeEditor( { initialHtml } ); Clipboard.getString.mockReturnValue( url ); // Act - try { - const block = await waitFor( () => + const block = await waitFor( () => + subject.getByA11yLabel( + type === 'core/image' + ? /Image Block/ + : /Button Block/ + ) + ); + fireEvent.press( block ); + fireEvent.press( block ); + fireEvent.press( + await waitFor( () => + subject.getByA11yLabel( 'Open Settings' ) + ) + ); + fireEvent.press( + await waitFor( () => subject.getByA11yLabel( - type === 'core/image' - ? /Image Block/ - : /Button Block/ - ) - ); - fireEvent.press( block ); - fireEvent.press( block ); - fireEvent.press( - await waitFor( () => - subject.getByA11yLabel( 'Open Settings' ) + `Link to, ${ + type === 'core/image' + ? 'None' + : 'Search or type URL' + }` ) - ); + ) + ); + if ( type === 'core/image' ) { fireEvent.press( await waitFor( () => - subject.getByA11yLabel( - `Link to, ${ - type === 'core/image' - ? 'None' - : 'Search or type URL' - }` - ) - ) - ); - if ( type === 'core/image' ) { - fireEvent.press( - await waitFor( () => - subject.getByA11yLabel( /Custom URL/ ) - ) - ); - } - await waitFor( () => - subject.getByA11yLabel( - `Copy URL from the clipboard, ${ url }` + subject.getByA11yLabel( /Custom URL/ ) ) ); - } catch ( error ) { - done.fail( error ); } + await waitFor( () => + subject.getByA11yLabel( + `Copy URL from the clipboard, ${ url }` + ) + ); // Assert - try { - await waitFor( () => subject.getByText( url ) ); - await waitFor( () => - subject.getByText( __( 'From clipboard' ) ) - ); - done(); - } catch ( error ) { - done.fail( expectation ); - } + const clipboardUrl = await waitFor( () => + subject.getByText( url ) + ); + expect( clipboardUrl ).toBeTruthy(); + const clipboardNote = await waitFor( () => + subject.getByText( __( 'From clipboard' ) ) + ); + expect( clipboardNote ).toBeTruthy(); } ); } ); @@ -358,73 +305,62 @@ describe.each( [ it( 'should display the LINK SETTINGS with the URL from the CLIPBOARD' + ' populated in the LINK TO field.', - // eslint-disable-next-line jest/no-done-callback - async ( done ) => { + async () => { // Arrange - const expectation = - 'The LINK SETTINGS > LINK TO field SHOULD be displayed WITH a URL from the CLIPBOARD.'; const url = 'https://tonytahmouchtest.files.wordpress.com'; const subject = await initializeEditor( { initialHtml } ); Clipboard.getString.mockReturnValue( url ); // Act - try { - const block = await waitFor( () => + const block = await waitFor( () => + subject.getByA11yLabel( + type === 'core/image' + ? /Image Block/ + : /Button Block/ + ) + ); + fireEvent.press( block ); + fireEvent.press( block ); + fireEvent.press( + await waitFor( () => + subject.getByA11yLabel( 'Open Settings' ) + ) + ); + fireEvent.press( + await waitFor( () => subject.getByA11yLabel( - type === 'core/image' - ? /Image Block/ - : /Button Block/ - ) - ); - fireEvent.press( block ); - fireEvent.press( block ); - fireEvent.press( - await waitFor( () => - subject.getByA11yLabel( 'Open Settings' ) - ) - ); - fireEvent.press( - await waitFor( () => - subject.getByA11yLabel( - `Link to, ${ - type === 'core/image' - ? 'None' - : 'Search or type URL' - }` - ) + `Link to, ${ + type === 'core/image' + ? 'None' + : 'Search or type URL' + }` ) - ); - if ( type === 'core/image' ) { - fireEvent.press( - await waitFor( () => - subject.getByA11yLabel( /Custom URL/ ) - ) - ); - } + ) + ); + if ( type === 'core/image' ) { fireEvent.press( await waitFor( () => - subject.getByA11yLabel( - `Copy URL from the clipboard, ${ url }` - ) + subject.getByA11yLabel( /Custom URL/ ) ) ); - } catch ( error ) { - done.fail( error ); } - - // Assert - try { + fireEvent.press( await waitFor( () => subject.getByA11yLabel( - `Link to, ${ - type === 'core/image' ? 'Custom URL' : url - }` + `Copy URL from the clipboard, ${ url }` ) - ); - done(); - } catch ( error ) { - done.fail( expectation ); - } + ) + ); + + // Assert + const linkToField = await waitFor( () => + subject.getByA11yLabel( + `Link to, ${ + type === 'core/image' ? 'Custom URL' : url + }` + ) + ); + expect( linkToField ).toBeTruthy(); } ); } ); diff --git a/packages/components/src/mobile/link-settings/test/link-settings-navigation.native.js b/packages/components/src/mobile/link-settings/test/link-settings-navigation.native.js index 7c98462207cf8..7c5775d152404 100644 --- a/packages/components/src/mobile/link-settings/test/link-settings-navigation.native.js +++ b/packages/components/src/mobile/link-settings/test/link-settings-navigation.native.js @@ -9,10 +9,8 @@ import { render, fireEvent, waitFor } from 'test/helpers'; */ import LinkSettingsNavigation from '../link-settings-navigation'; -beforeAll( () => { - jest.useFakeTimers(); - jest.spyOn( Keyboard, 'dismiss' ); -} ); +jest.useFakeTimers( 'legacy' ); +jest.spyOn( Keyboard, 'dismiss' ); const subject = ( ; + return ( + + ); } diff --git a/packages/components/src/tooltip/test/index.native.js b/packages/components/src/tooltip/test/index.native.js index 710a48b977982..64bf0aa49fec1 100644 --- a/packages/components/src/tooltip/test/index.native.js +++ b/packages/components/src/tooltip/test/index.native.js @@ -54,7 +54,9 @@ it( 'displays the message', () => { expect( screen.getByText( 'A helpful message' ) ).toBeTruthy(); } ); -it( 'dismisses when the screen is tapped', () => { +// Skipped until `pointerEvents: 'box-none'` no longer erroneously prevents +// triggering `onTouch*` on the element: https://git.io/JSHZt +it.skip( 'dismisses when the screen is tapped', () => { const screen = render( diff --git a/packages/edit-post/src/test/editor.native.js b/packages/edit-post/src/test/editor.native.js index e153cee4b6a4f..b95d078cfc9a7 100644 --- a/packages/edit-post/src/test/editor.native.js +++ b/packages/edit-post/src/test/editor.native.js @@ -1,8 +1,7 @@ /** * External dependencies */ -import { mount } from 'enzyme'; -import { act } from 'react-dom/test-utils'; +import { act, render } from 'test/helpers'; /** * WordPress dependencies @@ -26,11 +25,12 @@ const unsupportedBlock = ` `; +jest.useFakeTimers( 'legacy' ); + describe( 'Editor', () => { beforeAll( registerCoreBlocks ); it( 'detects unsupported block and sends hasUnsupportedBlocks true to native', () => { - jest.useFakeTimers(); RNReactNativeGutenbergBridge.editorDidMount = jest.fn(); const appContainer = renderEditorWith( unsupportedBlock ); @@ -51,7 +51,7 @@ describe( 'Editor', () => { // Utilities const renderEditorWith = ( content ) => { - return mount( + return render( { it( 'is chooses the right thing', () => { - const element = Platform.select( { - web: shallow(
), - native: shallow( ), + const selection = Platform.select( { + web: 'web', + native: 'native', } ); - expect( element.type() ).toBe( 'button' ); + expect( selection ).toBe( 'native' ); } ); } ); diff --git a/packages/format-library/src/link/test/index.native.js b/packages/format-library/src/link/test/index.native.js index 58b270e14d75d..0b3bb1d2a15d1 100644 --- a/packages/format-library/src/link/test/index.native.js +++ b/packages/format-library/src/link/test/index.native.js @@ -24,10 +24,8 @@ const LinkEditSlot = ( props ) => ( ); -beforeAll( () => { - jest.useFakeTimers(); - jest.spyOn( Keyboard, 'dismiss' ); -} ); +jest.useFakeTimers( 'legacy' ); +jest.spyOn( Keyboard, 'dismiss' ); describe( 'Android', () => { it( 'improves back animation performance by dismissing keyboard beforehand', async () => { diff --git a/packages/format-library/src/link/test/modal.native.js b/packages/format-library/src/link/test/modal.native.js index d75a7604d078a..94d4499ef8906 100644 --- a/packages/format-library/src/link/test/modal.native.js +++ b/packages/format-library/src/link/test/modal.native.js @@ -5,11 +5,11 @@ import ModalLinkUI from '../modal'; /** * External dependencies */ -import { shallow } from 'enzyme'; +import { render } from 'test/helpers'; describe( 'LinksUI', () => { it( 'LinksUI renders', () => { - const wrapper = shallow( ); - expect( wrapper ).toBeTruthy(); + const screen = render( ); + expect( screen.container ).toBeTruthy(); } ); } ); diff --git a/test/native/enzyme.config.js b/test/native/enzyme.config.js deleted file mode 100644 index a2c5643f8794d..0000000000000 --- a/test/native/enzyme.config.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * External dependencies - */ -import { configure } from 'enzyme'; -import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; -configure( { adapter: new Adapter() } ); diff --git a/test/native/jest.config.js b/test/native/jest.config.js index ed4478d9e61bf..64e841f8d5dc3 100644 --- a/test/native/jest.config.js +++ b/test/native/jest.config.js @@ -25,12 +25,7 @@ module.exports = { // Automatically clear mock calls and instances between every test clearMocks: true, preset: 'react-native', - setupFiles: [ - '/' + configPath + '/setup.js', - '/' + configPath + '/enzyme.config.js', - ], - testEnvironment: 'jsdom', - testRunner: 'jest-jasmine2', + setupFiles: [ '/' + configPath + '/setup.js' ], testMatch: [ '**/test/*.native.[jt]s?(x)', '/packages/react-native-*/**/?(*.)+(spec|test).[jt]s?(x)', @@ -72,9 +67,6 @@ module.exports = { // https://github.com/facebook/react-native/blob/HEAD/jest-preset.json#L20 'node_modules/(?!(simple-html-tokenizer|(jest-)?react-native|@react-native|react-clone-referenced-element|@react-navigation))', ], - snapshotSerializers: [ - 'enzyme-to-json/serializer', - '@emotion/jest/serializer', - ], + snapshotSerializers: [ '@emotion/jest/serializer' ], reporters: [ 'default', 'jest-junit' ], }; diff --git a/test/native/setup.js b/test/native/setup.js index 6ec6ff91d98c8..7cfe77287523e 100644 --- a/test/native/setup.js +++ b/test/native/setup.js @@ -4,6 +4,14 @@ import 'react-native-gesture-handler/jestSetup'; import { Image, NativeModules as RNNativeModules } from 'react-native'; +// React Native sets up a global navigator, but that is not executed in the +// testing environment: https://git.io/JSSBg +global.navigator = global.navigator ?? {}; + +// Set up the app runtime globals for the test environment, which includes +// modifying the above `global.navigator` +require( '../../packages/react-native-editor/src/globals' ); + RNNativeModules.UIManager = RNNativeModules.UIManager || {}; RNNativeModules.UIManager.RCTView = RNNativeModules.UIManager.RCTView || {}; RNNativeModules.RNGestureHandlerModule = RNNativeModules.RNGestureHandlerModule || { @@ -26,8 +34,6 @@ const mockComponent = ( element ) => ( ...args ) => { return React.createElement( element, props, props.children ); }; -jest.useFakeTimers(); - jest.mock( '@wordpress/element', () => { return { __esModule: true, @@ -52,6 +58,8 @@ jest.mock( '@wordpress/react-native-bridge', () => { callback( {} ); } ), requestFocalPointPickerTooltipShown: jest.fn( () => true ), + sendMediaUpload: jest.fn(), + sendMediaSave: jest.fn(), setBlockTypeImpressions: jest.fn(), subscribeParentToggleHTMLMode: jest.fn(), subscribeSetTitle: jest.fn(), @@ -126,20 +134,6 @@ jest.mock( { virtual: true } ); -if ( ! global.window.matchMedia ) { - global.window.matchMedia = () => ( { - matches: false, - addListener: () => {}, - removeListener: () => {}, - } ); -} - -if ( ! global.window.setImmediate ) { - global.window.setImmediate = function ( callback ) { - return setTimeout( callback, 0 ); - }; -} - jest.mock( 'react-native-linear-gradient', () => () => 'LinearGradient', { virtual: true, } );