Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RNMobile] Add media inserter blocks to toolbar #51827

Merged
merged 18 commits into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/block-library/src/gallery/test/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,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( {
Expand All @@ -155,7 +155,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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -38,6 +43,7 @@ function HeaderToolbar( {
showInserter,
showKeyboardHideButton,
getStylesFromColorScheme,
insertBlock,
onHideKeyboard,
isRTL,
noContentSelected,
Expand All @@ -55,6 +61,7 @@ function HeaderToolbar( {
scrollViewRef.current.scrollTo( { x: 0 } );
}
};

const renderHistoryButtons = () => {
const buttons = [
/* TODO: replace with EditorHistoryRedo and EditorHistoryUndo. */
Expand Down Expand Up @@ -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 = (
<>
geriux marked this conversation as resolved.
Show resolved Hide resolved
<ToolbarButton
key="imageButton"
title={ __( 'Image' ) }
icon={ imageIcon }
onClick={ onInsertBlock( 'core/image' ) }
testID="insert-image-button"
extraProps={ {
hint: __( 'Insert Image Block' ),
} }
/>
<ToolbarButton
key="videoButton"
title={ __( 'Video' ) }
icon={ videoIcon }
onClick={ onInsertBlock( 'core/video' ) }
testID="insert-video-button"
extraProps={ {
hint: __( 'Insert Video Block' ),
} }
/>
<ToolbarButton
key="galleryButton"
title={ __( 'Gallery' ) }
icon={ galleryIcon }
onClick={ onInsertBlock( 'core/gallery' ) }
testID="insert-gallery-button"
extraProps={ {
hint: __( 'Insert Gallery Block' ),
} }
/>
<ToolbarButton
key="audioButton"
title={ __( 'Audio' ) }
icon={ audioIcon }
onClick={ onInsertBlock( 'core/audio' ) }
testID="insert-audio-button"
extraProps={ {
hint: __( 'Insert Audio Block' ),
} }
/>
</>
);

const onToggleInserter = useCallback(
( isOpen ) => {
if ( isOpen ) {
Expand Down Expand Up @@ -131,6 +192,7 @@ function HeaderToolbar( {
useExpandedMode={ useExpandedMode }
onToggle={ onToggleInserter }
/>
{ noContentSelected && renderMediaButtons }
{ renderHistoryButtons() }
<BlockToolbar />
</ScrollView>
Expand Down Expand Up @@ -181,7 +243,8 @@ export default compose( [
};
} ),
withDispatch( ( dispatch ) => {
const { clearSelectedBlock } = dispatch( blockEditorStore );
const { clearSelectedBlock, insertBlock } =
dispatch( blockEditorStore );
const { togglePostTitleSelection } = dispatch( editorStore );

return {
Expand All @@ -191,6 +254,7 @@ export default compose( [
clearSelectedBlock();
togglePostTitleSelection( false );
},
insertBlock,
};
} ),
withViewportMatch( { isLargeViewport: 'medium' } ),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`when nothing is selected media buttons and picker display correctly 1`] = `
"<!-- wp:paragraph -->
<p>First example paragraph.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Second example paragraph.</p>
<!-- /wp:paragraph -->

<!-- wp:gallery {"linkTo":"none"} -->
<figure class="wp-block-gallery has-nested-images columns-default is-cropped"></figure>
<!-- /wp:gallery -->"
`;
135 changes: 134 additions & 1 deletion packages/edit-post/src/components/visual-editor/test/index.native.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
/**
* External dependencies
*/
import { initializeEditor, fireEvent } from 'test/helpers';
import { initializeEditor, getEditorHtml, fireEvent } from 'test/helpers';
import { ActionSheetIOS } from 'react-native';

/**
* WordPress dependencies
*/
import { Platform } from '@wordpress/element';
import { getBlockTypes, unregisterBlockType } from '@wordpress/blocks';
import { registerCoreBlocks } from '@wordpress/block-library';

Expand All @@ -21,6 +23,12 @@ afterAll( () => {
} );
} );

const MEDIA_OPTIONS = [
'Choose from device',
'Take a Photo',
'WordPress Media Library',
];

const initialHtml = `
<!-- wp:paragraph -->
<p>First example paragraph.</p>
Expand Down Expand Up @@ -63,6 +71,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', () => {
Expand Down Expand Up @@ -101,4 +141,97 @@ 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.getAllByLabelText( /Gallery/ )[ 0 ];
geriux marked this conversation as resolved.
Show resolved Hide resolved
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();

// Observe that media options picker is displayed
/* eslint-disable jest/no-conditional-expect */
if ( Platform.isIOS ) {
geriux marked this conversation as resolved.
Show resolved Hide resolved
// On iOS the picker is rendered natively, so we have
// to check the arguments passed to `ActionSheetIOS`.
expect(
ActionSheetIOS.showActionSheetWithOptions
).toHaveBeenCalledWith(
expect.objectContaining( {
title: 'Choose images',
options: [ 'Cancel', ...MEDIA_OPTIONS ],
} ),
expect.any( Function )
);
} else {
expect( getByText( 'Choose images' ) ).toBeVisible();
MEDIA_OPTIONS.forEach( ( option ) =>
expect( getByText( option ) ).toBeVisible()
);
}
/* eslint-enable jest/no-conditional-expect */

// 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();
} );
} );