diff --git a/.github/workflows/build-test-measure.yml b/.github/workflows/build-test-measure.yml index bd025d44386..c4d49a96ac8 100644 --- a/.github/workflows/build-test-measure.yml +++ b/.github/workflows/build-test-measure.yml @@ -331,6 +331,14 @@ jobs: env: COMPOSE_INTERACTIVE_NO_CLI: true + + # TODO: Remove it once node version in .nvmrc is updated to >=16. + - name: Setup Node + uses: actions/setup-node@v3.6.0 + with: + node-version: 16 + cache: npm + - name: Run E2E tests run: npm run test:e2e:ci @@ -372,6 +380,7 @@ jobs: include: - php: '8.0' wp: 'trunk' + multisite: true experimental: true - php: '8.1' @@ -391,6 +400,7 @@ jobs: external-http: true - php: '7.4' + multisite: true wp: 'latest' - php: '7.4' @@ -553,6 +563,14 @@ jobs: env: WP_TESTS_DIR: /tmp/wordpress-tests-lib + - name: Run multisite tests + if: ${{ matrix.multisite == true && needs.pre-run.outputs.changed-php-count > 0 }} + run: vendor/bin/phpunit --verbose + working-directory: ${{ env.WP_CORE_DIR }}/src/wp-content/plugins/amp + env: + WP_TESTS_DIR: /tmp/wordpress-tests-lib + WP_MULTISITE: 1 + - name: Run tests with coverage if: ${{ matrix.coverage == true && needs.pre-run.outputs.changed-php-count > 0 }} run: vendor/bin/phpunit --verbose --coverage-clover ${{ env.WP_CORE_DIR }}/src/wp-content/plugins/amp/build/logs/clover.xml @@ -575,76 +593,6 @@ jobs: flags: php,unit fail_ci_if_error: true -#----------------------------------------------------------------------------------------------------------------------- - - unit-test-multisite-php: - name: 'Unit Tests Multisite: PHP 7.4, WP Latest' - needs: pre-run - runs-on: ubuntu-latest - if: needs.pre-run.outputs.changed-php-count > 0 - continue-on-error: true - strategy: - matrix: - testsuite: ['default', 'external-http'] - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup Node - uses: actions/setup-node@v3.6.0 - with: - node-version-file: '.nvmrc' - cache: npm - - - name: Get Composer Cache Directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Configure Composer cache - uses: actions/cache@v3.3.1 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - - name: Install Node dependencies - run: npm ci - env: - CI: true - - - name: Install Composer dependencies - run: | - # phpdocumentor/reflection has to be removed as it makes use of an outdated dependency. - composer remove --dev phpdocumentor/reflection - composer install --prefer-dist --ignore-platform-reqs --no-progress --no-interaction - - # See https://github.com/wp-cli/wp-cli/issues/5484 - - name: Remove conflicting Requests library - run: composer remove --dev --ignore-platform-reqs --no-interaction --no-scripts roave/security-advisories wp-cli/export-command wp-cli/extension-command wp-cli/wp-cli wp-cli/wp-cli-tests - - - name: Update PHPUnit - if: needs.pre-run.outputs.changed-php-count > 0 - run: | - # We are using PHP 7.4 and WP Latest. - echo "Installing PHPUnit 9.3" - composer require --dev --ignore-platform-reqs phpunit/phpunit:"9.3.*" --with-dependencies - - - name: Build plugin - run: npm run build:js - - - name: Move amp-wp to amp - run: cp -r "$PWD" "/tmp/amp" - - - name: Start wp-env - working-directory: /tmp/amp - run: npm run wp-env start - - - name: Run multisite unit tests - working-directory: /tmp/amp - run: npm run test:php:multisite ${{ matrix.testsuite == 'external-http' && '-- --testsuite external-http' || '' }} - #----------------------------------------------------------------------------------------------------------------------- feature-test-php: diff --git a/assets/src/admin/site-scan-notice/index.js b/assets/src/admin/site-scan-notice/index.js index 18f2b104776..428d42f882c 100644 --- a/assets/src/admin/site-scan-notice/index.js +++ b/assets/src/admin/site-scan-notice/index.js @@ -14,7 +14,7 @@ import { * WordPress dependencies */ import domReady from '@wordpress/dom-ready'; -import { render } from '@wordpress/element'; +import { createRoot } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; /** @@ -94,16 +94,15 @@ domReady(() => { event.filename && /amp-site-scan-notice(\.min)?\.js/.test(event.filename) ) { - render(, root); + createRoot(root).render(); } }; global.addEventListener('error', errorHandler); - render( + createRoot(root).render( - , - root + ); }); diff --git a/assets/src/block-editor/store/index.js b/assets/src/block-editor/store/index.js index 93d83f16938..d7f4f1ceb70 100644 --- a/assets/src/block-editor/store/index.js +++ b/assets/src/block-editor/store/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { registerStore } from '@wordpress/data'; +import { createReduxStore, register } from '@wordpress/data'; /** * Internal dependencies @@ -13,10 +13,12 @@ import * as selectors from './selectors'; */ const MODULE_KEY = 'amp/block-editor'; -export default registerStore(MODULE_KEY, { - reducer: (state) => state, - selectors, - initialState: { - ...window.ampBlockEditor, - }, -}); +export default register( + createReduxStore(MODULE_KEY, { + reducer: (state) => state, + selectors, + initialState: { + ...window.ampBlockEditor, + }, + }) +); diff --git a/assets/src/block-validation/components/amp-document-status/index.js b/assets/src/block-validation/components/amp-document-status/index.js index 182644e1f1f..dd3f39c5a83 100644 --- a/assets/src/block-validation/components/amp-document-status/index.js +++ b/assets/src/block-validation/components/amp-document-status/index.js @@ -10,7 +10,7 @@ import { useDispatch, useSelect } from '@wordpress/data'; */ import AMPValidationErrorsKeptIcon from '../../../../images/amp-validation-errors-kept.svg'; import BellIcon from '../../../../images/bell-icon.svg'; -import { BLOCK_VALIDATION_STORE_KEY } from '../../store'; +import { store as blockValidationStore } from '../../store'; import { StatusIcon } from '../icon'; import { SidebarNotification } from '../sidebar-notification'; import { useAMPDocumentToggle } from '../../hooks/use-amp-document-toggle'; @@ -37,19 +37,18 @@ export default function AMPDocumentStatusNotification() { unreviewedValidationErrorCount, } = useSelect( (select) => ({ - isPostDirty: select(BLOCK_VALIDATION_STORE_KEY).getIsPostDirty(), - maybeIsPostDirty: select( - BLOCK_VALIDATION_STORE_KEY - ).getMaybeIsPostDirty(), - keptMarkupValidationErrorCount: select( - BLOCK_VALIDATION_STORE_KEY - ).getKeptMarkupValidationErrors().length, - reviewedValidationErrorCount: select( - BLOCK_VALIDATION_STORE_KEY - ).getReviewedValidationErrors().length, - unreviewedValidationErrorCount: select( - BLOCK_VALIDATION_STORE_KEY - ).getUnreviewedValidationErrors().length, + isPostDirty: select(blockValidationStore).getIsPostDirty(), + maybeIsPostDirty: + select(blockValidationStore).getMaybeIsPostDirty(), + keptMarkupValidationErrorCount: + select(blockValidationStore).getKeptMarkupValidationErrors() + .length, + reviewedValidationErrorCount: + select(blockValidationStore).getReviewedValidationErrors() + .length, + unreviewedValidationErrorCount: + select(blockValidationStore).getUnreviewedValidationErrors() + .length, }), [] ); diff --git a/assets/src/block-validation/components/amp-document-status/test/amp-document-status-notification.js b/assets/src/block-validation/components/amp-document-status/test/amp-document-status-notification.js index 40269fe62f9..bdaa6d94383 100644 --- a/assets/src/block-validation/components/amp-document-status/test/amp-document-status-notification.js +++ b/assets/src/block-validation/components/amp-document-status/test/amp-document-status-notification.js @@ -1,12 +1,11 @@ /** * External dependencies */ -import { act } from 'react-dom/test-utils'; +import { render, fireEvent } from '@testing-library/react'; /** * WordPress dependencies */ -import { render, unmountComponentAtNode } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; /** @@ -28,8 +27,6 @@ jest.mock('../../../hooks/use-errors-fetching-state-changes', () => ({ })); describe('AMPDocumentStatusNotification', () => { - let container; - const openGeneralSidebar = jest.fn(); const closePublishSidebar = jest.fn(); @@ -65,18 +62,6 @@ describe('AMPDocumentStatusNotification', () => { })); }); - beforeEach(() => { - // jest.clearAllMocks(); - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - unmountComponentAtNode(container); - container.remove(); - container = null; - }); - it('renders only a toggle if AMP is disabled', () => { setupHooks( {}, @@ -86,9 +71,7 @@ describe('AMPDocumentStatusNotification', () => { } ); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.children).toHaveLength(1); expect(container.innerHTML).toContain('Enable AMP'); @@ -103,9 +86,7 @@ describe('AMPDocumentStatusNotification', () => { } ); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toContain('Enable AMP'); expect( @@ -119,9 +100,7 @@ describe('AMPDocumentStatusNotification', () => { isPostDirty: true, }); - act(() => { - render(, container); - }); + let { container } = render(); expect(container.innerHTML).toContain('Enable AMP'); expect(container.innerHTML).toContain('Content has changed.'); @@ -133,14 +112,13 @@ describe('AMPDocumentStatusNotification', () => { maybeIsPostDirty: true, }); - act(() => { - render(, container); - }); + ({ container } = render()); expect(container.innerHTML).toContain('Content may have changed.'); // Simulate button click. - container.querySelector('button').click(); + fireEvent.click(container.querySelector('button')); + expect(openGeneralSidebar).toHaveBeenCalledTimes(1); expect(closePublishSidebar).toHaveBeenCalledTimes(1); }); @@ -150,9 +128,7 @@ describe('AMPDocumentStatusNotification', () => { keptMarkupValidationErrorCount: 3, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toContain('Enable AMP'); expect(container.innerHTML).toContain( @@ -169,9 +145,7 @@ describe('AMPDocumentStatusNotification', () => { unreviewedValidationErrorCount: 1, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toContain('Enable AMP'); expect(container.innerHTML).toContain( @@ -186,9 +160,7 @@ describe('AMPDocumentStatusNotification', () => { it('renders a correct message if there are no errors', () => { setupHooks(); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toContain('Enable AMP'); expect(container.innerHTML).toContain( diff --git a/assets/src/block-validation/components/amp-toggle/test/amp-toggle.js b/assets/src/block-validation/components/amp-toggle/test/amp-toggle.js index 1bb7f837a7b..248e3c1a961 100644 --- a/assets/src/block-validation/components/amp-toggle/test/amp-toggle.js +++ b/assets/src/block-validation/components/amp-toggle/test/amp-toggle.js @@ -1,12 +1,7 @@ /** * External dependencies */ -import { act } from 'react-dom/test-utils'; - -/** - * WordPress dependencies - */ -import { render, unmountComponentAtNode } from '@wordpress/element'; +import { render, fireEvent } from '@testing-library/react'; /** * Internal dependencies @@ -19,8 +14,6 @@ jest.mock('../../../hooks/use-amp-document-toggle', () => ({ })); describe('AMPToggle', () => { - let container; - const toggleAMP = jest.fn(); function setupHooks(overrides) { @@ -33,15 +26,6 @@ describe('AMPToggle', () => { beforeEach(() => { jest.clearAllMocks(); - - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - unmountComponentAtNode(container); - container.remove(); - container = null; }); it('renders a toggle that reacts to changes', () => { @@ -49,9 +33,7 @@ describe('AMPToggle', () => { isAMPEnabled: true, }); - act(() => { - render(, container); - }); + const { container } = render(); expect( container.querySelector('input[type="checkbox"]') @@ -60,7 +42,8 @@ describe('AMPToggle', () => { true ); - container.querySelector('input[type="checkbox"]').click(); + fireEvent.click(container.querySelector('input[type="checkbox"]')); + expect(toggleAMP).toHaveBeenCalledTimes(1); }); }); diff --git a/assets/src/block-validation/components/amp-validation-status/revalidate-notification.js b/assets/src/block-validation/components/amp-validation-status/revalidate-notification.js index 9ad05221d41..32f11fdd3d2 100644 --- a/assets/src/block-validation/components/amp-validation-status/revalidate-notification.js +++ b/assets/src/block-validation/components/amp-validation-status/revalidate-notification.js @@ -8,7 +8,7 @@ import { useDispatch, useSelect } from '@wordpress/data'; /** * Internal dependencies */ -import { BLOCK_VALIDATION_STORE_KEY } from '../../store'; +import { store as blockValidationStore } from '../../store'; import BellIcon from '../../../../images/bell-icon.svg'; import { SidebarNotification } from '../sidebar-notification'; import { useErrorsFetchingStateChanges } from '../../hooks/use-errors-fetching-state-changes'; @@ -27,10 +27,9 @@ export default function AMPRevalidateNotification() { ['draft', 'auto-draft'].indexOf( select('core/editor').getEditedPostAttribute('status') ) !== -1, - isPostDirty: select(BLOCK_VALIDATION_STORE_KEY).getIsPostDirty(), - maybeIsPostDirty: select( - BLOCK_VALIDATION_STORE_KEY - ).getMaybeIsPostDirty(), + isPostDirty: select(blockValidationStore).getIsPostDirty(), + maybeIsPostDirty: + select(blockValidationStore).getMaybeIsPostDirty(), }), [] ); diff --git a/assets/src/block-validation/components/amp-validation-status/status-notification.js b/assets/src/block-validation/components/amp-validation-status/status-notification.js index 655b58ca725..93cf7aa4c47 100644 --- a/assets/src/block-validation/components/amp-validation-status/status-notification.js +++ b/assets/src/block-validation/components/amp-validation-status/status-notification.js @@ -9,7 +9,7 @@ import { useDispatch, useSelect } from '@wordpress/data'; * Internal dependencies */ import AMPValidationErrorsKeptIcon from '../../../../images/amp-validation-errors-kept.svg'; -import { BLOCK_VALIDATION_STORE_KEY } from '../../store'; +import { store as blockValidationStore } from '../../store'; import { StatusIcon } from '../icon'; import { SidebarNotification } from '../sidebar-notification'; import { useErrorsFetchingStateChanges } from '../../hooks/use-errors-fetching-state-changes'; @@ -32,25 +32,25 @@ export default function AMPValidationStatusNotification() { validationErrorCount, } = useSelect( (select) => ({ - fetchingErrorsRequestErrorMessage: select( - BLOCK_VALIDATION_STORE_KEY - ).getFetchingErrorsRequestErrorMessage(), + fetchingErrorsRequestErrorMessage: + select( + blockValidationStore + ).getFetchingErrorsRequestErrorMessage(), isDraft: ['draft', 'auto-draft'].indexOf( select('core/editor').getEditedPostAttribute('status') ) !== -1, isEditedPostNew: select('core/editor').isEditedPostNew(), - keptMarkupValidationErrorCount: select( - BLOCK_VALIDATION_STORE_KEY - ).getKeptMarkupValidationErrors().length, - reviewLink: select(BLOCK_VALIDATION_STORE_KEY).getReviewLink(), - supportLink: select(BLOCK_VALIDATION_STORE_KEY).getSupportLink(), - unreviewedValidationErrorCount: select( - BLOCK_VALIDATION_STORE_KEY - ).getUnreviewedValidationErrors().length, - validationErrorCount: select( - BLOCK_VALIDATION_STORE_KEY - ).getValidationErrors().length, + keptMarkupValidationErrorCount: + select(blockValidationStore).getKeptMarkupValidationErrors() + .length, + reviewLink: select(blockValidationStore).getReviewLink(), + supportLink: select(blockValidationStore).getSupportLink(), + unreviewedValidationErrorCount: + select(blockValidationStore).getUnreviewedValidationErrors() + .length, + validationErrorCount: + select(blockValidationStore).getValidationErrors().length, }), [] ); diff --git a/assets/src/block-validation/components/amp-validation-status/test/__snapshots__/revalidate-notification.js.snap b/assets/src/block-validation/components/amp-validation-status/test/__snapshots__/revalidate-notification.js.snap index 205939579bb..6a03d66f168 100644 --- a/assets/src/block-validation/components/amp-validation-status/test/__snapshots__/revalidate-notification.js.snap +++ b/assets/src/block-validation/components/amp-validation-status/test/__snapshots__/revalidate-notification.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`AMPRevalidateNotification always renders revalidate status message if there are active meta boxes 1`] = `"

