[e2e tests] Add tests for product images (#43775)

* Import media on environment setup

* Add product-images.spec with one complete test and all other skeleton tests

* Add changelog

* Implement can update the product image

* Implement can delete the product image

* Implement can delete the product image

* Skip not implemented test

* Merge fixtures

* Add productWithImage fixture

* Remove unused variable `api`

* Partial implementation of can create a product gallery

* Check the image gallery in store frontend

* Added `can update a product gallery` test

* Run all tests

* Search for image in media library

* Check that the remove gallery image is not displayed

* Add repeatEach configuration

* eslint formatting

* Extract some repeating steps into a function

* Update check for thumbnail

* Fix test image name
This commit is contained in:
Adrian Moldovan 2024-01-23 23:31:22 +02:00 committed by GitHub
parent c7d4c88270
commit d66a48e8e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 301 additions and 5 deletions

View File

@ -1,6 +1,8 @@
{
"phpVersion": "7.4",
"plugins": [ "." ],
"plugins": [
"."
],
"config": {
"JETPACK_AUTOLOAD_DEV": true,
"WP_DEBUG_LOG": true,
@ -11,7 +13,8 @@
"wp-cli.yml": "./tests/wp-cli.yml",
"wp-content/plugins/filter-setter.php": "./tests/e2e-pw/bin/filter-setter.php",
"wp-content/plugins/process-waiting-actions.php": "./tests/e2e-pw/bin/process-waiting-actions.php",
"wp-content/plugins/test-helper-apis.php": "./tests/e2e-pw/bin/test-helper-apis.php"
"wp-content/plugins/test-helper-apis.php": "./tests/e2e-pw/bin/test-helper-apis.php",
"test-data/images/": "./tests/e2e-pw/test-data/images/"
},
"lifecycleScripts": {
"afterStart": "./tests/e2e-pw/bin/test-env-setup.sh",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
E2E tests: Add checks for product images

View File

@ -37,3 +37,7 @@ if [ $ENABLE_TRACKING == 1 ]; then
echo -e 'Enable tracking\n'
wp-env run tests-cli wp option update woocommerce_allow_tracking 'yes'
fi
echo -e 'Upload test images \n'
wp-env run tests-cli wp media import './test-data/images/image-01.png' './test-data/images/image-02.png' './test-data/images/image-03.png'

View File

@ -8,6 +8,7 @@ const {
DEFAULT_TIMEOUT_OVERRIDE,
E2E_MAX_FAILURES,
PLAYWRIGHT_HTML_REPORT,
REPEAT_EACH,
} = process.env;
const config = {
@ -20,6 +21,7 @@ const config = {
globalTeardown: require.resolve( './global-teardown' ),
testDir: 'tests',
retries: 2,
repeatEach: REPEAT_EACH ? Number( REPEAT_EACH ) : 1,
workers: CI ? 1 : 4,
reporter: [
[ 'list' ],

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -4,7 +4,7 @@ const wcApi = require('@woocommerce/woocommerce-rest-api').default;
baseTest.describe('Products > Delete Product', () => {
baseTest.use({storageState: process.env.ADMINSTATE});
const apiFixture = baseTest.extend({
const test = baseTest.extend({
api: async ({baseURL}, use) => {
const api = new wcApi({
url: baseURL,
@ -21,9 +21,7 @@ baseTest.describe('Products > Delete Product', () => {
await use(api);
},
});
const test = apiFixture.extend({
product: async ({api}, use) => {
const product = {
id: 0,

View File

@ -0,0 +1,285 @@
const { test: baseTest, expect } = require( '@playwright/test' );
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
async function addImageFromLibrary( page, imageName, actionButtonName ) {
await page.getByRole( 'tab', { name: 'Media Library' } ).click();
await page.getByRole( 'searchbox', { name: 'Search' } ).fill( imageName );
const imageLocator = page.getByLabel( imageName ).nth( 0 );
await imageLocator.click();
const dataId = await imageLocator.getAttribute( 'data-id' );
await expect( imageLocator ).toBeChecked();
await page.getByRole( 'button', { name: actionButtonName } ).click();
return dataId;
}
baseTest.describe( 'Products > Product Images', () => {
baseTest.use( { storageState: process.env.ADMINSTATE } );
const test = baseTest.extend( {
api: async ( { baseURL }, use ) => {
const api = new wcApi( {
url: baseURL,
consumerKey: process.env.CONSUMER_KEY,
consumerSecret: process.env.CONSUMER_SECRET,
version: 'wc/v3',
} );
await use( api );
},
product: async ( { api }, use ) => {
let product = {
id: 0,
name: `Product ${ Date.now() }`,
type: 'simple',
regular_price: '12.99',
sale_price: '11.59',
};
await api.post( 'products', product ).then( ( response ) => {
product = response.data;
} );
await use( product );
// Cleanup
await api.delete( `products/${ product.id }`, { force: true } );
},
productWithImage: async ( { api, product }, use ) => {
let productWithImage;
await api
.put( `products/${ product.id }`, {
images: [
{
src: 'http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_2_front.jpg',
},
],
} )
.then( ( response ) => {
productWithImage = response.data;
} );
await use( productWithImage );
},
productWithGallery: async ( { api, product }, use ) => {
let productWithGallery;
await api
.put( `products/${ product.id }`, {
images: [
{
src: 'http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_2_front.jpg',
},
{
src: 'http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_2_back.jpg',
},
{
src: 'http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_3_front.jpg',
},
],
} )
.then( ( response ) => {
productWithGallery = response.data;
} );
await use( productWithGallery );
},
} );
test( 'can set product image', async ( { page, product } ) => {
await test.step( 'Navigate to product edit page', async () => {
await page.goto(
`wp-admin/post.php?post=${ product.id }&action=edit`
);
} );
await test.step( 'Set product image', async () => {
await page
.getByRole( 'link', { name: 'Set product image' } )
.click();
await addImageFromLibrary( page, 'image-01', 'Set product image' );
// Wait for the product image thumbnail to be updated.
// Clicking the "Update" button before this happens will not update the image.
// Use src* (contains) instead of src$ (ends with) to match duplicated images, like image-01-1.png
await expect(
page.locator( '#set-post-thumbnail img[src*="image-01"]' )
).toBeVisible();
await page.getByRole( 'button', { name: 'Update' } ).click();
} );
await test.step( 'Verify product image was set', async () => {
// Verify product was updated
await expect( page.getByText( 'Product updated.' ) ).toBeVisible();
// Verify image in store frontend
await page.goto( product.permalink );
await expect( page.getByTitle( `image-01` ) ).toBeVisible();
} );
} );
test( 'can update the product image', async ( {
page,
productWithImage,
} ) => {
await test.step( 'Navigate to product edit page', async () => {
await page.goto(
`wp-admin/post.php?post=${ productWithImage.id }&action=edit`
);
} );
await test.step( 'Update product image', async () => {
await page.locator( '#set-post-thumbnail' ).click();
await addImageFromLibrary( page, 'image-02', 'Set product image' );
// Wait for the product image thumbnail to be updated.
// Clicking the "Update" button before this happens will not update the image.
// Use src* (contains) instead of src$ (ends with) to match duplicated images, like image-01-1.png
await expect(
page.locator( '#set-post-thumbnail img[src*="image-02"]' )
).toBeVisible();
await page.getByRole( 'button', { name: 'Update' } ).click();
} );
await test.step( 'Verify product image was set', async () => {
// Verify product was updated
await expect( page.getByText( 'Product updated.' ) ).toBeVisible();
// Verify image in store frontend
await page.goto( productWithImage.permalink );
await expect( page.getByTitle( `image-02` ) ).toBeVisible();
} );
} );
test( 'can delete the product image', async ( {
page,
productWithImage,
} ) => {
await test.step( 'Navigate to product edit page', async () => {
await page.goto(
`wp-admin/post.php?post=${ productWithImage.id }&action=edit`
);
} );
await test.step( 'Remove product image', async () => {
await page
.getByRole( 'link', { name: 'Remove product image' } )
.click();
await expect(
page.getByRole( 'link', { name: 'Set product image' } )
).toBeVisible();
await page.getByRole( 'button', { name: 'Update' } ).click();
} );
await test.step( 'Verify product image was removed', async () => {
// Verify product was updated
await expect( page.getByText( 'Product updated.' ) ).toBeVisible();
// Verify image in store frontend
await page.goto( productWithImage.permalink );
await expect(
page.getByAltText( 'Awaiting product image' )
).toBeVisible();
} );
} );
test( 'can create a product gallery', async ( {
page,
productWithImage,
} ) => {
const images = [ 'image-02', 'image-03' ];
await test.step( 'Navigate to product edit page', async () => {
await page.goto(
`wp-admin/post.php?post=${ productWithImage.id }&action=edit`
);
} );
await test.step( 'Add product gallery images', async () => {
const imageSelector = '#product_images_container img';
let initialImagesCount = await page
.locator( imageSelector )
.count();
for ( const image of images ) {
await page
.getByRole( 'link', { name: 'Add product gallery images' } )
.click();
const dataId = await addImageFromLibrary(
page,
image,
'Add to gallery'
);
await expect(
page.locator( `li[data-attachment_id="${ dataId }"]` ),
'thumbnail should be visible'
).toBeVisible();
const currentImagesCount = await page
.locator( imageSelector )
.count();
await expect(
currentImagesCount,
'number of images should increase'
).toEqual( initialImagesCount + 1 );
initialImagesCount = currentImagesCount;
}
await page.getByRole( 'button', { name: 'Update' } ).click();
} );
await test.step( 'Verify product gallery', async () => {
// Verify gallery in store frontend
await page.goto( productWithImage.permalink );
await expect(
page
.locator( `#product-${ productWithImage.id } ol img` )
.nth( images.length ),
'all gallery images should be visible'
).toBeVisible(); // +1 for the featured image
} );
} );
test( 'can update a product gallery', async ( {
page,
productWithGallery,
} ) => {
let imagesCount;
await test.step( 'Navigate to product edit page', async () => {
await page.goto(
`wp-admin/post.php?post=${ productWithGallery.id }&action=edit`
);
} );
await test.step( 'Remove images from product gallery', async () => {
const imageSelector = '#product_images_container img';
imagesCount = await page.locator( imageSelector ).count();
await page.locator( imageSelector ).first().hover();
await page.getByRole( 'link', { name: ' Delete' } ).click();
await expect(
await page.locator( imageSelector ).count(),
'number of images should decrease'
).toEqual( imagesCount - 1 );
await page.getByRole( 'button', { name: 'Update' } ).click();
} );
await test.step( 'Verify product gallery', async () => {
// Verify gallery in store frontend
await page.goto( productWithGallery.permalink );
const selector = `#product-${ productWithGallery.id } ol img`;
await expect(
page.locator( selector ).nth( imagesCount - 1 ),
'gallery images should be visible'
).toBeVisible();
await expect(
page.locator( selector ).nth( imagesCount ),
'one gallery image should not be visible'
).toBeHidden();
} );
} );
} );