UNPKG

@wordpress/block-library

Version:
621 lines (517 loc) 21.1 kB
/** * External dependencies */ import { act, changeTextOfRichText, fireEvent, getBlock, getEditorHtml, initializeEditor, openBlockSettings, setupCoreBlocks, setupMediaPicker, setupMediaUpload, triggerBlockListLayout, within, } from 'test/helpers'; /** * WordPress dependencies */ import { Platform } from '@wordpress/element'; import { getOtherMediaOptions, requestImageFailedRetryDialog, requestImageUploadCancelDialog, } from '@wordpress/react-native-bridge'; /** * Internal dependencies */ import { addGalleryBlock, initializeWithGalleryBlock, getGalleryItem, generateGalleryBlock, } from './helpers'; const media = [ { localId: 1, localUrl: 'file:///local-image-1.jpeg', serverId: 2000, serverUrl: 'https://test-site.files.wordpress.com/local-image-1.jpeg', }, { localId: 2, localUrl: 'file:///local-image-2.jpeg', serverId: 2001, serverUrl: 'https://test-site.files.wordpress.com/local-image-2.jpeg', }, { localId: 3, localUrl: 'file:///local-image-3.jpeg', serverId: 2002, serverUrl: 'https://test-site.files.wordpress.com/local-image-3.jpeg', }, ]; setupCoreBlocks(); describe( 'Gallery block', () => { it( 'inserts block', async () => { const screen = await addGalleryBlock(); expect( getBlock( screen, 'Gallery' ) ).toBeVisible(); expect( getEditorHtml() ).toMatchSnapshot(); } ); it( 'selects a gallery item', async () => { const { galleryBlock } = await initializeWithGalleryBlock( { numberOfItems: 1, media, selected: false, } ); const galleryItem = getGalleryItem( galleryBlock, 1 ); fireEvent.press( galleryItem ); expect( galleryItem ).toBeVisible(); } ); it( 'shows appender button when gallery has images', async () => { const { galleryBlock, getByText } = await initializeWithGalleryBlock( { numberOfItems: 1, media, } ); const appenderButton = within( galleryBlock ).getByTestId( 'media-placeholder-appender-icon' ); fireEvent.press( appenderButton ); expect( getByText( 'Choose from device' ) ).toBeVisible(); expect( getByText( 'Take a Photo' ) ).toBeVisible(); expect( getByText( 'WordPress Media Library' ) ).toBeVisible(); } ); // This case is disabled until the issue (https://github.com/WordPress/gutenberg/issues/38444) // is addressed. it.skip( 'displays media options picker when selecting the block', async () => { // Initialize with an empty gallery const { getByA11yLabel, getByText, getByTestId } = await initializeEditor( { initialHtml: generateGalleryBlock( 0 ), } ); // Tap on Gallery block fireEvent.press( getByText( 'ADD MEDIA' ) ); // Observe that media options picker is displayed expect( getByText( 'Choose images' ) ).toBeVisible(); expect( getByText( 'WordPress Media Library' ) ).toBeVisible(); // Dimiss the picker if ( Platform.isIOS ) { fireEvent.press( getByText( 'Cancel' ) ); } else { fireEvent( getByTestId( 'media-options-picker' ), 'backdropPress' ); } // Observe that the block is selected, this is done by checking if the block settings // button is visible const blockActionsButton = getByA11yLabel( /Open Block Actions Menu/ ); expect( blockActionsButton ).toBeVisible(); } ); // Test case related to TC001 - Close/Re-open post with an ongoing image upload // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc001 it( 'finishes pending uploads upon opening the editor', async () => { const { notifyUploadingState, notifySucceedState } = setupMediaUpload(); // Initialize with a gallery that contains two items that are being uploaded const { galleryBlock } = await initializeWithGalleryBlock( { numberOfItems: 2, media, useLocalUrl: true, } ); // Notify that the media items are uploading await notifyUploadingState( media[ 0 ] ); await notifyUploadingState( media[ 1 ] ); // Check that images are showing a loading state expect( within( getGalleryItem( galleryBlock, 1 ) ).getByTestId( 'spinner' ) ).toBeVisible(); expect( within( getGalleryItem( galleryBlock, 2 ) ).getByTestId( 'spinner' ) ).toBeVisible(); // Notify that the media items upload succeeded await notifySucceedState( media[ 0 ] ); await notifySucceedState( media[ 1 ] ); expect( getEditorHtml() ).toMatchSnapshot(); } ); // Test case related to TC003 - Add caption to gallery // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc003 it( 'sets caption to gallery', async () => { // Initialize with a gallery that contains one item const { getByA11yLabel } = await initializeWithGalleryBlock( { numberOfItems: 1, media, } ); // Check gallery item caption is not visible const galleryItemCaption = getByA11yLabel( /Image caption. Empty/ ); expect( galleryItemCaption ).not.toBeVisible(); // Set gallery caption const captionField = within( getByA11yLabel( /Gallery caption. Empty/ ) ).getByPlaceholderText( 'Add caption' ); changeTextOfRichText( captionField, '<strong>Bold</strong> <em>italic</em> <s>strikethrough</s> gallery caption' ); expect( getEditorHtml() ).toMatchSnapshot(); } ); // Test case related to TC004 - Add caption to gallery images // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc004 it( 'sets caption to gallery items', async () => { // Initialize with a gallery that contains one item const { galleryBlock } = await initializeWithGalleryBlock( { numberOfItems: 1, media, } ); // Select gallery item const galleryItem = getGalleryItem( galleryBlock, 1 ); fireEvent.press( galleryItem ); // Set gallery item caption const captionField = within( galleryItem ).getByPlaceholderText( 'Add caption' ); changeTextOfRichText( captionField, '<strong>Bold</strong> <em>italic</em> <s>strikethrough</s> image caption' ); expect( getEditorHtml() ).toMatchSnapshot(); } ); // Test case related to TC005 - Choose from device (stay in editor) - Successful upload // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc005 it( 'successfully uploads items', async () => { const { notifyUploadingState, notifySucceedState } = setupMediaUpload(); const { expectMediaPickerCall, mediaPickerCallback } = setupMediaPicker(); // Initialize with an empty gallery const { galleryBlock, getByText } = await initializeWithGalleryBlock(); // Upload images from device fireEvent.press( getByText( 'ADD MEDIA' ) ); fireEvent.press( getByText( 'Choose from device' ) ); expectMediaPickerCall( 'DEVICE_MEDIA_LIBRARY', [ 'image' ], true ); // Return media items picked await mediaPickerCallback( media[ 0 ], media[ 1 ] ); // Check that gallery items are visible await triggerBlockListLayout( galleryBlock ); const galleryItem1 = getGalleryItem( galleryBlock, 1 ); const galleryItem2 = getGalleryItem( galleryBlock, 2 ); expect( galleryItem1 ).toBeVisible(); expect( galleryItem2 ).toBeVisible(); // Check that images are showing a loading state await notifyUploadingState( media[ 0 ] ); await notifyUploadingState( media[ 1 ] ); expect( within( galleryItem1 ).getByTestId( 'spinner' ) ).toBeVisible(); expect( within( galleryItem2 ).getByTestId( 'spinner' ) ).toBeVisible(); // Notify that the media items upload succeeded await notifySucceedState( media[ 0 ] ); await notifySucceedState( media[ 1 ] ); expect( getEditorHtml() ).toMatchSnapshot(); } ); // Test case related to TC006 - Choose from device (stay in editor) - Failed upload // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc006 it( 'handles failed uploads', async () => { const { notifyUploadingState, notifyFailedState } = setupMediaUpload(); const { expectMediaPickerCall, mediaPickerCallback } = setupMediaPicker(); // Initialize with an empty gallery const { galleryBlock, getByText } = await initializeWithGalleryBlock(); // Upload images from device fireEvent.press( getByText( 'ADD MEDIA' ) ); fireEvent.press( getByText( 'Choose from device' ) ); expectMediaPickerCall( 'DEVICE_MEDIA_LIBRARY', [ 'image' ], true ); // Return media items picked await mediaPickerCallback( media[ 0 ], media[ 1 ] ); // Check that gallery items are visible await triggerBlockListLayout( galleryBlock ); const galleryItem1 = getGalleryItem( galleryBlock, 1 ); const galleryItem2 = getGalleryItem( galleryBlock, 2 ); expect( galleryItem1 ).toBeVisible(); expect( galleryItem2 ).toBeVisible(); // Check that images are showing a loading state await notifyUploadingState( media[ 0 ] ); await notifyUploadingState( media[ 1 ] ); expect( within( galleryItem1 ).getByTestId( 'spinner' ) ).toBeVisible(); expect( within( galleryItem2 ).getByTestId( 'spinner' ) ).toBeVisible(); // Notify that the media items uploads failed await notifyFailedState( media[ 0 ] ); await notifyFailedState( media[ 1 ] ); // Check that failed images provide the option to retry the upload fireEvent.press( galleryItem1 ); fireEvent.press( within( galleryItem1 ).getByText( /Failed to insert media/ ) ); expect( requestImageFailedRetryDialog ).toHaveBeenCalledWith( media[ 0 ].localId ); fireEvent.press( galleryItem2 ); fireEvent.press( within( galleryItem2 ).getByText( /Failed to insert media/ ) ); expect( requestImageFailedRetryDialog ).toHaveBeenCalledWith( media[ 1 ].localId ); expect( getEditorHtml() ).toMatchSnapshot(); } ); // Test case related to TC007 - Take a photo // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc007 it( 'takes a photo', async () => { const { notifyUploadingState, notifySucceedState } = setupMediaUpload(); const { expectMediaPickerCall, mediaPickerCallback } = setupMediaPicker(); // Initialize with an empty gallery const { galleryBlock, getByText } = await initializeWithGalleryBlock(); // Take a photo fireEvent.press( getByText( 'ADD MEDIA' ) ); fireEvent.press( getByText( 'Take a Photo' ) ); expectMediaPickerCall( 'DEVICE_CAMERA', [ 'image' ], true ); // Return media item from photo taken await mediaPickerCallback( media[ 0 ] ); // Check gallery item is visible await triggerBlockListLayout( galleryBlock ); const galleryItem = getGalleryItem( galleryBlock, 1 ); expect( galleryItem ).toBeVisible(); // Check image is showing a loading state await notifyUploadingState( media[ 0 ] ); expect( within( galleryItem ).getByTestId( 'spinner' ) ).toBeVisible(); // Notify that the media item upload succeeded await notifySucceedState( media[ 0 ] ); expect( getEditorHtml() ).toMatchSnapshot(); } ); // Test case related to TC008 - Choose from the free photo library // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc008 it( 'uploads from free photo library', async () => { const freePhotoMedia = [ ...media ].map( ( item, index ) => ( { ...item, localUrl: `https://images.pexels.com/photos/110854/pexels-photo-${ index + 1 }.jpeg`, } ) ); const { notifyUploadingState, notifySucceedState } = setupMediaUpload(); const { expectMediaPickerCall, mediaPickerCallback } = setupMediaPicker(); let otherMediaOptionsCallback; getOtherMediaOptions.mockImplementation( ( filter, callback ) => { otherMediaOptionsCallback = callback; } ); // Initialize with an empty gallery const { galleryBlock, getByText } = await initializeWithGalleryBlock(); // Notify other media options act( () => otherMediaOptionsCallback( [ { label: 'Free Photo Library', value: 'stock-photo-library', }, ] ) ); // Upload images from free photo library fireEvent.press( getByText( 'ADD MEDIA' ) ); fireEvent.press( getByText( 'Free Photo Library' ) ); expectMediaPickerCall( 'stock-photo-library', [ 'image' ], true ); // Return media items picked await act( async () => mediaPickerCallback( freePhotoMedia[ 0 ], freePhotoMedia[ 1 ] ) ); // Check that gallery items are visible await triggerBlockListLayout( galleryBlock ); const galleryItem1 = getGalleryItem( galleryBlock, 1 ); const galleryItem2 = getGalleryItem( galleryBlock, 2 ); expect( galleryItem1 ).toBeVisible(); expect( galleryItem2 ).toBeVisible(); // Check that images are showing a loading state await notifyUploadingState( freePhotoMedia[ 0 ] ); await notifyUploadingState( freePhotoMedia[ 1 ] ); expect( within( galleryItem1 ).getByTestId( 'spinner' ) ).toBeVisible(); expect( within( galleryItem2 ).getByTestId( 'spinner' ) ).toBeVisible(); // Notify that the media items upload succeeded await notifySucceedState( freePhotoMedia[ 0 ] ); await notifySucceedState( freePhotoMedia[ 1 ] ); expect( getEditorHtml() ).toMatchSnapshot(); } ); // Test case related to TC009 - Choose from device (stay in editor) - Cancel upload // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc009 it( 'cancels uploads', async () => { const { notifyUploadingState, notifyResetState } = setupMediaUpload(); const { expectMediaPickerCall, mediaPickerCallback } = setupMediaPicker(); // Initialize with an empty gallery const { galleryBlock, getByText } = await initializeWithGalleryBlock(); // Upload images from device fireEvent.press( getByText( 'ADD MEDIA' ) ); fireEvent.press( getByText( 'Choose from device' ) ); expectMediaPickerCall( 'DEVICE_MEDIA_LIBRARY', [ 'image' ], true ); // Return media items picked await mediaPickerCallback( media[ 0 ], media[ 1 ] ); // Check that gallery items are visible await triggerBlockListLayout( galleryBlock ); const galleryItem1 = getGalleryItem( galleryBlock, 1 ); const galleryItem2 = getGalleryItem( galleryBlock, 2 ); expect( galleryItem1 ).toBeVisible(); expect( galleryItem2 ).toBeVisible(); // Check that images are showing a loading state await notifyUploadingState( media[ 0 ] ); await notifyUploadingState( media[ 1 ] ); expect( within( galleryItem1 ).getByTestId( 'spinner' ) ).toBeVisible(); expect( within( galleryItem2 ).getByTestId( 'spinner' ) ).toBeVisible(); // Cancel uploads fireEvent.press( galleryItem1 ); fireEvent.press( within( galleryItem1 ).getByTestId( 'spinner' ) ); expect( requestImageUploadCancelDialog ).toHaveBeenCalledWith( media[ 0 ].localId ); await notifyResetState( media[ 0 ] ); fireEvent.press( galleryItem2 ); fireEvent.press( within( galleryItem2 ).getByTestId( 'spinner' ) ); expect( requestImageUploadCancelDialog ).toHaveBeenCalledWith( media[ 1 ].localId ); await notifyResetState( media[ 1 ] ); expect( getEditorHtml() ).toMatchSnapshot(); } ); // Test case related to TC010 - Rearrange images in Gallery // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc010 it( 'rearranges gallery items', async () => { // Initialize with a gallery that contains three items const { galleryBlock } = await initializeWithGalleryBlock( { numberOfItems: 3, media, } ); // Rearrange items (final disposition will be: Image 3 - Image 1 - Image 2) const galleryItem1 = getGalleryItem( galleryBlock, 1 ); const galleryItem3 = getGalleryItem( galleryBlock, 3 ); fireEvent.press( galleryItem3 ); await act( () => fireEvent.press( within( galleryItem3 ).getByA11yLabel( /Move block left from position 3 to position 2/ ) ) ); fireEvent.press( galleryItem1 ); await act( () => fireEvent.press( within( galleryItem1 ).getByA11yLabel( /Move block right from position 1 to position 2/ ) ) ); expect( getEditorHtml() ).toMatchSnapshot(); } ); // Test case related to TC011 - Choose from Other Apps (iOS Files App) // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc011 it( 'uploads from other apps', async () => { const otherAppsMedia = [ ...media ].map( ( item, index ) => ( { ...item, localUrl: `file:///IMG_${ index + 1 }.JPG`, } ) ); const { notifyUploadingState, notifySucceedState } = setupMediaUpload(); const { expectMediaPickerCall, mediaPickerCallback } = setupMediaPicker(); let otherMediaOptionsCallback; getOtherMediaOptions.mockImplementation( ( filter, callback ) => { otherMediaOptionsCallback = callback; } ); // Initialize with an empty gallery const { galleryBlock, getByText } = await initializeWithGalleryBlock(); // Notify other media options act( () => otherMediaOptionsCallback( [ { label: 'Other Apps', value: 'other-files' }, ] ) ); // Upload images from other apps fireEvent.press( getByText( 'ADD MEDIA' ) ); fireEvent.press( getByText( 'Other Apps' ) ); expectMediaPickerCall( 'other-files', [ 'image' ], true ); // Return media items picked await mediaPickerCallback( otherAppsMedia[ 0 ], otherAppsMedia[ 1 ] ); // Check that gallery items are visible await triggerBlockListLayout( galleryBlock ); const galleryItem1 = getGalleryItem( galleryBlock, 1 ); const galleryItem2 = getGalleryItem( galleryBlock, 2 ); expect( galleryItem1 ).toBeVisible(); expect( galleryItem2 ).toBeVisible(); // Check that images are showing a loading state await notifyUploadingState( otherAppsMedia[ 0 ] ); await notifyUploadingState( otherAppsMedia[ 1 ] ); expect( within( galleryItem1 ).getByTestId( 'spinner' ) ).toBeVisible(); expect( within( galleryItem2 ).getByTestId( 'spinner' ) ).toBeVisible(); // Notify that the media items upload succeeded await notifySucceedState( otherAppsMedia[ 0 ] ); await notifySucceedState( otherAppsMedia[ 1 ] ); expect( getEditorHtml() ).toMatchSnapshot(); } ); // Test case related to TC012 - Settings - Link to // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc012 it( 'overrides "Link to" setting of gallery items', async () => { // Initialize with a gallery that contains two items, the latter includes "linkDestination" attribute const screen = await initializeWithGalleryBlock( { html: `<!-- wp:gallery {"linkTo":"none"} --> <figure class="wp-block-gallery has-nested-images columns-default is-cropped"><!-- wp:image {"id":${ media[ 0 ].localId }} --> <figure class="wp-block-image"><img src="${ media[ 0 ].localUrl }" alt="" class="wp-image-${ media[ 0 ].localId }"/></figure> <!-- /wp:image --> <!-- wp:image {"id":${ media[ 1 ].localId },"linkDestination":"attachment"} --> <figure class="wp-block-image"><img src="${ media[ 1 ].localUrl }" alt="" class="wp-image-${ media[ 1 ].localId }"/></figure> <!-- /wp:image --></figure> <!-- /wp:gallery -->`, numberOfItems: 2, } ); const { getByText } = screen; // Set "Link to" setting via Gallery block settings await openBlockSettings( screen ); fireEvent.press( getByText( 'Link to' ) ); fireEvent.press( getByText( 'Media File' ) ); expect( getEditorHtml() ).toMatchSnapshot(); } ); // Test cases related to TC013 - Settings - Columns // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc013 describe( 'Columns setting', () => { it( 'does not increment due to maximum value', async () => { // Initialize with a gallery that contains three items const screen = await initializeWithGalleryBlock( { numberOfItems: 3, media, } ); const { getByA11yLabel } = screen; await openBlockSettings( screen ); // Can't increment due to maximum value // NOTE: Default columns value is 3 fireEvent( getByA11yLabel( /Columns\. Value is 3/ ), 'accessibilityAction', { nativeEvent: { actionName: 'increment' }, } ); expect( getEditorHtml() ).toMatchSnapshot(); } ); it( 'decrements columns', async () => { // Initialize with a gallery that contains three items const screen = await initializeWithGalleryBlock( { numberOfItems: 3, media, } ); const { getByA11yLabel } = screen; await openBlockSettings( screen ); // Decrement columns fireEvent( getByA11yLabel( /Columns\. Value is 3/ ), 'accessibilityAction', { nativeEvent: { actionName: 'decrement' }, } ); expect( getEditorHtml() ).toMatchSnapshot(); } ); } ); // Test case related to TC014 - Settings - Crop images // Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc014 it( 'disables crop images setting', async () => { // Initialize with a gallery that contains one item const screen = await initializeWithGalleryBlock( { numberOfItems: 1, media, } ); const { getByText } = screen; await openBlockSettings( screen ); // Disable crop images setting fireEvent.press( getByText( 'Crop images' ) ); expect( getEditorHtml() ).toMatchSnapshot(); } ); } );