Content may have changed.

"`; +exports[`AMPRevalidateNotification always renders revalidate status message if there are active meta boxes 1`] = `""`; -exports[`AMPRevalidateNotification renders revalidate message if draft post is dirty 1`] = `"

Content has changed.

"`; +exports[`AMPRevalidateNotification renders revalidate message if draft post is dirty 1`] = `""`; -exports[`AMPRevalidateNotification renders revalidate message if post is dirty 1`] = `"

Content has changed.

"`; +exports[`AMPRevalidateNotification renders revalidate message if post is dirty 1`] = `""`; diff --git a/assets/src/block-validation/components/amp-validation-status/test/__snapshots__/status-notification.js.snap b/assets/src/block-validation/components/amp-validation-status/test/__snapshots__/status-notification.js.snap index caa3d6d383f..c8a992e85bf 100644 --- a/assets/src/block-validation/components/amp-validation-status/test/__snapshots__/status-notification.js.snap +++ b/assets/src/block-validation/components/amp-validation-status/test/__snapshots__/status-notification.js.snap @@ -1,13 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`AMPValidationStatusNotification renders error message when API request error is present 1`] = `"

request error message

"`; +exports[`AMPValidationStatusNotification renders error message when API request error is present 1`] = `""`; -exports[`AMPValidationStatusNotification renders error message when there are kept issues 1`] = `"

