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;
+ } );
+}