diff --git a/packages/e2e-tests/specs/editor/blocks/__snapshots__/image.test.js.snap b/packages/e2e-tests/specs/editor/blocks/__snapshots__/image.test.js.snap deleted file mode 100644 index 6683872d66fc6..0000000000000 --- a/packages/e2e-tests/specs/editor/blocks/__snapshots__/image.test.js.snap +++ /dev/null @@ -1,25 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Image allows changing aspect ratio using the crop tools 1`] = `"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMAAwICAgICAwICAgMDAwMEBgQEBAQECAYGBQYJCAoKCQgJCQoMDwwKCw4LCQkNEQ0ODxAQERAKDBITEhATDxAQEP/bAEMBAwMDBAMECAQECBALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/AABEIAAoACgMBIgACEQEDEQH/xAAVAAEBAAAAAAAAAAAAAAAAAAAJB//EACAQAAADCQEAAAAAAAAAAAAAAAAEBQEDBgk1OHR3srX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AlMlS6eKdfnvRTgrytVTuQ86aChkqXTxTr896KcFeVqqdyHnTQH//2Q=="`; - -exports[`Image allows changing aspect ratio using the crop tools 2`] = `"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMAAwICAgICAwICAgMDAwMEBgQEBAQECAYGBQYJCAoKCQgJCQoMDwwKCw4LCQkNEQ0ODxAQERAKDBITEhATDxAQEP/bAEMBAwMDBAMECAQECBALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/AABEIAAYACgMBIgACEQEDEQH/xAAWAAEBAQAAAAAAAAAAAAAAAAAABwn/xAAgEAABAgUFAAAAAAAAAAAAAAAABAUBAwYJNTh0d7K1/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AJTZU1T1Tx+u9FuNXnbKrdxM7RAA/9k="`; - -exports[`Image allows rotating using the crop tools 1`] = `"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMAAwICAgICAwICAgMDAwMEBgQEBAQECAYGBQYJCAoKCQgJCQoMDwwKCw4LCQkNEQ0ODxAQERAKDBITEhATDxAQEP/bAEMBAwMDBAMECAQECBALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/AABEIAAoACgMBIgACEQEDEQH/xAAVAAEBAAAAAAAAAAAAAAAAAAAJB//EACAQAAADCQEAAAAAAAAAAAAAAAAEBQEDBgk1OHR3srX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AlMlS6eKdfnvRTgrytVTuQ86aChkqXTxTr896KcFeVqqdyHnTQH//2Q=="`; - -exports[`Image allows rotating using the crop tools 2`] = `"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMAAwICAgICAwICAgMDAwMEBgQEBAQECAYGBQYJCAoKCQgJCQoMDwwKCw4LCQkNEQ0ODxAQERAKDBITEhATDxAQEP/bAEMBAwMDBAMECAQECBALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/AABEIAAoACgMBIgACEQEDEQH/xAAWAAEBAQAAAAAAAAAAAAAAAAAABwn/xAAhEAAAAgsBAAAAAAAAAAAAAAAABQIEBwgVGVVWk5XR1P/EABQBAQAAAAAAAAAAAAAAAAAAAAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCUyVHp7+ZVtTHwhJUenv5lW1MfCNXosa1NbzJdCLGtTW8yXQH/2Q=="`; - -exports[`Image allows zooming using the crop tools 1`] = `"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMAAwICAgICAwICAgMDAwMEBgQEBAQECAYGBQYJCAoKCQgJCQoMDwwKCw4LCQkNEQ0ODxAQERAKDBITEhATDxAQEP/bAEMBAwMDBAMECAQECBALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/AABEIAAoACgMBIgACEQEDEQH/xAAVAAEBAAAAAAAAAAAAAAAAAAAJB//EACAQAAADCQEAAAAAAAAAAAAAAAAEBQEDBgk1OHR3srX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AlMlS6eKdfnvRTgrytVTuQ86aChkqXTxTr896KcFeVqqdyHnTQH//2Q=="`; - -exports[`Image allows zooming using the crop tools 2`] = `"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMAAwICAgICAwICAgMDAwMEBgQEBAQECAYGBQYJCAoKCQgJCQoMDwwKCw4LCQkNEQ0ODxAQERAKDBITEhATDxAQEP/bAEMBAwMDBAMECAQECBALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/AABEIAAUABQMBIgACEQEDEQH/xAAVAAEBAAAAAAAAAAAAAAAAAAAACP/EABoQAQABBQAAAAAAAAAAAAAAAAAEBwk4hbX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8Aqm1xgnTLddiaAD//2Q=="`; - -exports[`Image should drag and drop files into media placeholder 1`] = ` -" -
\\"\\"/
-" -`; - -exports[`Image should undo without broken temporary state 1`] = ` -" -
\\"\\"/
-" -`; diff --git a/packages/e2e-tests/specs/editor/blocks/image.test.js b/packages/e2e-tests/specs/editor/blocks/image.test.js deleted file mode 100644 index ac3ddba34b46e..0000000000000 --- a/packages/e2e-tests/specs/editor/blocks/image.test.js +++ /dev/null @@ -1,373 +0,0 @@ -/** - * External dependencies - */ -import path from 'path'; -import fs from 'fs'; -import os from 'os'; -import { v4 as uuid } from 'uuid'; - -/** - * WordPress dependencies - */ -import { - insertBlock, - getEditedPostContent, - createNewPost, - clickButton, - clickBlockToolbarButton, - clickMenuItem, - openDocumentSettingsSidebar, - pressKeyWithModifier, -} from '@wordpress/e2e-test-utils'; - -async function upload( selector ) { - await page.waitForSelector( selector ); - const inputElement = await page.$( selector ); - const testImagePath = path.join( - __dirname, - '..', - '..', - '..', - 'assets', - '10x10_e2e_test_image_z9T8jK.png' - ); - const filename = uuid(); - const tmpFileName = path.join( os.tmpdir(), filename + '.png' ); - fs.copyFileSync( testImagePath, tmpFileName ); - await inputElement.uploadFile( tmpFileName ); - return filename; -} - -async function waitForImage( filename ) { - await page.waitForSelector( - `.wp-block-image img[src$="${ filename }.png"]` - ); -} - -async function getSrc( elementHandle ) { - return elementHandle.evaluate( ( node ) => node.src ); -} -async function getDataURL( elementHandle ) { - return elementHandle.evaluate( ( node ) => { - const canvas = document.createElement( 'canvas' ); - const context = canvas.getContext( '2d' ); - canvas.width = node.width; - canvas.height = node.height; - context.drawImage( node, 0, 0 ); - return canvas.toDataURL( 'image/jpeg' ); - } ); -} - -describe( 'Image', () => { - beforeEach( async () => { - await createNewPost(); - } ); - - it( 'can be inserted', async () => { - await insertBlock( 'Image' ); - const filename = await upload( '.wp-block-image input[type="file"]' ); - await waitForImage( filename ); - - const regex = new RegExp( - `\\s*
\\s*` - ); - expect( await getEditedPostContent() ).toMatch( regex ); - } ); - - it( 'should replace, reset size, and keep selection', async () => { - await insertBlock( 'Image' ); - const filename1 = await upload( '.wp-block-image input[type="file"]' ); - await waitForImage( filename1 ); - - const regex1 = new RegExp( - `\\s*
\\s*` - ); - expect( await getEditedPostContent() ).toMatch( regex1 ); - - await openDocumentSettingsSidebar(); - await page.click( '[aria-label="Image size presets"] button' ); - - const regex2 = new RegExp( - `\\s*
<\\/figure>\\s*` - ); - - expect( await getEditedPostContent() ).toMatch( regex2 ); - - await clickButton( 'Replace' ); - const filename2 = await upload( - '.block-editor-media-replace-flow__options input[type="file"]' - ); - await waitForImage( filename2 ); - - const regex3 = new RegExp( - `\\s*
\\s*` - ); - expect( await getEditedPostContent() ).toMatch( regex3 ); - // Focus outside the block to avoid the image caption being selected - // It can happen on CI specially. - await page.click( '.wp-block-post-title' ); - await page.click( '.wp-block-image img' ); - await page.keyboard.press( 'Backspace' ); - - expect( await getEditedPostContent() ).toBe( '' ); - } ); - - it.skip( 'should place caret at end of caption after merging empty paragraph', async () => { - await insertBlock( 'Image' ); - const fileName = await upload( '.wp-block-image input[type="file"]' ); - await waitForImage( fileName ); - await page.keyboard.type( '1' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.press( 'Backspace' ); - await page.keyboard.type( '2' ); - - expect( - await page.evaluate( () => document.activeElement.innerHTML ) - ).toBe( '12' ); - } ); - - it( 'should allow soft line breaks in caption', async () => { - await insertBlock( 'Image' ); - const fileName = await upload( '.wp-block-image input[type="file"]' ); - await waitForImage( fileName ); - await page.keyboard.type( '12' ); - await page.keyboard.press( 'ArrowLeft' ); - await page.keyboard.press( 'Enter' ); - - expect( - await page.evaluate( () => document.activeElement.innerHTML ) - ).toBe( '1
2' ); - } ); - - it( 'should have keyboard navigable toolbar for caption', async () => { - await insertBlock( 'Image' ); - const fileName = await upload( '.wp-block-image input[type="file"]' ); - await waitForImage( fileName ); - // Navigate to More, Link, Italic and finally Bold. - await pressKeyWithModifier( 'shift', 'Tab' ); - await pressKeyWithModifier( 'shift', 'Tab' ); - await pressKeyWithModifier( 'shift', 'Tab' ); - await pressKeyWithModifier( 'shift', 'Tab' ); - await page.keyboard.press( 'Space' ); - await page.keyboard.press( 'a' ); - await page.keyboard.press( 'ArrowRight' ); - - expect( - await page.evaluate( () => document.activeElement.innerHTML ) - ).toBe( 'a' ); - } ); - - it( 'should drag and drop files into media placeholder', async () => { - await page.keyboard.press( 'Enter' ); - await insertBlock( 'Image' ); - - // Confirm correct setup. - expect( await getEditedPostContent() ).toMatchSnapshot(); - - const image = await page.$( '[data-type="core/image"]' ); - - await image.evaluate( () => { - const input = document.createElement( 'input' ); - input.type = 'file'; - input.id = 'wp-temp-test-input'; - document.body.appendChild( input ); - } ); - - const fileName = await upload( '#wp-temp-test-input' ); - - const paragraphRect = await image.boundingBox(); - const pX = paragraphRect.x + paragraphRect.width / 2; - const pY = paragraphRect.y + paragraphRect.height / 3; - - await image.evaluate( - ( element, clientX, clientY ) => { - const input = document.getElementById( 'wp-temp-test-input' ); - const dataTransfer = new DataTransfer(); - dataTransfer.items.add( input.files[ 0 ] ); - const event = new DragEvent( 'drop', { - bubbles: true, - clientX, - clientY, - dataTransfer, - } ); - element.dispatchEvent( event ); - }, - pX, - pY - ); - - await waitForImage( fileName ); - } ); - - it( 'allows zooming using the crop tools', async () => { - // Insert the block, upload a file and crop. - await insertBlock( 'Image' ); - const filename = await upload( '.wp-block-image input[type="file"]' ); - await waitForImage( filename ); - - // Assert that the image is initially unscaled and unedited. - const initialImage = await page.$( '.wp-block-image img' ); - const initialImageSrc = await getSrc( initialImage ); - const initialImageDataURL = await getDataURL( initialImage ); - expect( initialImageDataURL ).toMatchSnapshot(); - - // Zoom in to twice the amount using the zoom input. - await clickBlockToolbarButton( 'Crop' ); - await clickBlockToolbarButton( 'Zoom' ); - await page.waitForFunction( () => - document.activeElement.classList.contains( - 'components-range-control__slider' - ) - ); - await page.keyboard.press( 'Tab' ); - await page.waitForFunction( () => - document.activeElement.classList.contains( - 'components-input-control__input' - ) - ); - await pressKeyWithModifier( 'primary', 'a' ); - await page.keyboard.type( '200' ); - await page.keyboard.press( 'Escape' ); - await clickBlockToolbarButton( 'Apply', 'content' ); - - // Wait for the cropping tools to disappear. - await page.waitForSelector( - '.wp-block-image img:not( .reactEasyCrop_Image )' - ); - - // Assert that the image is edited. - const updatedImage = await page.$( '.wp-block-image img' ); - const updatedImageSrc = await getSrc( updatedImage ); - expect( initialImageSrc ).not.toEqual( updatedImageSrc ); - const updatedImageDataURL = await getDataURL( updatedImage ); - expect( initialImageDataURL ).not.toEqual( updatedImageDataURL ); - expect( updatedImageDataURL ).toMatchSnapshot(); - } ); - - it( 'allows changing aspect ratio using the crop tools', async () => { - // Insert the block, upload a file and crop. - await insertBlock( 'Image' ); - const filename = await upload( '.wp-block-image input[type="file"]' ); - await waitForImage( filename ); - - // Assert that the image is initially unscaled and unedited. - const initialImage = await page.$( '.wp-block-image img' ); - const initialImageSrc = await getSrc( initialImage ); - const initialImageDataURL = await getDataURL( initialImage ); - expect( initialImageDataURL ).toMatchSnapshot(); - - // Zoom in to twice the amount using the zoom input. - await clickBlockToolbarButton( 'Crop' ); - await clickBlockToolbarButton( 'Aspect Ratio' ); - await page.waitForFunction( () => - document.activeElement.classList.contains( - 'components-menu-item__button' - ) - ); - await clickMenuItem( '16:10' ); - await clickBlockToolbarButton( 'Apply', 'content' ); - - // Wait for the cropping tools to disappear. - await page.waitForSelector( - '.wp-block-image img:not( .reactEasyCrop_Image )' - ); - - // Assert that the image is edited. - const updatedImage = await page.$( '.wp-block-image img' ); - const updatedImageSrc = await getSrc( updatedImage ); - expect( initialImageSrc ).not.toEqual( updatedImageSrc ); - const updatedImageDataURL = await getDataURL( updatedImage ); - expect( initialImageDataURL ).not.toEqual( updatedImageDataURL ); - expect( updatedImageDataURL ).toMatchSnapshot(); - } ); - - it( 'allows rotating using the crop tools', async () => { - // Insert the block, upload a file and crop. - await insertBlock( 'Image' ); - const filename = await upload( '.wp-block-image input[type="file"]' ); - await waitForImage( filename ); - - // Assert that the image is initially unscaled and unedited. - const initialImage = await page.$( '.wp-block-image img' ); - const initialImageDataURL = await getDataURL( initialImage ); - expect( initialImageDataURL ).toMatchSnapshot(); - - // Double the image's size using the zoom input. - await clickBlockToolbarButton( 'Crop' ); - await page.waitForSelector( '.wp-block-image img.reactEasyCrop_Image' ); - await clickBlockToolbarButton( 'Rotate' ); - await clickBlockToolbarButton( 'Apply', 'content' ); - - await page.waitForSelector( - '.wp-block-image img:not( .reactEasyCrop_Image )' - ); - - // Assert that the image is edited. - const updatedImage = await page.$( '.wp-block-image img' ); - const updatedImageDataURL = await getDataURL( updatedImage ); - expect( initialImageDataURL ).not.toEqual( updatedImageDataURL ); - expect( updatedImageDataURL ).toMatchSnapshot(); - } ); - - it( 'Should reset dimensions on change URL', async () => { - const imageUrl = '/wp-includes/images/w-logo-blue.png'; - - await insertBlock( 'Image' ); - - // Upload an initial image. - const filename = await upload( '.wp-block-image input[type="file"]' ); - await waitForImage( filename ); - // Resize the Uploaded Image. - await openDocumentSettingsSidebar(); - await page.waitForSelector( - '[aria-label="Image size presets"] button:first-child', - { visible: true } - ); - await page.click( - '[aria-label="Image size presets"] button:first-child' - ); - - const regexBefore = new RegExp( - `\\s*
<\\/figure>\\s*` - ); - - // Check if dimensions are changed. - expect( await getEditedPostContent() ).toMatch( regexBefore ); - - // Replace uploaded image with an URL. - await clickButton( 'Replace' ); - - const [ editButton ] = await page.$x( - '//button[contains(@aria-label, "Edit")]' - ); - await editButton.click(); - - await page.waitForSelector( '.block-editor-url-input__input' ); - - // Clear the input field. Delay added to account for typing delays. - const inputField = await page.$( '.block-editor-url-input__input' ); - await inputField.click( { clickCount: 3, delay: 200 } ); - - // Replace the url. Delay added to account for typing delays. - await page.focus( '.block-editor-url-input__input' ); - await page.keyboard.type( imageUrl, { delay: 100 } ); - await page.click( '.block-editor-link-control__search-submit' ); - - const regexAfter = new RegExp( - `\\s*
\\s*` - ); - - // Check if dimensions are reset. - expect( await getEditedPostContent() ).toMatch( regexAfter ); - } ); - - it( 'should undo without broken temporary state', async () => { - await insertBlock( 'Image' ); - const fileName = await upload( '.wp-block-image input[type="file"]' ); - await waitForImage( fileName ); - await pressKeyWithModifier( 'primary', 'z' ); - // Expect an empty image block (placeholder) rather than one with a - // broken temporary URL. - expect( await getEditedPostContent() ).toMatchSnapshot(); - } ); -} ); diff --git a/test/e2e/assets/10x10_e2e_test_image_z9T8jK.png b/test/e2e/assets/10x10_e2e_test_image_z9T8jK.png new file mode 100644 index 0000000000000..a13b8d3415a5a Binary files /dev/null and b/test/e2e/assets/10x10_e2e_test_image_z9T8jK.png differ diff --git a/test/e2e/specs/editor/blocks/__snapshots__/Image-allows-changing-aspect-ratio-using-the-crop-tools-1-chromium.txt b/test/e2e/specs/editor/blocks/__snapshots__/Image-allows-changing-aspect-ratio-using-the-crop-tools-1-chromium.txt new file mode 100644 index 0000000000000..023f807dff9f3 --- /dev/null +++ b/test/e2e/specs/editor/blocks/__snapshots__/Image-allows-changing-aspect-ratio-using-the-crop-tools-1-chromium.txt @@ -0,0 +1,6 @@ +Snapshot Diff: +- First value ++ Second value + +- data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMAAwICAgICAwICAgMDAwMEBgQEBAQECAYGBQYJCAoKCQgJCQoMDwwKCw4LCQkNEQ0ODxAQERAKDBITEhATDxAQEP/bAEMBAwMDBAMECAQECBALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/AABEIAAoACgMBIgACEQEDEQH/xAAVAAEBAAAAAAAAAAAAAAAAAAAJB//EACAQAAADCQEAAAAAAAAAAAAAAAAEBQEDBgk1OHR3srX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AlMlS6eKdfnvRTgrytVTuQ86aChkqXTxTr896KcFeVqqdyHnTQH//2Q== ++ data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMAAwICAgICAwICAgMDAwMEBgQEBAQECAYGBQYJCAoKCQgJCQoMDwwKCw4LCQkNEQ0ODxAQERAKDBITEhATDxAQEP/bAEMBAwMDBAMECAQECBALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/AABEIAAYACgMBIgACEQEDEQH/xAAWAAEBAQAAAAAAAAAAAAAAAAAABwn/xAAgEAABAgUFAAAAAAAAAAAAAAAABAUBAwYJNTh0d7K1/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AJTZU1T1Tx+u9FuNXnbKrdxM7RAA/9k= \ No newline at end of file diff --git a/test/e2e/specs/editor/blocks/__snapshots__/Image-allows-rotating-using-the-crop-tools-1-chromium.txt b/test/e2e/specs/editor/blocks/__snapshots__/Image-allows-rotating-using-the-crop-tools-1-chromium.txt new file mode 100644 index 0000000000000..4409ceaca181e --- /dev/null +++ b/test/e2e/specs/editor/blocks/__snapshots__/Image-allows-rotating-using-the-crop-tools-1-chromium.txt @@ -0,0 +1,6 @@ +Snapshot Diff: +- First value ++ Second value + +- data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMAAwICAgICAwICAgMDAwMEBgQEBAQECAYGBQYJCAoKCQgJCQoMDwwKCw4LCQkNEQ0ODxAQERAKDBITEhATDxAQEP/bAEMBAwMDBAMECAQECBALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/AABEIAAoACgMBIgACEQEDEQH/xAAVAAEBAAAAAAAAAAAAAAAAAAAJB//EACAQAAADCQEAAAAAAAAAAAAAAAAEBQEDBgk1OHR3srX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AlMlS6eKdfnvRTgrytVTuQ86aChkqXTxTr896KcFeVqqdyHnTQH//2Q== ++ data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMAAwICAgICAwICAgMDAwMEBgQEBAQECAYGBQYJCAoKCQgJCQoMDwwKCw4LCQkNEQ0ODxAQERAKDBITEhATDxAQEP/bAEMBAwMDBAMECAQECBALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/AABEIAAoACgMBIgACEQEDEQH/xAAWAAEBAQAAAAAAAAAAAAAAAAAABwn/xAAhEAAAAgsBAAAAAAAAAAAAAAAABQIEBwgVGVVWk5XR1P/EABQBAQAAAAAAAAAAAAAAAAAAAAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCUyVHp7+ZVtTHwhJUenv5lW1MfCNXosa1NbzJdCLGtTW8yXQH/2Q== \ No newline at end of file diff --git a/test/e2e/specs/editor/blocks/__snapshots__/Image-allows-zooming-using-the-crop-tools-1-chromium.txt b/test/e2e/specs/editor/blocks/__snapshots__/Image-allows-zooming-using-the-crop-tools-1-chromium.txt new file mode 100644 index 0000000000000..5f53c934223d3 --- /dev/null +++ b/test/e2e/specs/editor/blocks/__snapshots__/Image-allows-zooming-using-the-crop-tools-1-chromium.txt @@ -0,0 +1,6 @@ +Snapshot Diff: +- First value ++ Second value + +- data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMAAwICAgICAwICAgMDAwMEBgQEBAQECAYGBQYJCAoKCQgJCQoMDwwKCw4LCQkNEQ0ODxAQERAKDBITEhATDxAQEP/bAEMBAwMDBAMECAQECBALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/AABEIAAoACgMBIgACEQEDEQH/xAAVAAEBAAAAAAAAAAAAAAAAAAAJB//EACAQAAADCQEAAAAAAAAAAAAAAAAEBQEDBgk1OHR3srX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AlMlS6eKdfnvRTgrytVTuQ86aChkqXTxTr896KcFeVqqdyHnTQH//2Q== ++ data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMAAwICAgICAwICAgMDAwMEBgQEBAQECAYGBQYJCAoKCQgJCQoMDwwKCw4LCQkNEQ0ODxAQERAKDBITEhATDxAQEP/bAEMBAwMDBAMECAQECBALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEP/AABEIAAUABQMBIgACEQEDEQH/xAAVAAEBAAAAAAAAAAAAAAAAAAAACP/EABoQAQABBQAAAAAAAAAAAAAAAAAEBwk4hbX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8Aqm1xgnTLddiaAD//2Q== \ No newline at end of file diff --git a/test/e2e/specs/editor/blocks/image.spec.js b/test/e2e/specs/editor/blocks/image.spec.js new file mode 100644 index 0000000000000..8304533528ab8 --- /dev/null +++ b/test/e2e/specs/editor/blocks/image.spec.js @@ -0,0 +1,549 @@ +/** + * External dependencies + */ +const path = require( 'path' ); +const fs = require( 'fs/promises' ); +const os = require( 'os' ); +const { v4: uuid } = require( 'uuid' ); +const snapshotDiff = require( 'snapshot-diff' ); + +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.use( { + imageBlockUtils: async ( { page }, use ) => { + await use( new ImageBlockUtils( { page } ) ); + }, +} ); + +test.describe( 'Image', () => { + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.deleteAllMedia(); + } ); + + test.beforeEach( async ( { pageUtils } ) => { + await pageUtils.createNewPost(); + } ); + + test.afterEach( async ( { requestUtils } ) => { + await requestUtils.deleteAllMedia(); + } ); + + test( 'can be inserted', async ( { page, pageUtils, imageBlockUtils } ) => { + await pageUtils.insertBlock( { name: 'core/image' } ); + + const imageBlock = page.locator( + 'role=document[name="Block: Image"i]' + ); + await expect( imageBlock ).toBeVisible(); + + const filename = await imageBlockUtils.upload( + imageBlock.locator( 'data-testid=form-file-upload-input' ) + ); + + const image = imageBlock.locator( 'role=img' ); + await expect( image ).toBeVisible(); + await expect( image ).toHaveAttribute( 'src', new RegExp( filename ) ); + + const regex = new RegExp( + ` +
+` + ); + expect( await pageUtils.getEditedPostContent() ).toMatch( regex ); + } ); + + test( 'should replace, reset size, and keep selection', async ( { + page, + pageUtils, + imageBlockUtils, + } ) => { + await pageUtils.insertBlock( { name: 'core/image' } ); + + const imageBlock = page.locator( + 'role=document[name="Block: Image"i]' + ); + const image = imageBlock.locator( 'role=img' ); + + const filename = await imageBlockUtils.upload( + imageBlock.locator( 'data-testid=form-file-upload-input' ) + ); + + { + await expect( image ).toBeVisible(); + await expect( image ).toHaveAttribute( + 'src', + new RegExp( filename ) + ); + + const regex = new RegExp( + ` +
+` + ); + expect( await pageUtils.getEditedPostContent() ).toMatch( regex ); + } + + { + await pageUtils.openDocumentSettingsSidebar(); + await page.click( + 'role=group[name="Image size presets"i] >> role=button[name="25%"i]' + ); + + await expect( image ).toHaveCSS( 'width', '3px' ); + await expect( image ).toHaveCSS( 'height', '3px' ); + + const regex = new RegExp( + ` +
<\\/figure> +` + ); + + expect( await pageUtils.getEditedPostContent() ).toMatch( regex ); + } + + { + await pageUtils.showBlockToolbar(); + await page.click( 'role=button[name="Replace"i]' ); + + const replacedFilename = await imageBlockUtils.upload( + page + // Ideally the menu should have the name of "Replace" but is currently missing. + // Hence, we fallback to using CSS classname instead. + .locator( '.block-editor-media-replace-flow__options' ) + .locator( 'data-testid=form-file-upload-input' ) + ); + + await expect( image ).toHaveAttribute( + 'src', + new RegExp( replacedFilename ) + ); + await expect( image ).toBeVisible(); + + const regex = new RegExp( + ` +
+` + ); + expect( await pageUtils.getEditedPostContent() ).toMatch( regex ); + } + + { + // Focus outside the block to avoid the image caption being selected + // It can happen on CI specially. + await page.click( 'role=textbox[name="Add title"i]' ); + await image.click(); + await page.keyboard.press( 'Backspace' ); + + expect( await pageUtils.getEditedPostContent() ).toBe( '' ); + } + } ); + + test( 'should place caret at end of caption after merging empty paragraph', async ( { + page, + pageUtils, + imageBlockUtils, + } ) => { + await pageUtils.insertBlock( { name: 'core/image' } ); + + const imageBlock = page.locator( + 'role=document[name="Block: Image"i]' + ); + const image = imageBlock.locator( 'role=img' ); + + const filename = await imageBlockUtils.upload( + imageBlock.locator( 'data-testid=form-file-upload-input' ) + ); + await expect( image ).toHaveAttribute( 'src', new RegExp( filename ) ); + + await page.keyboard.type( '1' ); + await page.keyboard.press( 'Enter' ); + await page.keyboard.press( 'Backspace' ); + await page.keyboard.type( '2' ); + + expect( + await page.evaluate( () => document.activeElement.innerHTML ) + ).toBe( '12' ); + } ); + + test( 'should allow soft line breaks in caption', async ( { + page, + pageUtils, + imageBlockUtils, + } ) => { + await pageUtils.insertBlock( { name: 'core/image' } ); + + const imageBlock = page.locator( + 'role=document[name="Block: Image"i]' + ); + const image = imageBlock.locator( 'role=img' ); + + const fileName = await imageBlockUtils.upload( + imageBlock.locator( 'data-testid=form-file-upload-input' ) + ); + + await expect( image ).toBeVisible(); + await expect( image ).toHaveAttribute( 'src', new RegExp( fileName ) ); + + await page.keyboard.type( '12' ); + await page.keyboard.press( 'ArrowLeft' ); + await page.keyboard.press( 'Enter' ); + + expect( + await page.evaluate( () => document.activeElement.innerHTML ) + ).toBe( '1
2' ); + } ); + + test( 'should have keyboard navigable toolbar for caption', async ( { + page, + pageUtils, + imageBlockUtils, + } ) => { + await pageUtils.insertBlock( { name: 'core/image' } ); + + const imageBlock = page.locator( + 'role=document[name="Block: Image"i]' + ); + const image = imageBlock.locator( 'role=img' ); + + const fileName = await imageBlockUtils.upload( + imageBlock.locator( 'data-testid=form-file-upload-input' ) + ); + + await expect( image ).toBeVisible(); + await expect( image ).toHaveAttribute( 'src', new RegExp( fileName ) ); + + // Navigate to More, + await pageUtils.pressKeyWithModifier( 'shift', 'Tab' ); + // Link, + await pageUtils.pressKeyWithModifier( 'shift', 'Tab' ); + // Italic, + await pageUtils.pressKeyWithModifier( 'shift', 'Tab' ); + // and finally Bold. + await pageUtils.pressKeyWithModifier( 'shift', 'Tab' ); + + await page.keyboard.press( 'Space' ); + await page.keyboard.press( 'a' ); + await page.keyboard.press( 'ArrowRight' ); + + expect( + await page.evaluate( () => document.activeElement.innerHTML ) + ).toBe( 'a' ); + } ); + + test( 'should drag and drop files into media placeholder', async ( { + page, + pageUtils, + imageBlockUtils, + } ) => { + await pageUtils.insertBlock( { name: 'core/image' } ); + + const imageBlock = page.locator( + 'role=document[name="Block: Image"i]' + ); + const image = imageBlock.locator( 'role=img' ); + + const tmpInput = await page.evaluateHandle( () => { + const input = document.createElement( 'input' ); + input.type = 'file'; + return input; + } ); + + const fileName = await imageBlockUtils.upload( tmpInput ); + + const paragraphRect = await imageBlock.boundingBox(); + const pX = paragraphRect.x + paragraphRect.width / 2; + const pY = paragraphRect.y + paragraphRect.height / 3; + + await imageBlock.evaluate( + ( element, [ input, clientX, clientY ] ) => { + const dataTransfer = new window.DataTransfer(); + dataTransfer.items.add( input.files[ 0 ] ); + const event = new window.DragEvent( 'drop', { + bubbles: true, + clientX, + clientY, + dataTransfer, + } ); + element.dispatchEvent( event ); + }, + [ tmpInput, pX, pY ] + ); + + await expect( image ).toHaveAttribute( 'src', new RegExp( fileName ) ); + } ); + + test( 'allows zooming using the crop tools', async ( { + page, + pageUtils, + imageBlockUtils, + } ) => { + // Insert the block, upload a file and crop. + await pageUtils.insertBlock( { name: 'core/image' } ); + + const imageBlock = page.locator( + 'role=document[name="Block: Image"i]' + ); + const image = imageBlock.locator( 'role=img' ); + + const filename = await imageBlockUtils.upload( + imageBlock.locator( 'data-testid=form-file-upload-input' ) + ); + + await expect( image ).toHaveAttribute( 'src', new RegExp( filename ) ); + + // Assert that the image is initially unscaled and unedited. + const initialImageSrc = await image.getAttribute( 'src' ); + const initialImageDataURL = await imageBlockUtils.getDataURL( image ); + + // Zoom in to twice the amount using the zoom input. + await pageUtils.clickBlockToolbarButton( 'Crop' ); + await pageUtils.clickBlockToolbarButton( 'Zoom' ); + await expect( + page.locator( 'role=slider[name="Zoom"i]' ) + ).toBeFocused(); + + await page.keyboard.press( 'Tab' ); + await expect( + page.locator( 'role=spinbutton[name="Zoom"i]' ) + ).toBeFocused(); + + await pageUtils.pressKeyWithModifier( 'primary', 'a' ); + await page.keyboard.type( '200' ); + await page.keyboard.press( 'Escape' ); + await pageUtils.clickBlockToolbarButton( 'Apply' ); + + // Wait for the cropping tools to disappear. + await expect( + page.locator( 'role=button[name="Apply"i]' ) + ).toBeHidden(); + + // Assert that the image is edited. + const updatedImageSrc = await image.getAttribute( 'src' ); + expect( initialImageSrc ).not.toEqual( updatedImageSrc ); + + const updatedImageDataURL = await imageBlockUtils.getDataURL( image ); + expect( initialImageDataURL ).not.toEqual( updatedImageDataURL ); + + expect( + snapshotDiff( initialImageDataURL, updatedImageDataURL ) + ).toMatchSnapshot(); + } ); + + test( 'allows changing aspect ratio using the crop tools', async ( { + page, + pageUtils, + imageBlockUtils, + } ) => { + // Insert the block, upload a file and crop. + await pageUtils.insertBlock( { name: 'core/image' } ); + + const imageBlock = page.locator( + 'role=document[name="Block: Image"i]' + ); + const image = imageBlock.locator( 'role=img' ); + + const filename = await imageBlockUtils.upload( + imageBlock.locator( 'data-testid=form-file-upload-input' ) + ); + + await expect( image ).toHaveAttribute( 'src', new RegExp( filename ) ); + + // Assert that the image is initially unscaled and unedited. + const initialImageSrc = await image.getAttribute( 'src' ); + const initialImageDataURL = await imageBlockUtils.getDataURL( image ); + + // Zoom in to twice the amount using the zoom input. + await pageUtils.clickBlockToolbarButton( 'Crop' ); + await pageUtils.clickBlockToolbarButton( 'Aspect Ratio' ); + await page.click( + 'role=menu[name="Aspect Ratio"i] >> role=menuitemradio[name="16:10"i]' + ); + await pageUtils.clickBlockToolbarButton( 'Apply' ); + + // Wait for the cropping tools to disappear. + await expect( + page.locator( 'role=button[name="Apply"i]' ) + ).toBeHidden(); + + // Assert that the image is edited. + const updatedImageSrc = await image.getAttribute( 'src' ); + const updatedImageDataURL = await imageBlockUtils.getDataURL( image ); + + expect( initialImageSrc ).not.toEqual( updatedImageSrc ); + expect( initialImageDataURL ).not.toEqual( updatedImageDataURL ); + + expect( + snapshotDiff( initialImageDataURL, updatedImageDataURL ) + ).toMatchSnapshot(); + } ); + + test( 'allows rotating using the crop tools', async ( { + page, + pageUtils, + imageBlockUtils, + } ) => { + // Insert the block, upload a file and crop. + await pageUtils.insertBlock( { name: 'core/image' } ); + + const imageBlock = page.locator( + 'role=document[name="Block: Image"i]' + ); + const image = imageBlock.locator( 'role=img' ); + + const filename = await imageBlockUtils.upload( + imageBlock.locator( 'data-testid=form-file-upload-input' ) + ); + + await expect( image ).toHaveAttribute( 'src', new RegExp( filename ) ); + + // Assert that the image is initially unscaled and unedited. + const initialImageDataURL = await imageBlockUtils.getDataURL( image ); + + // Rotate the image. + await pageUtils.clickBlockToolbarButton( 'Crop' ); + await pageUtils.clickBlockToolbarButton( 'Rotate' ); + await pageUtils.clickBlockToolbarButton( 'Apply' ); + + // Wait for the cropping tools to disappear. + await expect( + page.locator( 'role=button[name="Apply"i]' ) + ).toBeHidden(); + + // Assert that the image is edited. + const updatedImageDataURL = await imageBlockUtils.getDataURL( image ); + expect( initialImageDataURL ).not.toEqual( updatedImageDataURL ); + + expect( + snapshotDiff( initialImageDataURL, updatedImageDataURL ) + ).toMatchSnapshot(); + } ); + + test( 'Should reset dimensions on change URL', async ( { + page, + pageUtils, + imageBlockUtils, + } ) => { + await pageUtils.insertBlock( { name: 'core/image' } ); + + const imageBlock = page.locator( + 'role=document[name="Block: Image"i]' + ); + const image = imageBlock.locator( 'role=img' ); + + { + // Upload an initial image. + const filename = await imageBlockUtils.upload( + imageBlock.locator( 'data-testid=form-file-upload-input' ) + ); + await expect( image ).toHaveAttribute( + 'src', + new RegExp( filename ) + ); + + // Resize the Uploaded Image. + await pageUtils.openDocumentSettingsSidebar(); + await page.click( + 'role=group[name="Image size presets"i] >> role=button[name="25%"i]' + ); + + const regex = new RegExp( + ` +
+` + ); + + // Check if dimensions are changed. + expect( await pageUtils.getEditedPostContent() ).toMatch( regex ); + } + + { + const imageUrl = '/wp-includes/images/w-logo-blue.png'; + + // Replace uploaded image with an URL. + await pageUtils.clickBlockToolbarButton( 'Replace' ); + await page.click( 'role=button[name="Edit"i]' ); + // Replace the url. + await page.fill( 'role=combobox[name="URL"i]', imageUrl ); + await page.click( 'role=button[name="Submit"i]' ); + + const regex = new RegExp( + ` +
+` + ); + + // Check if dimensions are reset. + expect( await pageUtils.getEditedPostContent() ).toMatch( regex ); + } + } ); + + test( 'should undo without broken temporary state', async ( { + page, + pageUtils, + imageBlockUtils, + } ) => { + await pageUtils.insertBlock( { name: 'core/image' } ); + + const imageBlock = page.locator( + 'role=document[name="Block: Image"i]' + ); + const image = imageBlock.locator( 'role=img' ); + + const filename = await imageBlockUtils.upload( + imageBlock.locator( 'data-testid=form-file-upload-input' ) + ); + + await expect( image ).toHaveAttribute( 'src', new RegExp( filename ) ); + + await pageUtils.pressKeyWithModifier( 'primary', 'z' ); + + // Expect an empty image block (placeholder) rather than one with a + // broken temporary URL. + expect( await pageUtils.getEditedPostContent() ) + .toBe( ` +
+` ); + } ); +} ); + +class ImageBlockUtils { + constructor( { page } ) { + this.page = page; + + this.TEST_IMAGE_FILE_PATH = path.join( + __dirname, + '..', + '..', + '..', + 'assets', + '10x10_e2e_test_image_z9T8jK.png' + ); + } + + async upload( inputElement ) { + const tmpDirectory = await fs.mkdtemp( + path.join( os.tmpdir(), 'gutenberg-test-image-' ) + ); + const filename = uuid(); + const tmpFileName = path.join( tmpDirectory, filename + '.png' ); + await fs.copyFile( this.TEST_IMAGE_FILE_PATH, tmpFileName ); + + await inputElement.setInputFiles( tmpFileName ); + + return filename; + } + + async getDataURL( element ) { + return element.evaluate( ( node ) => { + const canvas = document.createElement( 'canvas' ); + const context = canvas.getContext( '2d' ); + canvas.width = node.width; + canvas.height = node.height; + context.drawImage( node, 0, 0 ); + return canvas.toDataURL( 'image/jpeg' ); + } ); + } +}