[e2e tests] Add tests for product inventory in product block editor (#44699)
* Remove describe blocks and duplicated page fixture * Add test `can update sku` * Add changelog * Finish test 'can update sku' * Add test 'can update stock status' * Add test 'can track stock quantity' * Add test 'can limit purchases' * Remove extra whitespace * Disable product editor tour * Revert timeout update
This commit is contained in:
parent
487f230f0a
commit
f4f4d798fe
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: dev
|
||||||
|
|
||||||
|
E2E tests: add tests for product inventory in product block editor
|
|
@ -18,5 +18,15 @@ exports.test = base.test.extend( {
|
||||||
|
|
||||||
await use( api );
|
await use( api );
|
||||||
},
|
},
|
||||||
|
wcAdminApi: async ( { baseURL }, use ) => {
|
||||||
|
const wcAdminApi = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc-admin', // Use wc-admin namespace
|
||||||
|
} );
|
||||||
|
|
||||||
|
await use( wcAdminApi );
|
||||||
|
},
|
||||||
} );
|
} );
|
||||||
exports.expect = base.expect;
|
exports.expect = base.expect;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
const { test } = require( '../../../../fixtures' );
|
const { test } = require( '../../../../fixtures' );
|
||||||
|
|
||||||
exports.test = test.extend( {
|
exports.test = test.extend( {
|
||||||
page: async ( { page, api }, use ) => {
|
page: async ( { page, api, wcAdminApi }, use ) => {
|
||||||
|
// Enable product block editor
|
||||||
await api.put(
|
await api.put(
|
||||||
'settings/advanced/woocommerce_feature_product_block_editor_enabled',
|
'settings/advanced/woocommerce_feature_product_block_editor_enabled',
|
||||||
{
|
{
|
||||||
|
@ -9,8 +10,14 @@ exports.test = test.extend( {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Disable the product editor tour
|
||||||
|
await wcAdminApi.post( 'options', {
|
||||||
|
woocommerce_block_product_tour_shown: 'yes',
|
||||||
|
} );
|
||||||
|
|
||||||
await use( page );
|
await use( page );
|
||||||
|
|
||||||
|
// Disable product block editor
|
||||||
await api.put(
|
await api.put(
|
||||||
'settings/advanced/woocommerce_feature_product_block_editor_enabled',
|
'settings/advanced/woocommerce_feature_product_block_editor_enabled',
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,118 +1,100 @@
|
||||||
const { test: baseTest } = require( './block-editor-fixtures' );
|
const { test: baseTest } = require( './block-editor-fixtures' );
|
||||||
const { expect } = require( '../../../../fixtures' );
|
const { expect } = require( '../../../../fixtures' );
|
||||||
baseTest.describe( 'Products > Edit Product', () => {
|
|
||||||
const test = baseTest.extend( {
|
|
||||||
product: async ( { api }, use ) => {
|
|
||||||
let product;
|
|
||||||
|
|
||||||
await api
|
const test = baseTest.extend( {
|
||||||
.post( 'products', {
|
product: async ( { api }, use ) => {
|
||||||
id: 0,
|
let product;
|
||||||
name: `Product ${ Date.now() }`,
|
|
||||||
type: 'simple',
|
|
||||||
description: `This product is a longer description of the awesome product ${ Date.now() }`,
|
|
||||||
short_description: `This product is pretty awesome ${ Date.now() }`,
|
|
||||||
regular_price: '12.99',
|
|
||||||
} )
|
|
||||||
.then( ( response ) => {
|
|
||||||
product = response.data;
|
|
||||||
} );
|
|
||||||
|
|
||||||
await use( product );
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
id: 0,
|
||||||
|
name: `Product ${ Date.now() }`,
|
||||||
|
type: 'simple',
|
||||||
|
description: `This product is a longer description of the awesome product ${ Date.now() }`,
|
||||||
|
short_description: `This product is pretty awesome ${ Date.now() }`,
|
||||||
|
regular_price: '12.99',
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
product = response.data;
|
||||||
|
} );
|
||||||
|
|
||||||
// Cleanup
|
await use( product );
|
||||||
await api.delete( `products/${ product.id }`, { force: true } );
|
|
||||||
},
|
|
||||||
page: async ( { page, api }, use ) => {
|
|
||||||
await api.put(
|
|
||||||
'settings/advanced/woocommerce_feature_product_block_editor_enabled',
|
|
||||||
{
|
|
||||||
value: 'yes',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
await use( page );
|
// Cleanup
|
||||||
|
await api.delete( `products/${ product.id }`, { force: true } );
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
|
||||||
await api.put(
|
test( 'can update the general information of a product', async ( {
|
||||||
'settings/advanced/woocommerce_feature_product_block_editor_enabled',
|
page,
|
||||||
{
|
product,
|
||||||
value: 'no',
|
} ) => {
|
||||||
}
|
await page.goto( `wp-admin/post.php?post=${ product.id }&action=edit` );
|
||||||
);
|
|
||||||
},
|
const updatedProduct = {
|
||||||
|
name: `Product ${ Date.now() }`,
|
||||||
|
description: `Updated description for the awesome product ${ Date.now() }`,
|
||||||
|
short_description: `Updated summary for the awesome product ${ Date.now() }`,
|
||||||
|
regularPrice: '100.05',
|
||||||
|
salePrice: '99.05',
|
||||||
|
};
|
||||||
|
|
||||||
|
const nameTextbox = page.getByLabel( 'Name' ).getByRole( 'textbox' );
|
||||||
|
const summaryTextbox = page
|
||||||
|
.getByLabel( 'Block: Product textarea block' )
|
||||||
|
.getByRole( 'textbox' );
|
||||||
|
const descriptionTextbox = page
|
||||||
|
.getByLabel( 'Block: Product description' )
|
||||||
|
.getByRole( 'textbox' );
|
||||||
|
const listPriceTextbox = page.getByRole( 'textbox', {
|
||||||
|
name: 'List price',
|
||||||
|
} );
|
||||||
|
const salePriceTextbox = page.getByRole( 'textbox', {
|
||||||
|
name: 'Sale price',
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'can update the general information of a product', async ( {
|
await test.step( 'edit the product name', async () => {
|
||||||
page,
|
await nameTextbox.fill( updatedProduct.name );
|
||||||
product,
|
} );
|
||||||
} ) => {
|
|
||||||
await page.goto( `wp-admin/post.php?post=${ product.id }&action=edit` );
|
|
||||||
|
|
||||||
const updatedProduct = {
|
await test.step( 'edit the product price', async () => {
|
||||||
name: `Product ${ Date.now() }`,
|
await listPriceTextbox.fill( updatedProduct.regularPrice );
|
||||||
description: `Updated description for the awesome product ${ Date.now() }`,
|
await salePriceTextbox.fill( updatedProduct.salePrice );
|
||||||
short_description: `Updated summary for the awesome product ${ Date.now() }`,
|
} );
|
||||||
regularPrice: '100.05',
|
|
||||||
salePrice: '99.05',
|
|
||||||
};
|
|
||||||
|
|
||||||
const nameTextbox = page.getByLabel( 'Name' ).getByRole( 'textbox' );
|
await test.step( 'edit the product description and summary', async () => {
|
||||||
const summaryTextbox = page
|
// Need to clear the textbox before filling it, otherwise the text will be appended.
|
||||||
.getByLabel( 'Block: Product textarea block' )
|
await descriptionTextbox.clear();
|
||||||
.getByRole( 'textbox' );
|
await descriptionTextbox.fill( updatedProduct.description );
|
||||||
const descriptionTextbox = page
|
|
||||||
.getByLabel( 'Block: Product description' )
|
|
||||||
.getByRole( 'textbox' );
|
|
||||||
const listPriceTextbox = page.getByRole( 'textbox', {
|
|
||||||
name: 'List price',
|
|
||||||
} );
|
|
||||||
const salePriceTextbox = page.getByRole( 'textbox', {
|
|
||||||
name: 'Sale price',
|
|
||||||
} );
|
|
||||||
|
|
||||||
await test.step( 'edit the product name', async () => {
|
await summaryTextbox.clear();
|
||||||
await nameTextbox.fill( updatedProduct.name );
|
await summaryTextbox.fill( updatedProduct.short_description );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
await test.step( 'edit the product price', async () => {
|
await test.step( 'publish the updated product', async () => {
|
||||||
await listPriceTextbox.fill( updatedProduct.regularPrice );
|
await page.getByRole( 'button', { name: 'Update' } ).click();
|
||||||
await salePriceTextbox.fill( updatedProduct.salePrice );
|
|
||||||
} );
|
|
||||||
|
|
||||||
await test.step( 'edit the product description and summary', async () => {
|
await expect( page.getByLabel( 'Dismiss this notice' ) ).toContainText(
|
||||||
// Need to clear the textbox before filling it, otherwise the text will be appended.
|
'Product updated'
|
||||||
await descriptionTextbox.clear();
|
);
|
||||||
await descriptionTextbox.fill( updatedProduct.description );
|
} );
|
||||||
|
|
||||||
await summaryTextbox.clear();
|
await test.step( 'verify the changes', async () => {
|
||||||
await summaryTextbox.fill( updatedProduct.short_description );
|
await expect.soft( nameTextbox ).toHaveValue( updatedProduct.name );
|
||||||
} );
|
|
||||||
|
|
||||||
await test.step( 'publish the updated product', async () => {
|
await expect
|
||||||
await page.getByRole( 'button', { name: 'Update' } ).click();
|
.soft( summaryTextbox )
|
||||||
|
.toHaveText( updatedProduct.short_description );
|
||||||
|
|
||||||
await expect(
|
await expect
|
||||||
page.getByLabel( 'Dismiss this notice' )
|
.soft( descriptionTextbox )
|
||||||
).toContainText( 'Product updated' );
|
.toHaveText( updatedProduct.description );
|
||||||
} );
|
|
||||||
|
|
||||||
await test.step( 'verify the changes', async () => {
|
await expect
|
||||||
await expect.soft( nameTextbox ).toHaveValue( updatedProduct.name );
|
.soft( listPriceTextbox )
|
||||||
|
.toHaveValue( updatedProduct.regularPrice );
|
||||||
await expect
|
await expect
|
||||||
.soft( summaryTextbox )
|
.soft( salePriceTextbox )
|
||||||
.toHaveText( updatedProduct.short_description );
|
.toHaveValue( updatedProduct.salePrice );
|
||||||
|
|
||||||
await expect
|
|
||||||
.soft( descriptionTextbox )
|
|
||||||
.toHaveText( updatedProduct.description );
|
|
||||||
|
|
||||||
await expect
|
|
||||||
.soft( listPriceTextbox )
|
|
||||||
.toHaveValue( updatedProduct.regularPrice );
|
|
||||||
await expect
|
|
||||||
.soft( salePriceTextbox )
|
|
||||||
.toHaveValue( updatedProduct.salePrice );
|
|
||||||
} );
|
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -23,230 +23,223 @@ async function selectImagesInLibrary( page, imagesNames ) {
|
||||||
return dataIds;
|
return dataIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
baseTest.describe( 'Products > Edit Product', () => {
|
const test = baseTest.extend( {
|
||||||
const test = baseTest.extend( {
|
product: async ( { api }, use ) => {
|
||||||
product: async ( { api }, use ) => {
|
let product;
|
||||||
let product;
|
|
||||||
|
|
||||||
await api
|
await api
|
||||||
.post( 'products', {
|
.post( 'products', {
|
||||||
name: `Product ${ Date.now() }`,
|
name: `Product ${ Date.now() }`,
|
||||||
type: 'simple',
|
type: 'simple',
|
||||||
description: `This is a description of the awesome product ${ Date.now() }`,
|
description: `This is a description of the awesome product ${ Date.now() }`,
|
||||||
short_description: `This product is pretty awesome ${ Date.now() }`,
|
short_description: `This product is pretty awesome ${ Date.now() }`,
|
||||||
regular_price: '12.99',
|
regular_price: '12.99',
|
||||||
} )
|
} )
|
||||||
.then( ( response ) => {
|
.then( ( response ) => {
|
||||||
product = response.data;
|
product = response.data;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
await use( product );
|
await use( product );
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
await api.delete( `products/${ product.id }`, { force: true } );
|
await api.delete( `products/${ product.id }`, { force: true } );
|
||||||
},
|
},
|
||||||
productWithGallery: async ( { api, product }, use ) => {
|
productWithGallery: async ( { api, product }, use ) => {
|
||||||
let productWithGallery;
|
let productWithGallery;
|
||||||
await api
|
await api
|
||||||
.put( `products/${ product.id }`, {
|
.put( `products/${ product.id }`, {
|
||||||
images: [
|
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_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_2_back.jpg',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: 'http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_3_front.jpg',
|
src: 'http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_3_front.jpg',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} )
|
} )
|
||||||
.then( ( response ) => {
|
.then( ( response ) => {
|
||||||
productWithGallery = response.data;
|
productWithGallery = response.data;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
await use( productWithGallery );
|
await use( productWithGallery );
|
||||||
},
|
},
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can add images', async ( { page, product } ) => {
|
||||||
|
const images = [ 'image-01', 'image-02' ];
|
||||||
|
|
||||||
|
await test.step( 'navigate to product edit page', async () => {
|
||||||
|
await page.goto( `wp-admin/post.php?post=${ product.id }&action=edit` );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'can add images', async ( { page, product } ) => {
|
await test.step( 'add images', async () => {
|
||||||
const images = [ 'image-01', 'image-02' ];
|
await page.getByText( 'Choose an image' ).click();
|
||||||
|
const dataIds = await selectImagesInLibrary( page, images );
|
||||||
|
|
||||||
await test.step( 'navigate to product edit page', async () => {
|
await expect(
|
||||||
await page.goto(
|
page.getByLabel( 'Block: Product images' ).locator( 'img' )
|
||||||
`wp-admin/post.php?post=${ product.id }&action=edit`
|
).toHaveCount( images.length );
|
||||||
);
|
|
||||||
} );
|
|
||||||
|
|
||||||
await test.step( 'add images', async () => {
|
|
||||||
await page.getByText( 'Choose an image' ).click();
|
|
||||||
const dataIds = await selectImagesInLibrary( page, images );
|
|
||||||
|
|
||||||
|
for ( const dataId of dataIds ) {
|
||||||
await expect(
|
await expect(
|
||||||
page.getByLabel( 'Block: Product images' ).locator( 'img' )
|
page
|
||||||
).toHaveCount( images.length );
|
.getByLabel( 'Block: Product images' )
|
||||||
|
.locator( `img[id="${ dataId }"]` )
|
||||||
for ( const dataId of dataIds ) {
|
).toBeVisible();
|
||||||
await expect(
|
}
|
||||||
page
|
|
||||||
.getByLabel( 'Block: Product images' )
|
|
||||||
.locator( `img[id="${ dataId }"]` )
|
|
||||||
).toBeVisible();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
await test.step( 'update the product', async () => {
|
|
||||||
await page.getByRole( 'button', { name: 'Update' } ).click();
|
|
||||||
// Verify product was updated
|
|
||||||
await expect(
|
|
||||||
page.getByLabel( 'Dismiss this notice' )
|
|
||||||
).toContainText( 'Product updated' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
await test.step( 'verify product image was set', async () => {
|
|
||||||
// Verify image in store frontend
|
|
||||||
await page.goto( product.permalink );
|
|
||||||
|
|
||||||
for ( const image of images ) {
|
|
||||||
await expect( page.getByTitle( image ) ).toBeVisible();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'can replace an image', async ( { page, productWithGallery } ) => {
|
await test.step( 'update the product', async () => {
|
||||||
const initialImagesCount = productWithGallery.images.length;
|
await page.getByRole( 'button', { name: 'Update' } ).click();
|
||||||
const newImageName = 'image-01';
|
// Verify product was updated
|
||||||
const replacedImgLocator = page
|
await expect( page.getByLabel( 'Dismiss this notice' ) ).toContainText(
|
||||||
.getByLabel( 'Block: Product images' )
|
'Product updated'
|
||||||
.locator( 'img' )
|
);
|
||||||
.nth( 1 );
|
|
||||||
let dataIds = [];
|
|
||||||
|
|
||||||
await test.step( 'navigate to product edit page', async () => {
|
|
||||||
await page.goto(
|
|
||||||
`wp-admin/post.php?post=${ productWithGallery.id }&action=edit`
|
|
||||||
);
|
|
||||||
} );
|
|
||||||
|
|
||||||
await test.step( 'replace an image', async () => {
|
|
||||||
await replacedImgLocator.click();
|
|
||||||
await page
|
|
||||||
.getByRole( 'toolbar', { name: 'Options' } )
|
|
||||||
.getByLabel( 'Options' )
|
|
||||||
.click();
|
|
||||||
await page.getByRole( 'menuitem', { name: 'Replace' } ).click();
|
|
||||||
dataIds = await selectImagesInLibrary( page, [ newImageName ] );
|
|
||||||
|
|
||||||
expect( await replacedImgLocator.getAttribute( 'src' ) ).toContain(
|
|
||||||
newImageName
|
|
||||||
);
|
|
||||||
} );
|
|
||||||
|
|
||||||
await test.step( 'update the product', async () => {
|
|
||||||
await page.getByRole( 'button', { name: 'Update' } ).click();
|
|
||||||
// Verify product was updated
|
|
||||||
await expect(
|
|
||||||
page.getByLabel( 'Dismiss this notice' )
|
|
||||||
).toContainText( 'Product updated' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
await test.step( 'verify product image was set', async () => {
|
|
||||||
await expect( replacedImgLocator ).toHaveId( dataIds[ 0 ] );
|
|
||||||
await expect(
|
|
||||||
page.getByLabel( 'Block: Product images' ).locator( 'img' )
|
|
||||||
).toHaveCount( initialImagesCount );
|
|
||||||
|
|
||||||
// Verify image in store frontend
|
|
||||||
await page.goto( productWithGallery.permalink );
|
|
||||||
await expect( page.getByTitle( newImageName ) ).toBeVisible();
|
|
||||||
} );
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'can remove an image', async ( { page, productWithGallery } ) => {
|
await test.step( 'verify product image was set', async () => {
|
||||||
const initialImagesCount = productWithGallery.images.length;
|
// Verify image in store frontend
|
||||||
const removedImgLocator = page
|
await page.goto( product.permalink );
|
||||||
.getByLabel( 'Block: Product images' )
|
|
||||||
.locator( 'img' )
|
|
||||||
.nth( 1 );
|
|
||||||
|
|
||||||
await test.step( 'navigate to product edit page', async () => {
|
for ( const image of images ) {
|
||||||
await page.goto(
|
await expect( page.getByTitle( image ) ).toBeVisible();
|
||||||
`wp-admin/post.php?post=${ productWithGallery.id }&action=edit`
|
}
|
||||||
);
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
await test.step( 'remove an image', async () => {
|
test( 'can replace an image', async ( { page, productWithGallery } ) => {
|
||||||
await removedImgLocator.click();
|
const initialImagesCount = productWithGallery.images.length;
|
||||||
await page
|
const newImageName = 'image-01';
|
||||||
.getByRole( 'toolbar', { name: 'Options' } )
|
const replacedImgLocator = page
|
||||||
.getByLabel( 'Options' )
|
.getByLabel( 'Block: Product images' )
|
||||||
.click();
|
.locator( 'img' )
|
||||||
await page.getByRole( 'menuitem', { name: 'Remove' } ).click();
|
.nth( 1 );
|
||||||
|
let dataIds = [];
|
||||||
await expect(
|
|
||||||
page.getByLabel( 'Block: Product images' ).locator( 'img' )
|
await test.step( 'navigate to product edit page', async () => {
|
||||||
).toHaveCount( initialImagesCount - 1 );
|
await page.goto(
|
||||||
} );
|
`wp-admin/post.php?post=${ productWithGallery.id }&action=edit`
|
||||||
|
);
|
||||||
await test.step( 'update the product', async () => {
|
} );
|
||||||
await page.getByRole( 'button', { name: 'Update' } ).click();
|
|
||||||
// Verify product was updated
|
await test.step( 'replace an image', async () => {
|
||||||
await expect(
|
await replacedImgLocator.click();
|
||||||
page.getByLabel( 'Dismiss this notice' )
|
await page
|
||||||
).toContainText( 'Product updated' );
|
.getByRole( 'toolbar', { name: 'Options' } )
|
||||||
} );
|
.getByLabel( 'Options' )
|
||||||
|
.click();
|
||||||
await test.step( 'verify product image was set', async () => {
|
await page.getByRole( 'menuitem', { name: 'Replace' } ).click();
|
||||||
await expect(
|
dataIds = await selectImagesInLibrary( page, [ newImageName ] );
|
||||||
page.getByLabel( 'Block: Product images' ).locator( 'img' )
|
|
||||||
).toHaveCount( initialImagesCount - 1 );
|
expect( await replacedImgLocator.getAttribute( 'src' ) ).toContain(
|
||||||
|
newImageName
|
||||||
// Verify image in store frontend
|
);
|
||||||
await page.goto( productWithGallery.permalink );
|
} );
|
||||||
await expect(
|
|
||||||
page.locator( `#product-${ productWithGallery.id } ol img` )
|
await test.step( 'update the product', async () => {
|
||||||
).toHaveCount( initialImagesCount - 1 );
|
await page.getByRole( 'button', { name: 'Update' } ).click();
|
||||||
} );
|
// Verify product was updated
|
||||||
} );
|
await expect( page.getByLabel( 'Dismiss this notice' ) ).toContainText(
|
||||||
|
'Product updated'
|
||||||
test( 'can set an image as cover', async ( {
|
);
|
||||||
page,
|
} );
|
||||||
productWithGallery,
|
|
||||||
} ) => {
|
await test.step( 'verify product image was set', async () => {
|
||||||
const newCoverImgLocator = page
|
await expect( replacedImgLocator ).toHaveId( dataIds[ 0 ] );
|
||||||
.getByLabel( 'Block: Product images' )
|
await expect(
|
||||||
.locator( 'img' )
|
page.getByLabel( 'Block: Product images' ).locator( 'img' )
|
||||||
.nth( 1 );
|
).toHaveCount( initialImagesCount );
|
||||||
|
|
||||||
await test.step( 'navigate to product edit page', async () => {
|
// Verify image in store frontend
|
||||||
await page.goto(
|
await page.goto( productWithGallery.permalink );
|
||||||
`wp-admin/post.php?post=${ productWithGallery.id }&action=edit`
|
await expect( page.getByTitle( newImageName ) ).toBeVisible();
|
||||||
);
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
const newCoverImgId = await newCoverImgLocator.getAttribute( 'id' );
|
test( 'can remove an image', async ( { page, productWithGallery } ) => {
|
||||||
|
const initialImagesCount = productWithGallery.images.length;
|
||||||
await test.step( 'remove an image', async () => {
|
const removedImgLocator = page
|
||||||
await newCoverImgLocator.click();
|
.getByLabel( 'Block: Product images' )
|
||||||
await page.getByLabel( 'Set as cover' ).click();
|
.locator( 'img' )
|
||||||
|
.nth( 1 );
|
||||||
await expect(
|
|
||||||
page.getByRole( 'button', { name: 'Cover' } ).locator( 'img' )
|
await test.step( 'navigate to product edit page', async () => {
|
||||||
).toHaveId( newCoverImgId );
|
await page.goto(
|
||||||
} );
|
`wp-admin/post.php?post=${ productWithGallery.id }&action=edit`
|
||||||
|
);
|
||||||
await test.step( 'update the product', async () => {
|
} );
|
||||||
await page.getByRole( 'button', { name: 'Update' } ).click();
|
|
||||||
// Verify product was updated
|
await test.step( 'remove an image', async () => {
|
||||||
await expect(
|
await removedImgLocator.click();
|
||||||
page.getByLabel( 'Dismiss this notice' )
|
await page
|
||||||
).toContainText( 'Product updated' );
|
.getByRole( 'toolbar', { name: 'Options' } )
|
||||||
} );
|
.getByLabel( 'Options' )
|
||||||
|
.click();
|
||||||
await test.step( 'verify product image was set', async () => {
|
await page.getByRole( 'menuitem', { name: 'Remove' } ).click();
|
||||||
await expect(
|
|
||||||
page.getByRole( 'button', { name: 'Cover' } ).locator( 'img' )
|
await expect(
|
||||||
).toHaveId( newCoverImgId );
|
page.getByLabel( 'Block: Product images' ).locator( 'img' )
|
||||||
} );
|
).toHaveCount( initialImagesCount - 1 );
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'update the product', async () => {
|
||||||
|
await page.getByRole( 'button', { name: 'Update' } ).click();
|
||||||
|
// Verify product was updated
|
||||||
|
await expect( page.getByLabel( 'Dismiss this notice' ) ).toContainText(
|
||||||
|
'Product updated'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'verify product image was set', async () => {
|
||||||
|
await expect(
|
||||||
|
page.getByLabel( 'Block: Product images' ).locator( 'img' )
|
||||||
|
).toHaveCount( initialImagesCount - 1 );
|
||||||
|
|
||||||
|
// Verify image in store frontend
|
||||||
|
await page.goto( productWithGallery.permalink );
|
||||||
|
await expect(
|
||||||
|
page.locator( `#product-${ productWithGallery.id } ol img` )
|
||||||
|
).toHaveCount( initialImagesCount - 1 );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can set an image as cover', async ( { page, productWithGallery } ) => {
|
||||||
|
const newCoverImgLocator = page
|
||||||
|
.getByLabel( 'Block: Product images' )
|
||||||
|
.locator( 'img' )
|
||||||
|
.nth( 1 );
|
||||||
|
|
||||||
|
await test.step( 'navigate to product edit page', async () => {
|
||||||
|
await page.goto(
|
||||||
|
`wp-admin/post.php?post=${ productWithGallery.id }&action=edit`
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
const newCoverImgId = await newCoverImgLocator.getAttribute( 'id' );
|
||||||
|
|
||||||
|
await test.step( 'remove an image', async () => {
|
||||||
|
await newCoverImgLocator.click();
|
||||||
|
await page.getByLabel( 'Set as cover' ).click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole( 'button', { name: 'Cover' } ).locator( 'img' )
|
||||||
|
).toHaveId( newCoverImgId );
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'update the product', async () => {
|
||||||
|
await page.getByRole( 'button', { name: 'Update' } ).click();
|
||||||
|
// Verify product was updated
|
||||||
|
await expect( page.getByLabel( 'Dismiss this notice' ) ).toContainText(
|
||||||
|
'Product updated'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'verify product image was set', async () => {
|
||||||
|
await expect(
|
||||||
|
page.getByRole( 'button', { name: 'Cover' } ).locator( 'img' )
|
||||||
|
).toHaveId( newCoverImgId );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
const { test: baseTest } = require( './block-editor-fixtures' );
|
||||||
|
const { expect } = require( '../../../../fixtures' );
|
||||||
|
|
||||||
|
const test = baseTest.extend( {
|
||||||
|
product: async ( { api }, use ) => {
|
||||||
|
let product;
|
||||||
|
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: `Product ${ Date.now() }`,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: '12.99',
|
||||||
|
stock_status: 'instock',
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
product = response.data;
|
||||||
|
} );
|
||||||
|
|
||||||
|
await use( product );
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
await api.delete( `products/${ product.id }`, { force: true } );
|
||||||
|
},
|
||||||
|
page: async ( { page, product }, use ) => {
|
||||||
|
await test.step( 'go to product editor, inventory tab', async () => {
|
||||||
|
await page.goto(
|
||||||
|
`wp-admin/post.php?post=${ product.id }&action=edit`
|
||||||
|
);
|
||||||
|
await page.getByRole( 'button', { name: 'Inventory' } ).click();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await use( page );
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can update sku', async ( { page, product } ) => {
|
||||||
|
const sku = `SKU_${ Date.now() }`;
|
||||||
|
|
||||||
|
await test.step( 'update the sku value', async () => {
|
||||||
|
await page.locator( '[name="woocommerce-product-sku"]' ).fill( sku );
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'update the product', async () => {
|
||||||
|
await page.getByRole( 'button', { name: 'Update' } ).click();
|
||||||
|
// Verify product was updated
|
||||||
|
await expect( page.getByLabel( 'Dismiss this notice' ) ).toContainText(
|
||||||
|
'Product updated'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'verify the change in product editor', async () => {
|
||||||
|
await expect(
|
||||||
|
page.locator( '[name="woocommerce-product-sku"]' )
|
||||||
|
).toHaveValue( sku );
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'verify the changes in the store frontend', async () => {
|
||||||
|
// Verify image in store frontend
|
||||||
|
await page.goto( product.permalink );
|
||||||
|
|
||||||
|
await expect( page.getByText( `SKU: ${ sku }` ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can update stock status', async ( { page, product } ) => {
|
||||||
|
await test.step( 'update the sku value', async () => {
|
||||||
|
await page.getByLabel( 'Out of stock' ).check();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'update the product', async () => {
|
||||||
|
await page.getByRole( 'button', { name: 'Update' } ).click();
|
||||||
|
// Verify product was updated
|
||||||
|
await expect( page.getByLabel( 'Dismiss this notice' ) ).toContainText(
|
||||||
|
'Product updated'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'verify the change in product editor', async () => {
|
||||||
|
await expect( page.getByLabel( 'Out of stock' ) ).toBeChecked();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'verify the changes in the store frontend', async () => {
|
||||||
|
// Verify image in store frontend
|
||||||
|
await page.goto( product.permalink );
|
||||||
|
|
||||||
|
await expect( page.getByText( 'Out of stock' ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can track stock quantity', async ( { page, product } ) => {
|
||||||
|
await test.step( 'enable track stock quantity', async () => {
|
||||||
|
await page.getByLabel( 'Track stock quantity for this' ).check();
|
||||||
|
// await closeTourModal( { page, timeout: 2000 } );
|
||||||
|
await page.getByRole( 'button', { name: 'Advanced' } ).click();
|
||||||
|
await page.getByLabel( "Don't allow purchases" ).check();
|
||||||
|
} );
|
||||||
|
|
||||||
|
const quantity = '1';
|
||||||
|
|
||||||
|
await test.step( 'update available quantity', async () => {
|
||||||
|
await page.locator( '[name="stock_quantity"]' ).fill( quantity );
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'update the product', async () => {
|
||||||
|
await page.getByRole( 'button', { name: 'Update' } ).click();
|
||||||
|
// Verify product was updated
|
||||||
|
await expect( page.getByLabel( 'Dismiss this notice' ) ).toContainText(
|
||||||
|
'Product updated'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'verify the change in product editor', async () => {
|
||||||
|
await expect( page.locator( '[name="stock_quantity"]' ) ).toHaveValue(
|
||||||
|
quantity
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'verify the changes in the store frontend', async () => {
|
||||||
|
// Verify image in store frontend
|
||||||
|
await page.goto( product.permalink );
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText( `${ quantity } in stock` )
|
||||||
|
).toBeVisible();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'return to product editor', async () => {
|
||||||
|
await page.goto( `wp-admin/post.php?post=${ product.id }&action=edit` );
|
||||||
|
await page.getByRole( 'button', { name: 'Inventory' } ).click();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'update available quantity', async () => {
|
||||||
|
await page.locator( '[name="stock_quantity"]' ).fill( '0' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'update the product', async () => {
|
||||||
|
await page.getByRole( 'button', { name: 'Update' } ).click();
|
||||||
|
// Verify product was updated
|
||||||
|
await expect( page.getByLabel( 'Dismiss this notice' ) ).toContainText(
|
||||||
|
'Product updated'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'verify the change in product editor', async () => {
|
||||||
|
await expect( page.locator( '[name="stock_quantity"]' ) ).toHaveValue(
|
||||||
|
'0'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'verify the changes in the store frontend', async () => {
|
||||||
|
// Verify image in store frontend
|
||||||
|
await page.goto( product.permalink );
|
||||||
|
|
||||||
|
await expect( page.getByText( 'Out of stock' ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can limit purchases', async ( { page, product } ) => {
|
||||||
|
await test.step( 'ensure limit purchases is disabled', async () => {
|
||||||
|
// await closeTourModal( { page, timeout: 2000 } );
|
||||||
|
await page.getByRole( 'button', { name: 'Advanced' } ).click();
|
||||||
|
await expect(
|
||||||
|
page.getByLabel( 'Limit purchases to 1 item per order' )
|
||||||
|
).not.toBeChecked();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'add 2 items to cart', async () => {
|
||||||
|
// Verify image in store frontend
|
||||||
|
await page.goto( product.permalink );
|
||||||
|
|
||||||
|
await page.getByLabel( 'Product quantity' ).fill( '2' );
|
||||||
|
await page.getByRole( 'button', { name: 'Add to cart' } ).click();
|
||||||
|
await expect(
|
||||||
|
page.getByText(
|
||||||
|
`2 × “${ product.name }” have been added to your cart.`
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'return to product editor', async () => {
|
||||||
|
await page.goto( `wp-admin/post.php?post=${ product.id }&action=edit` );
|
||||||
|
await page.getByRole( 'button', { name: 'Inventory' } ).click();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'enable limit purchases', async () => {
|
||||||
|
await page.getByRole( 'button', { name: 'Advanced' } ).click();
|
||||||
|
await page.getByLabel( 'Limit purchases to 1 item per order' ).check();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'update the product', async () => {
|
||||||
|
await page.getByRole( 'button', { name: 'Update' } ).click();
|
||||||
|
// Verify product was updated
|
||||||
|
await expect( page.getByLabel( 'Dismiss this notice' ) ).toContainText(
|
||||||
|
'Product updated'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'verify you cannot order more than 1 item', async () => {
|
||||||
|
// Verify image in store frontend
|
||||||
|
await page.goto( product.permalink );
|
||||||
|
|
||||||
|
await page.getByRole( 'button', { name: 'Add to cart' } ).click();
|
||||||
|
await page.getByRole( 'button', { name: 'Add to cart' } ).click();
|
||||||
|
await expect(
|
||||||
|
page.getByText(
|
||||||
|
`You cannot add another "${ product.name }" to your cart.`
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
} );
|
||||||
|
} );
|
Loading…
Reference in New Issue