diff --git a/packages/block-library/src/gallery/test/index.native.js b/packages/block-library/src/gallery/test/index.native.js
index a64b8bf403281..70b05870b5f30 100644
--- a/packages/block-library/src/gallery/test/index.native.js
+++ b/packages/block-library/src/gallery/test/index.native.js
@@ -161,7 +161,7 @@ describe( 'Gallery block', () => {
// This case is disabled until the issue (https://github.com/WordPress/gutenberg/issues/38444)
// is addressed.
- it.skip( 'block remains selected after dimissing the media options picker', async () => {
+ it.skip( 'block remains selected after dismissing the media options picker', async () => {
// Initialize with an empty gallery
const { getByLabelText, getByText, getByTestId } =
await initializeEditor( {
@@ -175,7 +175,7 @@ describe( 'Gallery block', () => {
expect( getByText( 'Choose images' ) ).toBeVisible();
expect( getByText( 'WordPress Media Library' ) ).toBeVisible();
- // Dimiss the picker
+ // Dismiss the picker
if ( Platform.isIOS ) {
fireEvent.press( getByText( 'Cancel' ) );
} else {
diff --git a/packages/edit-post/src/components/header/header-toolbar/index.native.js b/packages/edit-post/src/components/header/header-toolbar/index.native.js
index b9b91c8d4f558..948d37fe76ff5 100644
--- a/packages/edit-post/src/components/header/header-toolbar/index.native.js
+++ b/packages/edit-post/src/components/header/header-toolbar/index.native.js
@@ -19,10 +19,15 @@ import {
import { ToolbarGroup, ToolbarButton } from '@wordpress/components';
import {
keyboardClose,
+ audio as audioIcon,
+ media as imageIcon,
+ video as videoIcon,
+ gallery as galleryIcon,
undo as undoIcon,
redo as redoIcon,
} from '@wordpress/icons';
import { store as editorStore } from '@wordpress/editor';
+import { createBlock } from '@wordpress/blocks';
/**
* Internal dependencies
@@ -38,6 +43,7 @@ function HeaderToolbar( {
showInserter,
showKeyboardHideButton,
getStylesFromColorScheme,
+ insertBlock,
onHideKeyboard,
isRTL,
noContentSelected,
@@ -55,6 +61,7 @@ function HeaderToolbar( {
scrollViewRef.current.scrollTo( { x: 0 } );
}
};
+
const renderHistoryButtons = () => {
const buttons = [
/* TODO: replace with EditorHistoryRedo and EditorHistoryUndo. */
@@ -83,6 +90,60 @@ function HeaderToolbar( {
return isRTL ? buttons.reverse() : buttons;
};
+ const onInsertBlock = useCallback(
+ ( blockType ) => () => {
+ insertBlock( createBlock( blockType ), undefined, undefined, true, {
+ source: 'inserter_menu',
+ } );
+ },
+ [ insertBlock ]
+ );
+
+ const renderMediaButtons = (
+
First example paragraph.
+ + + +Second example paragraph.
+ + + + +" +`; diff --git a/packages/edit-post/src/components/visual-editor/test/index.native.js b/packages/edit-post/src/components/visual-editor/test/index.native.js index af07e4309ab69..8c6e041880a83 100644 --- a/packages/edit-post/src/components/visual-editor/test/index.native.js +++ b/packages/edit-post/src/components/visual-editor/test/index.native.js @@ -1,11 +1,12 @@ /** * External dependencies */ -import { initializeEditor, fireEvent } from 'test/helpers'; +import { initializeEditor, getEditorHtml, fireEvent } from 'test/helpers'; /** * WordPress dependencies */ +import { Platform } from '@wordpress/element'; import { getBlockTypes, unregisterBlockType } from '@wordpress/blocks'; import { registerCoreBlocks } from '@wordpress/block-library'; @@ -21,6 +22,12 @@ afterAll( () => { } ); } ); +const MEDIA_OPTIONS = [ + 'Choose from device', + 'Take a Photo', + 'WordPress Media Library', +]; + const initialHtml = `First example paragraph.
@@ -63,6 +70,38 @@ describe( 'when title is focused', () => { screen.getAllByLabelText( /Paragraph Block. Row 3/ )[ 0 ] ).toBeDefined(); } ); + + it( 'media blocks should be displayed', async () => { + const screen = await initializeEditor( { + initialHtml, + } ); + + // Focus first block + fireEvent.press( + screen.getAllByLabelText( /Paragraph Block. Row 1/ )[ 0 ] + ); + + // Focus title + fireEvent( + screen.getAllByLabelText( 'Post title. test' )[ 0 ], + 'select' + ); + + // Assert that the media buttons are visible + const imageButton = await screen.findByTestId( 'insert-image-button' ); + expect( imageButton ).toBeVisible(); + + const videoButton = await screen.findByTestId( 'insert-video-button' ); + expect( videoButton ).toBeVisible(); + + const galleryButton = await screen.findByTestId( + 'insert-gallery-button' + ); + expect( galleryButton ).toBeVisible(); + + const audioButton = await screen.findByTestId( 'insert-audio-button' ); + expect( audioButton ).toBeVisible(); + } ); } ); describe( 'when title is no longer focused', () => { @@ -101,4 +140,82 @@ describe( 'when title is no longer focused', () => { screen.getAllByLabelText( /Heading Block. Row 3/ )[ 0 ] ).toBeDefined(); } ); + + it( 'media blocks should not be displayed', async () => { + const screen = await initializeEditor( { + initialHtml, + } ); + + // Focus first block + fireEvent.press( + screen.getAllByLabelText( /Paragraph Block. Row 1/ )[ 0 ] + ); + + // Focus title + fireEvent( + screen.getAllByLabelText( 'Post title. test' )[ 0 ], + 'select' + ); + + // Focus last block + fireEvent.press( + screen.getAllByLabelText( /Paragraph Block. Row 2/ )[ 0 ] + ); + + // Assert that the media buttons are not visible + const imageButton = screen.queryByTestId( 'insert-image-button' ); + expect( imageButton ).toBeNull(); + + const videoButton = screen.queryByTestId( 'insert-video-button' ); + expect( videoButton ).toBeNull(); + + const galleryButton = screen.queryByTestId( 'insert-gallery-button' ); + expect( galleryButton ).toBeNull(); + + const audioButton = screen.queryByTestId( 'insert-audio-button' ); + expect( audioButton ).toBeNull(); + } ); +} ); + +describe( 'when nothing is selected', () => { + it( 'media buttons and picker display correctly', async () => { + const screen = await initializeEditor( { + initialHtml, + } ); + + const { getByText, getByTestId } = screen; + + // Check that the gallery button is visible within the toolbar + const galleryButton = await screen.queryByTestId( + 'insert-gallery-button' + ); + expect( galleryButton ).toBeVisible(); + + // Press the toolbar Gallery button + fireEvent.press( galleryButton ); + + // Expect the block to be created + expect( + screen.getAllByLabelText( /Gallery Block. Row 3/ )[ 0 ] + ).toBeDefined(); + + expect( getByText( 'Choose images' ) ).toBeVisible(); + MEDIA_OPTIONS.forEach( ( option ) => + expect( getByText( option ) ).toBeVisible() + ); + + // Dismiss the picker + if ( Platform.isIOS ) { + fireEvent.press( getByText( 'Cancel' ) ); + } else { + fireEvent( getByTestId( 'media-options-picker' ), 'backdropPress' ); + } + + // Expect the Gallery block to remain + expect( + screen.getAllByLabelText( /Gallery Block. Row 3/ )[ 0 ] + ).toBeDefined(); + + expect( getEditorHtml() ).toMatchSnapshot(); + } ); } ); diff --git a/packages/react-native-editor/CHANGELOG.md b/packages/react-native-editor/CHANGELOG.md index d43144db54722..add4d4c780483 100644 --- a/packages/react-native-editor/CHANGELOG.md +++ b/packages/react-native-editor/CHANGELOG.md @@ -12,6 +12,7 @@ For each user feature we should also add a importance categorization label to i ## Unreleased - [*] Rename "Reusable blocks" to "Synced patterns", aligning with the web editor. [#51704] - [**] Fix a crash related to Reanimated when closing the editor [#52320] +- [**] Add media inserter buttons to editor toolbar [#51827] ## 1.98.1 - [*] fix: Display heading level dropdown icons and labels [#52004]