AMP is disabled due to invalid markup being kept for 2 issues.

"`; +exports[`AMPValidationStatusNotification renders error message when there are kept issues 1`] = `""`; -exports[`AMPValidationStatusNotification renders message when the post is new 1`] = `"

Validation will be checked upon saving.

"`; +exports[`AMPValidationStatusNotification renders message when the post is new 1`] = `""`; -exports[`AMPValidationStatusNotification renders message when there are no AMP validation errors 1`] = `"

No AMP validation issues detected.

"`; +exports[`AMPValidationStatusNotification renders message when there are no AMP validation errors 1`] = `""`; -exports[`AMPValidationStatusNotification renders message when there are reviewed issues 1`] = `""`; +exports[`AMPValidationStatusNotification renders message when there are reviewed issues 1`] = `""`; -exports[`AMPValidationStatusNotification renders message when there are unreviewed issues 1`] = `""`; +exports[`AMPValidationStatusNotification renders message when there are unreviewed issues 1`] = `""`; diff --git a/assets/src/block-validation/components/amp-validation-status/test/revalidate-notification.js b/assets/src/block-validation/components/amp-validation-status/test/revalidate-notification.js index f7a08f8ed7e..e5e993f4d15 100644 --- a/assets/src/block-validation/components/amp-validation-status/test/revalidate-notification.js +++ b/assets/src/block-validation/components/amp-validation-status/test/revalidate-notification.js @@ -1,12 +1,11 @@ /** * External dependencies */ -import { act } from 'react-dom/test-utils'; +import { render, fireEvent } from '@testing-library/react'; /** * WordPress dependencies */ -import { render, unmountComponentAtNode } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; /** @@ -24,8 +23,6 @@ jest.mock('../../../hooks/use-errors-fetching-state-changes', () => ({ })); describe('AMPRevalidateNotification', () => { - let container; - const autosave = jest.fn(); const savePost = jest.fn(); @@ -45,27 +42,16 @@ describe('AMPRevalidateNotification', () => { }); beforeEach(() => { - container = document.createElement('div'); - document.body.appendChild(container); - useErrorsFetchingStateChanges.mockImplementation(() => ({ isFetchingErrors: false, fetchingErrorsMessage: '', })); }); - afterEach(() => { - unmountComponentAtNode(container); - container.remove(); - container = null; - }); - it('does not render revalidate message if post is not dirty', () => { setupUseSelect(); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.children).toHaveLength(0); }); @@ -76,9 +62,7 @@ describe('AMPRevalidateNotification', () => { fetchingErrorsMessage: 'Loading', })); - act(() => { - render(, container); - }); + const { container } = render(); expect( container.querySelector('.amp-spinner-container') @@ -91,9 +75,7 @@ describe('AMPRevalidateNotification', () => { isPostDirty: true, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.children).toHaveLength(1); @@ -103,7 +85,8 @@ describe('AMPRevalidateNotification', () => { 'Re-validate' ); - container.querySelector('button').click(); + fireEvent.click(container.querySelector('button')); + expect(autosave).toHaveBeenCalledWith({ isPreview: true }); }); @@ -113,9 +96,7 @@ describe('AMPRevalidateNotification', () => { isPostDirty: true, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.innerHTML).toContain('has changed'); @@ -123,7 +104,8 @@ describe('AMPRevalidateNotification', () => { 'Save draft' ); - container.querySelector('button').click(); + fireEvent.click(container.querySelector('button')); + expect(savePost).toHaveBeenCalledWith({ isPreview: true }); }); @@ -134,9 +116,7 @@ describe('AMPRevalidateNotification', () => { maybeIsPostDirty: true, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.children).toHaveLength(1); diff --git a/assets/src/block-validation/components/amp-validation-status/test/status-notification.js b/assets/src/block-validation/components/amp-validation-status/test/status-notification.js index 4b115a43327..22c207543a8 100644 --- a/assets/src/block-validation/components/amp-validation-status/test/status-notification.js +++ b/assets/src/block-validation/components/amp-validation-status/test/status-notification.js @@ -1,12 +1,11 @@ /** * External dependencies */ -import { act } from 'react-dom/test-utils'; +import { render, fireEvent } from '@testing-library/react'; /** * WordPress dependencies */ -import { render, unmountComponentAtNode } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; /** @@ -20,8 +19,6 @@ jest.mock('@wordpress/data/build/components/use-dispatch/use-dispatch', () => ); describe('AMPValidationStatusNotification', () => { - let container; - const autosave = jest.fn(); const savePost = jest.fn(); @@ -44,25 +41,12 @@ describe('AMPValidationStatusNotification', () => { useDispatch.mockImplementation(() => ({ autosave, savePost })); }); - beforeEach(() => { - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - unmountComponentAtNode(container); - container.remove(); - container = null; - }); - it('does not render when errors are being fetched', () => { setupUseSelect({ isFetchingErrors: true, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.children).toHaveLength(0); }); @@ -72,9 +56,7 @@ describe('AMPValidationStatusNotification', () => { isEditedPostNew: true, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.innerHTML).toContain( @@ -90,9 +72,7 @@ describe('AMPValidationStatusNotification', () => { fetchingErrorsRequestErrorMessage: 'request error message', }); - act(() => { - render(, container); - }); + let { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.innerHTML).toContain('request error message'); @@ -100,7 +80,8 @@ describe('AMPValidationStatusNotification', () => { container.querySelector('a[href="http://example.com"]') ).toBeNull(); - container.querySelector('button').click(); + fireEvent.click(container.querySelector('button')); + expect(autosave).toHaveBeenCalledWith({ isPreview: true }); setupUseSelect({ @@ -108,10 +89,10 @@ describe('AMPValidationStatusNotification', () => { fetchingErrorsRequestErrorMessage: 'request error message', }); - act(() => { - render(, container); - }); - container.querySelector('button').click(); + ({ container } = render()); + + fireEvent.click(container.querySelector('button')); + expect(savePost).toHaveBeenCalledWith({ isPreview: true }); }); @@ -120,9 +101,7 @@ describe('AMPValidationStatusNotification', () => { keptMarkupValidationErrorCount: 2, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.innerHTML).toContain( @@ -138,9 +117,7 @@ describe('AMPValidationStatusNotification', () => { unreviewedValidationErrorCount: 3, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.innerHTML).toContain( @@ -156,9 +133,7 @@ describe('AMPValidationStatusNotification', () => { validationErrorCount: 1, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.innerHTML).toContain( @@ -172,9 +147,7 @@ describe('AMPValidationStatusNotification', () => { it('renders message when there are no AMP validation errors', () => { setupUseSelect(); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.innerHTML).toContain( diff --git a/assets/src/block-validation/components/error/index.js b/assets/src/block-validation/components/error/index.js index c1bea6c4837..b9a5adc228d 100644 --- a/assets/src/block-validation/components/error/index.js +++ b/assets/src/block-validation/components/error/index.js @@ -20,7 +20,7 @@ import { __ } from '@wordpress/i18n'; * Internal dependencies */ import './style.css'; -import { BLOCK_VALIDATION_STORE_KEY } from '../../store'; +import { store as blockValidationStore } from '../../store'; import { ErrorPanelTitle } from './error-panel-title'; import { ErrorContent } from './error-content'; @@ -37,7 +37,7 @@ import { ErrorContent } from './error-content'; export function Error({ clientId, error, status, term_id: termId, title }) { const { selectBlock } = useDispatch('core/block-editor'); const reviewLink = useSelect( - (select) => select(BLOCK_VALIDATION_STORE_KEY).getReviewLink(), + (select) => select(blockValidationStore).getReviewLink(), [] ); const reviewed = diff --git a/assets/src/block-validation/components/error/test/error.js b/assets/src/block-validation/components/error/test/error.js index 8e41b84fb0e..af96399d54a 100644 --- a/assets/src/block-validation/components/error/test/error.js +++ b/assets/src/block-validation/components/error/test/error.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { act } from 'react-dom/test-utils'; +import { render, act, fireEvent } from '@testing-library/react'; import { noop } from 'lodash'; import { VALIDATION_ERROR_ACK_ACCEPTED_STATUS, @@ -13,7 +13,6 @@ import { /** * WordPress dependencies */ -import { render } from '@wordpress/element'; import { dispatch, select } from '@wordpress/data'; import { registerBlockType, createBlock } from '@wordpress/blocks'; @@ -21,9 +20,9 @@ import { registerBlockType, createBlock } from '@wordpress/blocks'; * Internal dependencies */ import { Error } from '../index'; -import { createStore } from '../../../store'; +import { store as blockValidationStore } from '../../../store'; -let container, pluginBlock, muPluginBlock, themeBlock, coreBlock, unknownBlock; +let pluginBlock, muPluginBlock, themeBlock, coreBlock, unknownBlock; const TEST_PLUGIN_BLOCK = 'my-plugin/test-block'; const TEST_MU_PLUGIN_BLOCK = 'my-mu-plugin/test-block'; @@ -85,66 +84,65 @@ function createTestStoreAndBlocks() { unknownBlock, ]); - createStore({ - reviewLink: 'http://site.test/wp-admin', - validationErrors: [ - { - clientId: pluginBlock.clientId, - code: 'DISALLOWED_TAG', - status: 3, - term_id: 12, - title: 'Invalid script: jquery.js', - error: { - type: 'js_error', - sources: [], - }, + dispatch(blockValidationStore).setReviewLink('http://site.test/wp-admin'); + + dispatch(blockValidationStore).setValidationErrors([ + { + clientId: pluginBlock.clientId, + code: 'DISALLOWED_TAG', + status: 3, + term_id: 12, + title: 'Invalid script: jquery.js', + error: { + type: 'js_error', + sources: [], }, - { - clientId: muPluginBlock.clientId, - code: 'DISALLOWED_TAG', - status: 3, - term_id: 12, - title: 'Invalid script: jquery.js', - error: { - type: 'js_error', - sources: [], - }, + }, + { + clientId: muPluginBlock.clientId, + code: 'DISALLOWED_TAG', + status: 3, + term_id: 12, + title: 'Invalid script: jquery.js', + error: { + type: 'js_error', + sources: [], }, - { - clientId: themeBlock.clientId, - code: 'DISALLOWED_TAG', - status: 3, - term_id: 12, - title: 'Invalid script: jquery.js', - error: { - type: 'js_error', - sources: [], - }, + }, + { + clientId: themeBlock.clientId, + code: 'DISALLOWED_TAG', + status: 3, + term_id: 12, + title: 'Invalid script: jquery.js', + error: { + type: 'js_error', + sources: [], }, - { - clientId: coreBlock.clientId, - code: 'DISALLOWED_TAG', - status: 3, - term_id: 12, - title: 'Invalid script: jquery.js', - error: { - type: 'js_error', - sources: [], - }, + }, + { + clientId: coreBlock.clientId, + code: 'DISALLOWED_TAG', + status: 3, + term_id: 12, + title: 'Invalid script: jquery.js', + error: { + type: 'js_error', + sources: [], }, - { - clientId: unknownBlock.clientId, - code: 'DISALLOWED_TAG', - status: 3, - term_id: 12, - title: 'Invalid script: jquery.js', - error: { - type: 'js_error', - sources: [], - }, + }, + { + clientId: unknownBlock.clientId, + code: 'DISALLOWED_TAG', + status: 3, + term_id: 12, + title: 'Invalid script: jquery.js', + error: { + type: 'js_error', + sources: [], }, - ], - }); + }, + ]); } function getTestBlock(type) { @@ -194,16 +192,6 @@ describe('Error', () => { createTestStoreAndBlocks(); }); - beforeEach(() => { - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - document.body.removeChild(container); - container = null; - }); - it.each( [ VALIDATION_ERROR_ACK_ACCEPTED_STATUS, @@ -224,9 +212,7 @@ describe('Error', () => { )( 'errors with no associated blocks work correctly', (status, ErrorComponent) => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.firstChild.classList).toContain('amp-error'); expect( @@ -243,11 +229,12 @@ describe('Error', () => { ) ).not.toBeNull(); - container - .querySelector( + fireEvent.click( + container.querySelector( `.amp-error--${getErrorTypeClassName(status)} button` ) - .click(); + ); + expect( container.querySelector('.amp-error__block-type-icon') ).toBeNull(); @@ -281,9 +268,7 @@ describe('Error', () => { )( 'errors with associated blocks work correctly', (status, ErrorComponent) => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.firstChild.classList).toContain('amp-error'); expect( @@ -300,11 +285,12 @@ describe('Error', () => { ) ).not.toBeNull(); - container - .querySelector( + fireEvent.click( + container.querySelector( `.amp-error--${getErrorTypeClassName(status)} button` ) - .click(); + ); + expect( container.querySelector('.amp-error__block-type-icon') ).not.toBeNull(); @@ -341,9 +327,10 @@ describe('Error', () => { pluginBlock.clientId, false ); - render(, container); }); + const { container } = render(); + expect(container.firstChild.classList).toContain('amp-error'); expect( container.querySelectorAll( @@ -356,7 +343,8 @@ describe('Error', () => { container.querySelector('.amp-error--removed button') ).not.toBeNull(); - container.querySelector('.amp-error--removed button').click(); + fireEvent.click(container.querySelector('.amp-error--removed button')); + expect( container.querySelector('.amp-error__block-type-icon') ).toBeNull(); @@ -368,33 +356,20 @@ describe('Error', () => { }); describe('ErrorTypeIcon', () => { - beforeEach(() => { - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - document.body.removeChild(container); - container = null; - }); - it.each([ 'js_error', 'html_attribute_error', 'html_element_error', 'css_error', ])('shows the correct error icon', (errorType) => { - act(() => { - render( - , - container - ); - }); + const { container } = render( + + ); expect( container.querySelector( @@ -404,17 +379,14 @@ describe('ErrorTypeIcon', () => { }); it('shows no error icon for unknown error type', () => { - act(() => { - render( - , - container - ); - }); + const { container } = render( + + ); expect( container.querySelector('svg[class^=amp-error__error-type-icon]') @@ -427,16 +399,6 @@ describe('ErrorContent', () => { createTestStoreAndBlocks(); }); - beforeEach(() => { - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - document.body.removeChild(container); - container = null; - }); - /* eslint-disable jest/no-conditional-in-test */ it.each( [null, 'plugin', 'mu-plugin', 'theme', 'core', 'removed'].reduce( @@ -456,18 +418,17 @@ describe('ErrorContent', () => { (testBlockSource, status) => { const clientId = getTestBlock(testBlockSource); - render( + const { container } = render( , - container + /> ); - container.querySelector(`.components-button`).click(); + fireEvent.click(container.querySelector(`.components-button`)); expect(container.innerHTML).toContain('Markup status'); @@ -540,7 +501,10 @@ describe('ErrorContent', () => { : 'Kept' ); - container.querySelector('.amp-error__select-block').click(); + fireEvent.click( + container.querySelector('.amp-error__select-block') + ); + expect( select('core/block-editor').getSelectedBlock().clientId ).toBe(clientId); diff --git a/assets/src/block-validation/components/icon/test/icon.js b/assets/src/block-validation/components/icon/test/icon.js index f0d5153bc2a..6dd0f33e614 100644 --- a/assets/src/block-validation/components/icon/test/icon.js +++ b/assets/src/block-validation/components/icon/test/icon.js @@ -1,35 +1,16 @@ /** * External dependencies */ -import { act } from 'react-dom/test-utils'; - -/** - * WordPress dependencies - */ -import { render } from '@wordpress/element'; +import { render } from '@testing-library/react'; /** * Internal dependencies */ import { MoreMenuIcon, ToolbarIcon, StatusIcon } from '../index'; -let container; - describe('Icons', () => { - beforeEach(() => { - container = document.createElement('ul'); - document.body.appendChild(container); - }); - - afterEach(() => { - document.body.removeChild(container); - container = null; - }); - it('renders a toolbar icon without AMP broken and no badge', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.querySelector('.amp-toolbar-icon')).not.toBeNull(); expect( @@ -42,9 +23,7 @@ describe('Icons', () => { }); it('renders a toolbar icon without AMP broken and with a badge', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.querySelector('.amp-toolbar-icon')).not.toBeNull(); expect( @@ -57,9 +36,7 @@ describe('Icons', () => { }); it('renders a toolbar icon with AMP broken and with no badge', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.querySelector('.amp-toolbar-icon')).toBeNull(); expect( @@ -74,9 +51,7 @@ describe('Icons', () => { }); it('renders a toolbar icon with AMP broken and with a badge', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.querySelector('.amp-toolbar-icon')).toBeNull(); expect( @@ -91,9 +66,7 @@ describe('Icons', () => { }); it('renders the MoreMenuIcon', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.querySelector('.amp-toolbar-icon')).not.toBeNull(); expect( @@ -102,18 +75,14 @@ describe('Icons', () => { }); it('renders the StatusIcon', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.querySelector('.amp-status-icon')).not.toBeNull(); expect(container.querySelector('.amp-status-icon--broken')).toBeNull(); }); it('renders the broken StatusIcon', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect( container.querySelector('.amp-status-icon--broken') diff --git a/assets/src/block-validation/components/invalid-block-outline/index.js b/assets/src/block-validation/components/invalid-block-outline/index.js index fc6cd9c1518..09c3c30823c 100644 --- a/assets/src/block-validation/components/invalid-block-outline/index.js +++ b/assets/src/block-validation/components/invalid-block-outline/index.js @@ -7,7 +7,7 @@ import { useMemo } from '@wordpress/element'; /** * Internal dependencies */ -import { BLOCK_VALIDATION_STORE_KEY } from '../../store'; +import { store as blockValidationStore } from '../../store'; /** * Adds a style rule for all blocks with validation errors. @@ -15,7 +15,7 @@ import { BLOCK_VALIDATION_STORE_KEY } from '../../store'; export function InvalidBlockOutline() { const validationErrors = useSelect( (select) => - select(BLOCK_VALIDATION_STORE_KEY).getUnreviewedValidationErrors(), + select(blockValidationStore).getUnreviewedValidationErrors(), [] ); diff --git a/assets/src/block-validation/components/sidebar-notification/test/__snapshots__/sidebar-notification.js.snap b/assets/src/block-validation/components/sidebar-notification/test/__snapshots__/sidebar-notification.js.snap index ca2421db332..07e1178855b 100644 --- a/assets/src/block-validation/components/sidebar-notification/test/__snapshots__/sidebar-notification.js.snap +++ b/assets/src/block-validation/components/sidebar-notification/test/__snapshots__/sidebar-notification.js.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`SidebarNotification renders notification without icon and call to action 1`] = `"

