Blocks E2E: Use layout-based selectors in Thumbnails block tests (#47904)
* Use layout-based selectors in Thumbnails block tests * improve test readability * add changelog entry
This commit is contained in:
parent
b4efa72b07
commit
44efb7ffac
|
@ -1,418 +1,204 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { Locator, Page } from '@playwright/test';
|
import { test, expect } from '@woocommerce/e2e-utils';
|
||||||
import { test as base, expect } from '@woocommerce/e2e-utils';
|
|
||||||
|
|
||||||
/**
|
test.describe( 'Product Gallery Thumbnails block', () => {
|
||||||
* Internal dependencies
|
test.beforeEach( async ( { admin, editor, requestUtils } ) => {
|
||||||
*/
|
const template = await requestUtils.createTemplate( 'wp_template', {
|
||||||
import { ProductGalleryPage } from '../../product-gallery.page';
|
|
||||||
|
|
||||||
const blockData = {
|
|
||||||
name: 'woocommerce/product-gallery-thumbnails',
|
|
||||||
mainClass: '.wp-block-woocommerce-product-gallery-thumbnails',
|
|
||||||
selectors: {
|
|
||||||
frontend: {},
|
|
||||||
editor: {
|
|
||||||
thumbnails: '.wp-block-woocommerce-product-gallery-thumbnails',
|
|
||||||
noThumbnailsOption: 'button[data-value=off]',
|
|
||||||
leftPositionThumbnailsOption: 'button[data-value=left]',
|
|
||||||
bottomPositionThumbnailsOption: 'button[data-value=bottom]',
|
|
||||||
rightPositionThumbnailsOption: 'button[data-value=right]',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
slug: 'single-product',
|
slug: 'single-product',
|
||||||
productPage: '/product/v-neck-t-shirt/',
|
title: 'Custom Single Product',
|
||||||
};
|
content: 'placeholder',
|
||||||
|
|
||||||
const changeNumberOfThumbnailsInputValue = async (
|
|
||||||
page: Page,
|
|
||||||
numberOfThumbnailInput: Locator,
|
|
||||||
value: string
|
|
||||||
) => {
|
|
||||||
await numberOfThumbnailInput.fill( value );
|
|
||||||
await page.keyboard.press( 'Enter' );
|
|
||||||
};
|
|
||||||
|
|
||||||
const test = base.extend< { pageObject: ProductGalleryPage } >( {
|
|
||||||
pageObject: async ( { page, editor, frontendUtils }, use ) => {
|
|
||||||
const pageObject = new ProductGalleryPage( {
|
|
||||||
page,
|
|
||||||
editor,
|
|
||||||
frontendUtils,
|
|
||||||
} );
|
} );
|
||||||
await use( pageObject );
|
|
||||||
},
|
|
||||||
} );
|
|
||||||
test.describe( `${ blockData.name }`, () => {
|
|
||||||
test.beforeEach( async ( { admin, editor } ) => {
|
|
||||||
await admin.visitSiteEditor( {
|
await admin.visitSiteEditor( {
|
||||||
postId: `woocommerce/woocommerce//${ blockData.slug }`,
|
postId: template.id,
|
||||||
postType: 'wp_template',
|
postType: 'wp_template',
|
||||||
canvas: 'edit',
|
canvas: 'edit',
|
||||||
} );
|
} );
|
||||||
|
|
||||||
await editor.canvas
|
await expect( editor.canvas.getByText( 'placeholder' ) ).toBeVisible();
|
||||||
.locator( '[data-testid="product-image"]' )
|
|
||||||
.first()
|
|
||||||
.waitFor();
|
|
||||||
} );
|
|
||||||
|
|
||||||
test( 'Renders Product Gallery Thumbnails block on the editor and frontend side', async ( {
|
|
||||||
page,
|
|
||||||
editor,
|
|
||||||
pageObject,
|
|
||||||
frontendUtils,
|
|
||||||
} ) => {
|
|
||||||
await editor.insertBlock( {
|
await editor.insertBlock( {
|
||||||
name: 'woocommerce/product-gallery',
|
name: 'woocommerce/product-gallery',
|
||||||
} );
|
} );
|
||||||
|
|
||||||
const thumbnailsBlock = await pageObject.getThumbnailsBlock( {
|
|
||||||
page: 'editor',
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
await expect( thumbnailsBlock ).toBeVisible();
|
test( 'renders as expected', async ( { page, editor } ) => {
|
||||||
|
await test.step( 'in editor', async () => {
|
||||||
// Test the default (left) position of thumbnails by cross-checking:
|
const productGalleryBlock = editor.canvas.locator(
|
||||||
// - The Gallery block has the classes "is-layout-flex" and "is-nowrap".
|
|
||||||
// - The Thumbnails block has a lower index than the Large Image block.
|
|
||||||
const groupBlock = editor.canvas
|
|
||||||
.locator( '[data-type="woocommerce/product-gallery"]' )
|
|
||||||
.locator( '[data-type="core/group"]' )
|
|
||||||
.first();
|
|
||||||
|
|
||||||
const groupBlockClassAttribute = await groupBlock.getAttribute(
|
|
||||||
'class'
|
|
||||||
);
|
|
||||||
expect( groupBlockClassAttribute ).toContain( 'is-layout-flex' );
|
|
||||||
expect( groupBlockClassAttribute ).toContain( 'is-nowrap' );
|
|
||||||
|
|
||||||
const isThumbnailsBlockEarlier = await editor.isBlockEarlierThan(
|
|
||||||
groupBlock,
|
|
||||||
'woocommerce/product-gallery-thumbnails',
|
|
||||||
'core/group'
|
|
||||||
);
|
|
||||||
|
|
||||||
expect( isThumbnailsBlockEarlier ).toBe( true );
|
|
||||||
|
|
||||||
await editor.saveSiteEditorEntities();
|
|
||||||
|
|
||||||
await page.goto( blockData.productPage );
|
|
||||||
|
|
||||||
const groupBlockFrontend = (
|
|
||||||
await frontendUtils.getBlockByClassWithParent(
|
|
||||||
'wp-block-group',
|
|
||||||
'woocommerce/product-gallery'
|
|
||||||
)
|
|
||||||
).first();
|
|
||||||
|
|
||||||
const groupBlockFrontendClassAttribute =
|
|
||||||
await groupBlockFrontend.getAttribute( 'class' );
|
|
||||||
expect( groupBlockFrontendClassAttribute ).toContain(
|
|
||||||
'is-layout-flex'
|
|
||||||
);
|
|
||||||
expect( groupBlockFrontendClassAttribute ).toContain( 'is-nowrap' );
|
|
||||||
|
|
||||||
const isThumbnailsFrontendBlockEarlier =
|
|
||||||
await frontendUtils.isBlockEarlierThanGroupBlock(
|
|
||||||
groupBlockFrontend,
|
|
||||||
'woocommerce/product-gallery-thumbnails'
|
|
||||||
);
|
|
||||||
|
|
||||||
expect( isThumbnailsFrontendBlockEarlier ).toBe( true );
|
|
||||||
} );
|
|
||||||
|
|
||||||
test.describe( `${ blockData.name } Settings`, () => {
|
|
||||||
test( 'Hide correctly the thumbnails', async ( { page, editor } ) => {
|
|
||||||
await editor.insertBlock( {
|
|
||||||
name: 'woocommerce/product-gallery',
|
|
||||||
} );
|
|
||||||
|
|
||||||
await editor.canvas
|
|
||||||
.locator( `[data-type="${ blockData.name }"]` )
|
|
||||||
.click();
|
|
||||||
|
|
||||||
await editor.openDocumentSettingsSidebar();
|
|
||||||
|
|
||||||
await page
|
|
||||||
.locator( blockData.selectors.editor.noThumbnailsOption )
|
|
||||||
.click();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.locator( blockData.selectors.editor.thumbnails )
|
|
||||||
).toBeHidden();
|
|
||||||
|
|
||||||
await editor.saveSiteEditorEntities();
|
|
||||||
} );
|
|
||||||
|
|
||||||
// We can test the left position of thumbnails by cross-checking:
|
|
||||||
// - The Gallery block has the classes "is-layout-flex" and "is-nowrap".
|
|
||||||
// - The Thumbnails block has a lower index than the Large Image block.
|
|
||||||
test( 'Position thumbnails on the left of the large image', async ( {
|
|
||||||
page,
|
|
||||||
editor,
|
|
||||||
frontendUtils,
|
|
||||||
} ) => {
|
|
||||||
// Currently we are adding the block under the legacy Product Image Gallery block, but in the future we have to add replace the product gallery block with this block.
|
|
||||||
const parentBlock = await editor.getBlockByName(
|
|
||||||
'woocommerce/product-image-gallery'
|
|
||||||
);
|
|
||||||
const clientId =
|
|
||||||
( await parentBlock.getAttribute( 'data-block' ) ) ?? '';
|
|
||||||
const parentClientId =
|
|
||||||
( await editor.getBlockRootClientId( clientId ) ) ?? '';
|
|
||||||
|
|
||||||
await editor.selectBlocks( parentBlock );
|
|
||||||
await editor.insertBlock(
|
|
||||||
{ name: 'woocommerce/product-gallery' },
|
|
||||||
{ clientId: parentClientId }
|
|
||||||
);
|
|
||||||
await ( await editor.getBlockByName( blockData.name ) ).click();
|
|
||||||
|
|
||||||
await editor.openDocumentSettingsSidebar();
|
|
||||||
await page
|
|
||||||
.locator(
|
|
||||||
blockData.selectors.editor.leftPositionThumbnailsOption
|
|
||||||
)
|
|
||||||
.click();
|
|
||||||
|
|
||||||
const groupBlock = editor.canvas
|
|
||||||
.locator( '[data-type="woocommerce/product-gallery"]' )
|
|
||||||
.locator( '[data-type="core/group"]' )
|
|
||||||
.first();
|
|
||||||
|
|
||||||
const groupBlockClassAttribute = await groupBlock.getAttribute(
|
|
||||||
'class'
|
|
||||||
);
|
|
||||||
expect( groupBlockClassAttribute ).toContain( 'is-layout-flex' );
|
|
||||||
expect( groupBlockClassAttribute ).toContain( 'is-nowrap' );
|
|
||||||
|
|
||||||
const isThumbnailsBlockEarlier = await editor.isBlockEarlierThan(
|
|
||||||
groupBlock,
|
|
||||||
'woocommerce/product-gallery-thumbnails',
|
|
||||||
'core/group'
|
|
||||||
);
|
|
||||||
|
|
||||||
expect( isThumbnailsBlockEarlier ).toBe( true );
|
|
||||||
|
|
||||||
await editor.saveSiteEditorEntities();
|
|
||||||
|
|
||||||
await page.goto( blockData.productPage );
|
|
||||||
|
|
||||||
const groupBlockFrontend = (
|
|
||||||
await frontendUtils.getBlockByClassWithParent(
|
|
||||||
'wp-block-group',
|
|
||||||
'woocommerce/product-gallery'
|
|
||||||
)
|
|
||||||
).first();
|
|
||||||
|
|
||||||
const groupBlockFrontendClassAttribute =
|
|
||||||
await groupBlockFrontend.getAttribute( 'class' );
|
|
||||||
expect( groupBlockFrontendClassAttribute ).toContain(
|
|
||||||
'is-layout-flex'
|
|
||||||
);
|
|
||||||
expect( groupBlockFrontendClassAttribute ).toContain( 'is-nowrap' );
|
|
||||||
|
|
||||||
const isThumbnailsFrontendBlockEarlier =
|
|
||||||
await frontendUtils.isBlockEarlierThanGroupBlock(
|
|
||||||
groupBlockFrontend,
|
|
||||||
'woocommerce/product-gallery-thumbnails'
|
|
||||||
);
|
|
||||||
|
|
||||||
expect( isThumbnailsFrontendBlockEarlier ).toBe( true );
|
|
||||||
} );
|
|
||||||
|
|
||||||
// We can test the bottom position of thumbnails by cross-checking:
|
|
||||||
// - The Gallery block has the classes "is-layout-flex" and "is-vertical".
|
|
||||||
// - The Thumbnails block has a higher index than the Large Image block.
|
|
||||||
test( 'Position thumbnails on the bottom of the large image', async ( {
|
|
||||||
page,
|
|
||||||
editor,
|
|
||||||
frontendUtils,
|
|
||||||
} ) => {
|
|
||||||
// Currently we are adding the block under the legacy Product Image Gallery block, but in the future we have to add replace the product gallery block with this block.
|
|
||||||
const parentBlock = await editor.getBlockByName(
|
|
||||||
'woocommerce/product-image-gallery'
|
|
||||||
);
|
|
||||||
const clientId =
|
|
||||||
( await parentBlock.getAttribute( 'data-block' ) ) ?? '';
|
|
||||||
const parentClientId =
|
|
||||||
( await editor.getBlockRootClientId( clientId ) ) ?? '';
|
|
||||||
|
|
||||||
await editor.selectBlocks( parentBlock );
|
|
||||||
await editor.insertBlock(
|
|
||||||
{ name: 'woocommerce/product-gallery' },
|
|
||||||
{ clientId: parentClientId }
|
|
||||||
);
|
|
||||||
await ( await editor.getBlockByName( blockData.name ) ).click();
|
|
||||||
|
|
||||||
await editor.openDocumentSettingsSidebar();
|
|
||||||
await page
|
|
||||||
.locator(
|
|
||||||
blockData.selectors.editor.bottomPositionThumbnailsOption
|
|
||||||
)
|
|
||||||
.click();
|
|
||||||
|
|
||||||
const groupBlock = editor.canvas
|
|
||||||
.locator( '[data-type="woocommerce/product-gallery"]' )
|
|
||||||
.locator( '[data-type="core/group"]' )
|
|
||||||
.first();
|
|
||||||
|
|
||||||
const groupBlockClassAttribute = await groupBlock.getAttribute(
|
|
||||||
'class'
|
|
||||||
);
|
|
||||||
expect( groupBlockClassAttribute ).toContain( 'is-layout-flex' );
|
|
||||||
expect( groupBlockClassAttribute ).toContain( 'is-vertical' );
|
|
||||||
|
|
||||||
const isThumbnailsBlockEarlier = await editor.isBlockEarlierThan(
|
|
||||||
groupBlock,
|
|
||||||
'woocommerce/product-gallery-thumbnails',
|
|
||||||
'core/group'
|
|
||||||
);
|
|
||||||
|
|
||||||
expect( isThumbnailsBlockEarlier ).toBe( false );
|
|
||||||
|
|
||||||
await editor.saveSiteEditorEntities();
|
|
||||||
await page.goto( blockData.productPage );
|
|
||||||
|
|
||||||
const groupBlockFrontend = (
|
|
||||||
await frontendUtils.getBlockByClassWithParent(
|
|
||||||
'wp-block-group',
|
|
||||||
'woocommerce/product-gallery'
|
|
||||||
)
|
|
||||||
).first();
|
|
||||||
|
|
||||||
const groupBlockFrontendClassAttribute =
|
|
||||||
await groupBlockFrontend.getAttribute( 'class' );
|
|
||||||
expect( groupBlockFrontendClassAttribute ).toContain(
|
|
||||||
'is-layout-flex'
|
|
||||||
);
|
|
||||||
expect( groupBlockFrontendClassAttribute ).toContain(
|
|
||||||
'is-vertical'
|
|
||||||
);
|
|
||||||
|
|
||||||
const isThumbnailsFrontendBlockEarlier =
|
|
||||||
await frontendUtils.isBlockEarlierThanGroupBlock(
|
|
||||||
groupBlockFrontend,
|
|
||||||
'woocommerce/product-gallery-thumbnails'
|
|
||||||
);
|
|
||||||
|
|
||||||
expect( isThumbnailsFrontendBlockEarlier ).toBe( false );
|
|
||||||
} );
|
|
||||||
|
|
||||||
// We can test the right position of thumbnails by cross-checking:
|
|
||||||
// - The Gallery block has the classes "is-layout-flex" and "is-nowrap".
|
|
||||||
// - The Thumbnails block has a higher index than the Large Image block.
|
|
||||||
test( 'Position thumbnails on the right of the large image', async ( {
|
|
||||||
page,
|
|
||||||
editor,
|
|
||||||
frontendUtils,
|
|
||||||
} ) => {
|
|
||||||
// Currently we are adding the block under the legacy Product Image Gallery block, but in the future we have to add replace the product gallery block with this block.
|
|
||||||
const parentBlock = await editor.getBlockByName(
|
|
||||||
'woocommerce/product-image-gallery'
|
|
||||||
);
|
|
||||||
const clientId =
|
|
||||||
( await parentBlock.getAttribute( 'data-block' ) ) ?? '';
|
|
||||||
const parentClientId =
|
|
||||||
( await editor.getBlockRootClientId( clientId ) ) ?? '';
|
|
||||||
|
|
||||||
await editor.selectBlocks( parentBlock );
|
|
||||||
await editor.insertBlock(
|
|
||||||
{ name: 'woocommerce/product-gallery' },
|
|
||||||
{ clientId: parentClientId }
|
|
||||||
);
|
|
||||||
await ( await editor.getBlockByName( blockData.name ) ).click();
|
|
||||||
|
|
||||||
await editor.openDocumentSettingsSidebar();
|
|
||||||
await page
|
|
||||||
.locator(
|
|
||||||
blockData.selectors.editor.rightPositionThumbnailsOption
|
|
||||||
)
|
|
||||||
.click();
|
|
||||||
|
|
||||||
const groupBlock = editor.canvas
|
|
||||||
.locator( '[data-type="woocommerce/product-gallery"]' )
|
|
||||||
.locator( '[data-type="core/group"]' )
|
|
||||||
.first();
|
|
||||||
|
|
||||||
const groupBlockClassAttribute = await groupBlock.getAttribute(
|
|
||||||
'class'
|
|
||||||
);
|
|
||||||
expect( groupBlockClassAttribute ).toContain( 'is-layout-flex' );
|
|
||||||
expect( groupBlockClassAttribute ).toContain( 'is-nowrap' );
|
|
||||||
|
|
||||||
const isThumbnailsBlockEarlier = await editor.isBlockEarlierThan(
|
|
||||||
groupBlock,
|
|
||||||
'woocommerce/product-gallery-thumbnails',
|
|
||||||
'core/group'
|
|
||||||
);
|
|
||||||
|
|
||||||
expect( isThumbnailsBlockEarlier ).toBe( false );
|
|
||||||
|
|
||||||
await editor.saveSiteEditorEntities();
|
|
||||||
await page.goto( blockData.productPage );
|
|
||||||
|
|
||||||
const groupBlockFrontend = (
|
|
||||||
await frontendUtils.getBlockByClassWithParent(
|
|
||||||
'wp-block-group',
|
|
||||||
'woocommerce/product-gallery'
|
|
||||||
)
|
|
||||||
).first();
|
|
||||||
|
|
||||||
const groupBlockFrontendClassAttribute =
|
|
||||||
await groupBlockFrontend.getAttribute( 'class' );
|
|
||||||
expect( groupBlockFrontendClassAttribute ).toContain(
|
|
||||||
'is-layout-flex'
|
|
||||||
);
|
|
||||||
expect( groupBlockFrontendClassAttribute ).toContain( 'is-nowrap' );
|
|
||||||
|
|
||||||
const isThumbnailsFrontendBlockEarlier =
|
|
||||||
await frontendUtils.isBlockEarlierThanGroupBlock(
|
|
||||||
groupBlockFrontend,
|
|
||||||
'woocommerce/product-gallery-thumbnails'
|
|
||||||
);
|
|
||||||
|
|
||||||
expect( isThumbnailsFrontendBlockEarlier ).toBe( false );
|
|
||||||
} );
|
|
||||||
|
|
||||||
test( 'Ensure entered Number of Thumbnails rounds to integer', async ( {
|
|
||||||
page,
|
|
||||||
editor,
|
|
||||||
} ) => {
|
|
||||||
await editor.insertBlock( {
|
|
||||||
name: 'woocommerce/product-gallery',
|
|
||||||
} );
|
|
||||||
|
|
||||||
await editor.selectBlocks(
|
|
||||||
'[data-type="woocommerce/product-gallery"]'
|
'[data-type="woocommerce/product-gallery"]'
|
||||||
);
|
);
|
||||||
|
|
||||||
await editor.openDocumentSettingsSidebar();
|
await expect(
|
||||||
|
productGalleryBlock.locator(
|
||||||
|
'[data-type="woocommerce/product-gallery-thumbnails"]'
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
const numberOfThumbnailInput = page.getByRole( 'spinbutton', {
|
await expect(
|
||||||
|
productGalleryBlock.locator(
|
||||||
|
`[data-type="woocommerce/product-gallery-thumbnails"]:left-of(
|
||||||
|
[data-type="woocommerce/product-gallery-large-image"]
|
||||||
|
)`
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await editor.saveSiteEditorEntities();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'in frontend', async () => {
|
||||||
|
await page.goto( '/product/v-neck-t-shirt/' );
|
||||||
|
const productGalleryBlock = page.locator(
|
||||||
|
'[data-block-name="woocommerce/product-gallery"]'
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
productGalleryBlock.locator(
|
||||||
|
'[data-block-name="woocommerce/product-gallery-thumbnails"]'
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
productGalleryBlock.locator(
|
||||||
|
`[data-block-name="woocommerce/product-gallery-thumbnails"]:left-of(
|
||||||
|
[data-block-name="woocommerce/product-gallery-large-image"]
|
||||||
|
)`
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.describe( 'settings', () => {
|
||||||
|
test( 'hides thumbnails', async ( { page, editor } ) => {
|
||||||
|
await test.step( 'in editor', async () => {
|
||||||
|
const productGalleryBlock = editor.canvas.locator(
|
||||||
|
'[data-type="woocommerce/product-gallery"]'
|
||||||
|
);
|
||||||
|
const thumbailsBlock = productGalleryBlock.locator(
|
||||||
|
'[data-type="woocommerce/product-gallery-thumbnails"]'
|
||||||
|
);
|
||||||
|
await expect( thumbailsBlock ).toBeVisible();
|
||||||
|
|
||||||
|
await editor.selectBlocks( thumbailsBlock );
|
||||||
|
|
||||||
|
await editor.openDocumentSettingsSidebar();
|
||||||
|
await page
|
||||||
|
.getByLabel( 'Editor settings' )
|
||||||
|
.locator( 'button[data-value="off"]' )
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect( thumbailsBlock ).toBeHidden();
|
||||||
|
|
||||||
|
await editor.saveSiteEditorEntities();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'in frontend', async () => {
|
||||||
|
await page.goto( '/product/v-neck-t-shirt/' );
|
||||||
|
|
||||||
|
const productGalleryBlock = page.locator(
|
||||||
|
'[data-block-name="woocommerce/product-gallery"]'
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
productGalleryBlock.locator(
|
||||||
|
'[data-block-name="woocommerce/product-gallery-large-image"]:visible'
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
productGalleryBlock.locator(
|
||||||
|
'[data-block-name="woocommerce/product-gallery-thumbnails"]'
|
||||||
|
)
|
||||||
|
).toBeHidden();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
for ( const position of [ 'left', 'bottom', 'right' ] ) {
|
||||||
|
test( `positions thumbnails to the ${ position }`, async ( {
|
||||||
|
page,
|
||||||
|
editor,
|
||||||
|
} ) => {
|
||||||
|
const layoutClass = {
|
||||||
|
left: 'left-of',
|
||||||
|
bottom: 'below',
|
||||||
|
right: 'right-of',
|
||||||
|
}[ position ];
|
||||||
|
|
||||||
|
await test.step( 'in editor', async () => {
|
||||||
|
const productGalleryBlock = editor.canvas.locator(
|
||||||
|
'[data-type="woocommerce/product-gallery"]'
|
||||||
|
);
|
||||||
|
|
||||||
|
await editor.selectBlocks( productGalleryBlock );
|
||||||
|
await editor.openDocumentSettingsSidebar();
|
||||||
|
await page
|
||||||
|
.getByLabel( 'Editor settings' )
|
||||||
|
.locator( `button[data-value="${ position }"]` )
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
productGalleryBlock.locator(
|
||||||
|
`[data-type="woocommerce/product-gallery-thumbnails"]:${ layoutClass }(
|
||||||
|
[data-type="woocommerce/product-gallery-large-image"]
|
||||||
|
)`
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await editor.saveSiteEditorEntities();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'in frontend', async () => {
|
||||||
|
await page.goto( '/product/v-neck-t-shirt/' );
|
||||||
|
const productGalleryBlock = page.locator(
|
||||||
|
'[data-block-name="woocommerce/product-gallery"]'
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
productGalleryBlock.locator(
|
||||||
|
'[data-block-name="woocommerce/product-gallery-thumbnails"]'
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
productGalleryBlock.locator(
|
||||||
|
`[data-block-name="woocommerce/product-gallery-thumbnails"]:${ layoutClass }(
|
||||||
|
[data-block-name="woocommerce/product-gallery-large-image"]
|
||||||
|
)`
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
test( 'rounds the number of thumbnails to integer', async ( {
|
||||||
|
page,
|
||||||
|
editor,
|
||||||
|
} ) => {
|
||||||
|
const productGalleryBlock = editor.canvas.locator(
|
||||||
|
'[data-type="woocommerce/product-gallery"]'
|
||||||
|
);
|
||||||
|
|
||||||
|
await editor.selectBlocks( productGalleryBlock );
|
||||||
|
|
||||||
|
await editor.openDocumentSettingsSidebar();
|
||||||
|
const numberOfThumbnailInput = page
|
||||||
|
.getByLabel( 'Editor settings' )
|
||||||
|
.getByRole( 'spinbutton', {
|
||||||
name: 'Number of Thumbnails',
|
name: 'Number of Thumbnails',
|
||||||
} );
|
} );
|
||||||
|
|
||||||
await changeNumberOfThumbnailsInputValue(
|
await numberOfThumbnailInput.fill( '4.2' );
|
||||||
page,
|
await page.keyboard.press( 'Enter' );
|
||||||
numberOfThumbnailInput,
|
|
||||||
'4.2'
|
|
||||||
);
|
|
||||||
|
|
||||||
const numberOfThumbnailsOnScreen = editor.canvas.locator(
|
const numberOfThumbnailsOnScreen = productGalleryBlock.locator(
|
||||||
'.wc-block-product-gallery-thumbnails__thumbnail'
|
'.wc-block-product-gallery-thumbnails__thumbnail'
|
||||||
);
|
);
|
||||||
|
|
||||||
await expect( numberOfThumbnailsOnScreen ).toHaveCount( 4 );
|
await expect( numberOfThumbnailsOnScreen ).toHaveCount( 4 );
|
||||||
|
|
||||||
await changeNumberOfThumbnailsInputValue(
|
await numberOfThumbnailInput.fill( '4.7' );
|
||||||
page,
|
await page.keyboard.press( 'Enter' );
|
||||||
numberOfThumbnailInput,
|
|
||||||
'4.7'
|
|
||||||
);
|
|
||||||
|
|
||||||
await expect( numberOfThumbnailsOnScreen ).toHaveCount( 5 );
|
await expect( numberOfThumbnailsOnScreen ).toHaveCount( 5 );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -65,50 +65,6 @@ export class Editor extends CoreEditor {
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
async isBlockEarlierThan< T >(
|
|
||||||
containerBlock: T,
|
|
||||||
firstBlock: string,
|
|
||||||
secondBlock: string
|
|
||||||
) {
|
|
||||||
const container =
|
|
||||||
containerBlock instanceof Function
|
|
||||||
? await containerBlock()
|
|
||||||
: containerBlock;
|
|
||||||
|
|
||||||
if ( ! container ) {
|
|
||||||
throw new Error( 'Container block not found.' );
|
|
||||||
}
|
|
||||||
|
|
||||||
const childBlocks = container.locator( ':scope > .wp-block' );
|
|
||||||
|
|
||||||
let firstBlockIndex = -1;
|
|
||||||
let secondBlockIndex = -1;
|
|
||||||
|
|
||||||
for ( let i = 0; i < ( await childBlocks.count() ); i++ ) {
|
|
||||||
const blockName = await childBlocks
|
|
||||||
.nth( i )
|
|
||||||
.getAttribute( 'data-type' );
|
|
||||||
|
|
||||||
if ( blockName === firstBlock ) {
|
|
||||||
firstBlockIndex = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( blockName === secondBlock ) {
|
|
||||||
secondBlockIndex = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( firstBlockIndex !== -1 && secondBlockIndex !== -1 ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( firstBlockIndex === -1 || secondBlockIndex === -1 ) {
|
|
||||||
throw new Error( 'Both blocks must exist within the editor' );
|
|
||||||
}
|
|
||||||
|
|
||||||
return firstBlockIndex < secondBlockIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
async transformIntoBlocks() {
|
async transformIntoBlocks() {
|
||||||
// Select the block, so the button is visible.
|
// Select the block, so the button is visible.
|
||||||
const block = this.canvas
|
const block = this.canvas
|
||||||
|
|
|
@ -21,15 +21,6 @@ export class FrontendUtils {
|
||||||
return this.page.locator( selector );
|
return this.page.locator( selector );
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBlockByClassWithParent( blockClass: string, parentName: string ) {
|
|
||||||
const parentBlock = await this.getBlockByName( parentName );
|
|
||||||
if ( ! parentBlock ) {
|
|
||||||
throw new Error( `Parent block "${ parentName }" not found.` );
|
|
||||||
}
|
|
||||||
const block = parentBlock.locator( `.${ blockClass }` );
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
async addToCart( itemName = '' ) {
|
async addToCart( itemName = '' ) {
|
||||||
await this.page.waitForLoadState( 'domcontentloaded' );
|
await this.page.waitForLoadState( 'domcontentloaded' );
|
||||||
if ( itemName !== '' ) {
|
if ( itemName !== '' ) {
|
||||||
|
@ -99,93 +90,6 @@ export class FrontendUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async isBlockEarlierThan< T >(
|
|
||||||
containerBlock: T,
|
|
||||||
firstBlock: string,
|
|
||||||
secondBlock: string
|
|
||||||
) {
|
|
||||||
const container =
|
|
||||||
containerBlock instanceof Function
|
|
||||||
? await containerBlock()
|
|
||||||
: containerBlock;
|
|
||||||
|
|
||||||
if ( ! container ) {
|
|
||||||
throw new Error( 'Container block not found.' );
|
|
||||||
}
|
|
||||||
|
|
||||||
const childBlocks = container.locator( '[data-block-name]' );
|
|
||||||
|
|
||||||
let firstBlockIndex = -1;
|
|
||||||
let secondBlockIndex = -1;
|
|
||||||
|
|
||||||
for ( let i = 0; i < ( await childBlocks.count() ); i++ ) {
|
|
||||||
const blockName = await childBlocks
|
|
||||||
.nth( i )
|
|
||||||
.getAttribute( 'data-block-name' );
|
|
||||||
|
|
||||||
if ( blockName === firstBlock ) {
|
|
||||||
firstBlockIndex = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( blockName === secondBlock ) {
|
|
||||||
secondBlockIndex = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( firstBlockIndex !== -1 && secondBlockIndex !== -1 ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( firstBlockIndex === -1 || secondBlockIndex === -1 ) {
|
|
||||||
throw new Error( 'Both blocks must exist within the editor' );
|
|
||||||
}
|
|
||||||
|
|
||||||
return firstBlockIndex < secondBlockIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
async isBlockEarlierThanGroupBlock(
|
|
||||||
containerBlock: Locator,
|
|
||||||
firstBlock: string
|
|
||||||
) {
|
|
||||||
if ( ! containerBlock ) {
|
|
||||||
throw new Error( 'Container block not found.' );
|
|
||||||
}
|
|
||||||
|
|
||||||
const childBlocks: Locator = containerBlock.locator( '> div' );
|
|
||||||
|
|
||||||
let firstBlockIndex = -1;
|
|
||||||
let secondBlockIndex = -1;
|
|
||||||
|
|
||||||
for ( let i = 0; i < ( await childBlocks.count() ); i++ ) {
|
|
||||||
const blockName = await childBlocks
|
|
||||||
.nth( i )
|
|
||||||
.getAttribute( 'data-block-name' );
|
|
||||||
const isGroupBlock = await childBlocks
|
|
||||||
.nth( i )
|
|
||||||
.evaluate( ( node ) =>
|
|
||||||
node.classList.contains( 'wp-block-group' )
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( blockName === firstBlock ) {
|
|
||||||
firstBlockIndex = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( isGroupBlock ) {
|
|
||||||
secondBlockIndex = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( firstBlockIndex !== -1 && secondBlockIndex !== -1 ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( firstBlockIndex === -1 || secondBlockIndex === -1 ) {
|
|
||||||
throw new Error( 'Both blocks must exist within the editor' );
|
|
||||||
}
|
|
||||||
|
|
||||||
return firstBlockIndex < secondBlockIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Playwright selectText causes flaky tests when running on local
|
* Playwright selectText causes flaky tests when running on local
|
||||||
* development machine. This method is more reliable on both environments.
|
* development machine. This method is more reliable on both environments.
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: dev
|
||||||
|
|
||||||
|
Blocks E2E: Remove confusing utilities in favor of native locator functionality.
|
Loading…
Reference in New Issue