diff --git a/packages/block-library/src/image/test/edit.native.js b/packages/block-library/src/image/test/edit.native.js index 73f4ec22a554d..1f1bdd6ae4eda 100644 --- a/packages/block-library/src/image/test/edit.native.js +++ b/packages/block-library/src/image/test/edit.native.js @@ -8,6 +8,7 @@ import { getEditorHtml, render, waitFor, + setupApiFetch, } from 'test/helpers'; import { Image } from 'react-native'; import Clipboard from '@react-native-clipboard/clipboard'; @@ -22,9 +23,10 @@ import { sendMediaUpload, subscribeMediaUpload, } from '@wordpress/react-native-bridge'; -import { select } from '@wordpress/data'; +import { select, dispatch } from '@wordpress/data'; import { store as editorStore } from '@wordpress/editor'; import { store as coreStore } from '@wordpress/core-data'; +import apiFetch from '@wordpress/api-fetch'; import '@wordpress/jest-console'; /** @@ -45,7 +47,15 @@ function mockGetMedia( media ) { jest.spyOn( select( coreStore ), 'getMedia' ).mockReturnValue( media ); } -const apiFetchPromise = Promise.resolve( {} ); +const FETCH_MEDIA = { + request: { + path: `/wp/v2/media/1?context=edit`, + }, + response: { + source_url: 'https://cldup.com/cXyG__fTLN.jpg', + id: 1, + }, +}; const clipboardPromise = Promise.resolve( '' ); Clipboard.getString.mockImplementation( () => clipboardPromise ); @@ -58,6 +68,18 @@ beforeAll( () => { getSizeSpy.mockImplementation( ( _url, callback ) => callback( 300, 200 ) ); } ); +beforeEach( () => { + // Mock media fetch requests + setupApiFetch( [ FETCH_MEDIA ] ); + + // Invalidate `getMedia` resolutions to allow requesting to the API the same media id + dispatch( coreStore ).invalidateResolutionForStoreSelector( 'getMedia' ); +} ); + +afterEach( () => { + apiFetch.mockReset(); +} ); + afterAll( () => { getBlockTypes().forEach( ( { name } ) => { unregisterBlockType( name ); @@ -78,8 +100,8 @@ describe( 'Image Block', () => {
Mountain
`; const screen = await initializeEditor( { initialHtml } ); - // We must await the image fetch via `getMedia` - await act( () => apiFetchPromise ); + // Check that image is fetched via `getMedia` + expect( apiFetch ).toHaveBeenCalledWith( FETCH_MEDIA.request ); const [ imageBlock ] = screen.getAllByLabelText( /Image Block/ ); fireEvent.press( imageBlock ); @@ -105,8 +127,8 @@ describe( 'Image Block', () => {
Mountain
`; const screen = await initializeEditor( { initialHtml } ); - // We must await the image fetch via `getMedia` - await act( () => apiFetchPromise ); + // Check that image is fetched via `getMedia` + expect( apiFetch ).toHaveBeenCalledWith( FETCH_MEDIA.request ); const [ imageBlock ] = screen.getAllByLabelText( /Image Block/ ); fireEvent.press( imageBlock ); @@ -132,8 +154,8 @@ describe( 'Image Block', () => {
Mountain
`; const screen = await initializeEditor( { initialHtml } ); - // We must await the image fetch via `getMedia` - await act( () => apiFetchPromise ); + // Check that image is fetched via `getMedia` + expect( apiFetch ).toHaveBeenCalledWith( FETCH_MEDIA.request ); const [ imageBlock ] = screen.getAllByLabelText( /Image Block/ ); fireEvent.press( imageBlock ); @@ -169,8 +191,8 @@ describe( 'Image Block', () => {
Mountain
`; const screen = await initializeEditor( { initialHtml } ); - // We must await the image fetch via `getMedia` - await act( () => apiFetchPromise ); + // Check that image is fetched via `getMedia` + expect( apiFetch ).toHaveBeenCalledWith( FETCH_MEDIA.request ); const [ imageBlock ] = screen.getAllByLabelText( /Image Block/ ); fireEvent.press( imageBlock ); @@ -211,8 +233,8 @@ describe( 'Image Block', () => {
Mountain
`; const screen = await initializeEditor( { initialHtml } ); - // We must await the image fetch via `getMedia` - await act( () => apiFetchPromise ); + // Check that image is not fetched via `getMedia` due to the presence of query parameters in the URL. + expect( apiFetch ).not.toHaveBeenCalledWith( FETCH_MEDIA.request ); const [ imageBlock ] = screen.getAllByLabelText( /Image Block/ ); fireEvent.press( imageBlock ); @@ -236,8 +258,8 @@ describe( 'Image Block', () => {
Mountain
`; const screen = await initializeEditor( { initialHtml } ); - // We must await the image fetch via `getMedia` - await act( () => apiFetchPromise ); + // Check that image is fetched via `getMedia` + expect( apiFetch ).toHaveBeenCalledWith( FETCH_MEDIA.request ); const [ imageBlock ] = screen.getAllByLabelText( /Image Block/ ); fireEvent.press( imageBlock ); @@ -267,8 +289,8 @@ describe( 'Image Block', () => { `; const screen = await initializeEditor( { initialHtml } ); - // We must await the image fetch via `getMedia` - await act( () => apiFetchPromise ); + // Check that image is fetched via `getMedia` + expect( apiFetch ).toHaveBeenCalledWith( FETCH_MEDIA.request ); const [ imageBlock ] = screen.getAllByLabelText( /Image Block/ ); fireEvent.press( imageBlock ); diff --git a/test/native/integration-test-helpers/README.md b/test/native/integration-test-helpers/README.md index a02bbce64c965..49b63794ed8ff 100644 --- a/test/native/integration-test-helpers/README.md +++ b/test/native/integration-test-helpers/README.md @@ -54,6 +54,10 @@ Changes the text of a RichText component. Paste content into a RichText component. +### [`setupApiFetch`](https://github.com/WordPress/gutenberg/blob/HEAD/test/native/integration-test-helpers/setup-api-fetch.js) + +Sets up the `apiFetch` library for testing by mocking request responses. + ### [`setupCoreBlocks`](https://github.com/WordPress/gutenberg/blob/HEAD/test/native/integration-test-helpers/setup-core-blocks.js) Registers all core blocks or a specific list of blocks before running tests, once the tests are run, all registered blocks are unregistered. diff --git a/test/native/integration-test-helpers/index.js b/test/native/integration-test-helpers/index.js index 0df77d7312196..13e74a69c4a66 100644 --- a/test/native/integration-test-helpers/index.js +++ b/test/native/integration-test-helpers/index.js @@ -14,6 +14,7 @@ export { openBlockSettings } from './open-block-settings'; export { selectRangeInRichText } from './rich-text-select-range'; export { typeInRichText } from './rich-text-type'; export { pasteIntoRichText } from './rich-text-paste'; +export { setupApiFetch } from './setup-api-fetch'; export { setupCoreBlocks } from './setup-core-blocks'; export { setupMediaPicker } from './setup-media-picker'; export { setupMediaUpload } from './setup-media-upload'; diff --git a/test/native/integration-test-helpers/setup-api-fetch.js b/test/native/integration-test-helpers/setup-api-fetch.js new file mode 100644 index 0000000000000..e8b20e261630b --- /dev/null +++ b/test/native/integration-test-helpers/setup-api-fetch.js @@ -0,0 +1,50 @@ +/** + * WordPress dependencies + */ +import apiFetch from '@wordpress/api-fetch'; + +/** + * Sets up the `apiFetch` library for testing by mocking request responses. + * + * Example: + * + * const responses = [ + * { + * request: { + * path: `/wp/v2/media/1?context=edit`, + * }, + * response: { + * source_url: 'https://image-1.jpg', + * id: 1, + * }, + * }, + * { + * request: { + * path: `/wp/v2/media/2?context=edit`, + * }, + * response: { + * source_url: 'https://image-2.jpg', + * id: 2, + * }, + * }, + * ]; + * setupApiFetch( responses ); + * ... + * expect( apiFetch ).toHaveBeenCalledWith( responses[1].request ); + * + * @param {object[]} responses Array with the potential responses to return upon requests. + * + */ +export function setupApiFetch( responses ) { + apiFetch.mockImplementation( async ( options ) => { + const matchedResponse = responses.find( + ( { request: { path, method } } ) => { + return ( + path === options.path && + ( ! options.method || method === options.method ) + ); + } + ); + return matchedResponse?.response; + } ); +}