Foobar

"`; +exports[`SidebarNotification renders notification without icon and call to action 1`] = `""`; -exports[`SidebarNotification renders status message with icon and call to action 1`] = `"

Foobar

"`; +exports[`SidebarNotification renders status message with icon and call to action 1`] = `""`; diff --git a/assets/src/block-validation/components/sidebar-notification/test/sidebar-notification.js b/assets/src/block-validation/components/sidebar-notification/test/sidebar-notification.js index b0a839e0558..3afe9f02c19 100644 --- a/assets/src/block-validation/components/sidebar-notification/test/sidebar-notification.js +++ b/assets/src/block-validation/components/sidebar-notification/test/sidebar-notification.js @@ -1,12 +1,7 @@ /** * External dependencies */ -import { act } from 'react-dom/test-utils'; - -/** - * WordPress dependencies - */ -import { render, unmountComponentAtNode } from '@wordpress/element'; +import { render } from '@testing-library/react'; /** * Internal dependencies @@ -14,23 +9,8 @@ import { render, unmountComponentAtNode } from '@wordpress/element'; import { SidebarNotification } from '../index'; describe('SidebarNotification', () => { - let container; - - beforeEach(() => { - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - unmountComponentAtNode(container); - container.remove(); - container = null; - }); - it('renders notification without icon and call to action', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.children).toHaveLength(1); @@ -45,16 +25,13 @@ describe('SidebarNotification', () => { }); it('renders status message with icon and call to action', () => { - act(() => { - render( - } - action={