Split the `can create product, attributes and variations, edit variations and delete variations` E2E test into smaller tests (#37733)
This commit is contained in:
commit
aa55d04e14
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: dev
|
||||||
|
|
||||||
|
Split can create product, attributes and variations, edit variations and delete variations into smaller tests to avoid timing out
|
|
@ -16,6 +16,9 @@ const defaultAttributes = [ 'val2', 'val1', 'val2' ];
|
||||||
const stockAmount = '100';
|
const stockAmount = '100';
|
||||||
const lowStockAmount = '10';
|
const lowStockAmount = '10';
|
||||||
|
|
||||||
|
let fixedVariableProductId;
|
||||||
|
let fixedVariationIds;
|
||||||
|
|
||||||
async function deleteProductsAddedByTests( baseURL ) {
|
async function deleteProductsAddedByTests( baseURL ) {
|
||||||
const api = new wcApi( {
|
const api = new wcApi( {
|
||||||
url: baseURL,
|
url: baseURL,
|
||||||
|
@ -34,206 +37,678 @@ async function deleteProductsAddedByTests( baseURL ) {
|
||||||
|
|
||||||
const ids = varProducts
|
const ids = varProducts
|
||||||
.map( ( { id } ) => id )
|
.map( ( { id } ) => id )
|
||||||
.concat( manualProducts.map( ( { id } ) => id ) );
|
.concat( manualProducts.map( ( { id } ) => id ) )
|
||||||
|
.concat( [ fixedVariableProductId ] );
|
||||||
|
|
||||||
await api.post( 'products/batch', { delete: ids } );
|
await api.post( 'products/batch', { delete: ids } );
|
||||||
}
|
}
|
||||||
|
|
||||||
async function resetVariableProductTour( baseURL, browser ) {
|
async function resetVariableProductTour( page ) {
|
||||||
// Go to the product page, so that the `window.wp.data` module is available
|
await test.step(
|
||||||
const page = await browser.newPage( { baseURL: baseURL } );
|
'Go to the product page, so that the `window.wp.data` module is available',
|
||||||
await page.goto( productPageURL );
|
async () => {
|
||||||
|
await page.goto( productPageURL );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Get the current user's ID and user preferences
|
const { id: userId, woocommerce_meta } = await test.step(
|
||||||
const { id: userId, woocommerce_meta } = await page.evaluate( () => {
|
"Get the current user's ID and user preferences",
|
||||||
return window.wp.data.select( 'core' ).getCurrentUser();
|
async () => {
|
||||||
|
return await page.evaluate( () => {
|
||||||
|
return window.wp.data.select( 'core' ).getCurrentUser();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const updatedWooCommerceMeta = await test.step(
|
||||||
|
'Reset the variable product tour preference, so that it will be shown again',
|
||||||
|
async () => {
|
||||||
|
return {
|
||||||
|
...woocommerce_meta,
|
||||||
|
variable_product_tour_shown: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step( 'Save the updated user preferences', async () => {
|
||||||
|
await page.evaluate(
|
||||||
|
async ( { userId, updatedWooCommerceMeta } ) => {
|
||||||
|
await window.wp.data.dispatch( 'core' ).saveUser( {
|
||||||
|
id: userId,
|
||||||
|
woocommerce_meta: updatedWooCommerceMeta,
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
{ userId, updatedWooCommerceMeta }
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createVariableProductFixture( baseURL ) {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// Reset the variable product tour preference, so that it will be shown again
|
const createVariableProductRequestPayload = {
|
||||||
const updatedWooCommerceMeta = {
|
name: 'Unbranded Granite Shirt',
|
||||||
...woocommerce_meta,
|
type: 'variable',
|
||||||
variable_product_tour_shown: '',
|
attributes: [
|
||||||
|
{
|
||||||
|
name: 'Colour',
|
||||||
|
visible: true,
|
||||||
|
variation: true,
|
||||||
|
options: [ 'Red', 'Green' ],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Size',
|
||||||
|
visible: true,
|
||||||
|
variation: true,
|
||||||
|
options: [ 'Small', 'Medium' ],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Logo',
|
||||||
|
visible: true,
|
||||||
|
variation: true,
|
||||||
|
options: [ 'Woo', 'WordPress' ],
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Save the updated user preferences
|
const batchCreateVariationsPayload = {
|
||||||
await page.evaluate(
|
create: [
|
||||||
async ( { userId, updatedWooCommerceMeta } ) => {
|
{
|
||||||
await window.wp.data.dispatch( 'core' ).saveUser( {
|
attributes: [
|
||||||
id: userId,
|
{ name: 'Colour', option: 'Red' },
|
||||||
woocommerce_meta: updatedWooCommerceMeta,
|
{ name: 'Size', option: 'Small' },
|
||||||
} );
|
{ name: 'Logo', option: 'Woo' },
|
||||||
},
|
],
|
||||||
{ userId, updatedWooCommerceMeta }
|
},
|
||||||
|
{
|
||||||
|
attributes: [
|
||||||
|
{ name: 'Colour', option: 'Red' },
|
||||||
|
{ name: 'Size', option: 'Small' },
|
||||||
|
{ name: 'Logo', option: 'WordPress' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attributes: [
|
||||||
|
{ name: 'Colour', option: 'Red' },
|
||||||
|
{ name: 'Size', option: 'Medium' },
|
||||||
|
{ name: 'Logo', option: 'Woo' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attributes: [
|
||||||
|
{ name: 'Colour', option: 'Red' },
|
||||||
|
{ name: 'Size', option: 'Medium' },
|
||||||
|
{ name: 'Logo', option: 'WordPress' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attributes: [
|
||||||
|
{ name: 'Colour', option: 'Green' },
|
||||||
|
{ name: 'Size', option: 'Small' },
|
||||||
|
{ name: 'Logo', option: 'Woo' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attributes: [
|
||||||
|
{ name: 'Colour', option: 'Green' },
|
||||||
|
{ name: 'Size', option: 'Small' },
|
||||||
|
{ name: 'Logo', option: 'WordPress' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attributes: [
|
||||||
|
{ name: 'Colour', option: 'Green' },
|
||||||
|
{ name: 'Size', option: 'Medium' },
|
||||||
|
{ name: 'Logo', option: 'Woo' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attributes: [
|
||||||
|
{ name: 'Colour', option: 'Green' },
|
||||||
|
{ name: 'Size', option: 'Medium' },
|
||||||
|
{ name: 'Logo', option: 'WordPress' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Create the variable product and its attributes.',
|
||||||
|
async () => {
|
||||||
|
await api
|
||||||
|
.post( 'products', createVariableProductRequestPayload )
|
||||||
|
.then( ( response ) => {
|
||||||
|
fixedVariableProductId = response.data.id;
|
||||||
|
} );
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await test.step( 'Generate all variations.', async () => {
|
||||||
|
await api
|
||||||
|
.post(
|
||||||
|
`products/${ fixedVariableProductId }/variations/batch`,
|
||||||
|
batchCreateVariationsPayload
|
||||||
|
)
|
||||||
|
.then( ( response ) => {
|
||||||
|
fixedVariationIds = response.data.create
|
||||||
|
.map( ( variation ) => variation.id )
|
||||||
|
.sort();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
test.describe( 'Add New Variable Product Page', () => {
|
test.describe( 'Add New Variable Product Page', () => {
|
||||||
test.use( { storageState: process.env.ADMINSTATE } );
|
test.use( { storageState: process.env.ADMINSTATE } );
|
||||||
|
|
||||||
test.afterAll( async ( { baseURL, browser } ) => {
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
await deleteProductsAddedByTests( baseURL );
|
await test.step(
|
||||||
await resetVariableProductTour( baseURL, browser );
|
'Set up a variable product fixture through the REST API.',
|
||||||
|
async () => {
|
||||||
|
await createVariableProductFixture( baseURL );
|
||||||
|
}
|
||||||
|
);
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'can create product, attributes and variations, edit variations and delete variations', async ( {
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
await deleteProductsAddedByTests( baseURL );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can create product, attributes and variations', async ( {
|
||||||
page,
|
page,
|
||||||
} ) => {
|
} ) => {
|
||||||
await page.goto( productPageURL );
|
await test.step( 'Reset the variable product tour.', async () => {
|
||||||
await page.fill( '#title', variableProductName );
|
await resetVariableProductTour( page );
|
||||||
await page.selectOption( '#product-type', 'variable' );
|
} );
|
||||||
|
|
||||||
await page
|
await test.step( 'Go to "Products > Add new" page.', async () => {
|
||||||
.locator( '.attribute_tab' )
|
await page.goto( productPageURL );
|
||||||
.getByRole( 'link', { name: 'Attributes' } )
|
} );
|
||||||
.scrollIntoViewIfNeeded();
|
|
||||||
|
await test.step(
|
||||||
|
`Type "${ variableProductName }" into the "Product name" input field.`,
|
||||||
|
async () => {
|
||||||
|
await page.fill( '#title', variableProductName );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Select the "Variable product" product type.',
|
||||||
|
async () => {
|
||||||
|
await page.selectOption( '#product-type', 'variable' );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Scroll into the "Attributes" tab and click it.',
|
||||||
|
async () => {
|
||||||
|
const attributesTab = page
|
||||||
|
.locator( '.attribute_tab' )
|
||||||
|
.getByRole( 'link', { name: 'Attributes' } );
|
||||||
|
|
||||||
|
await attributesTab.scrollIntoViewIfNeeded();
|
||||||
|
|
||||||
|
await attributesTab.click();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// the tour only seems to display when not running headless, so just make sure
|
// the tour only seems to display when not running headless, so just make sure
|
||||||
if ( await page.locator( '.woocommerce-tour-kit-step__heading' ).isVisible() ) {
|
const tourWasDisplayed = await test.step(
|
||||||
// dismiss the variable product tour
|
'See if the tour was displayed.',
|
||||||
await page
|
async () => {
|
||||||
.getByRole( 'button', { name: 'Close Tour' } )
|
return await page
|
||||||
.click();
|
.locator( '.woocommerce-tour-kit-step__heading' )
|
||||||
|
.isVisible();
|
||||||
// wait for the tour's dismissal to be saved
|
|
||||||
await page.waitForResponse(
|
|
||||||
( response ) =>
|
|
||||||
response.url().includes( '/users/' ) &&
|
|
||||||
response.status() === 200
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await page.click( 'a[href="#product_attributes"]' );
|
|
||||||
|
|
||||||
// add 3 attributes
|
|
||||||
for ( let i = 0; i < 3; i++ ) {
|
|
||||||
if ( i > 0 ) {
|
|
||||||
await page.getByRole( 'button', { name: 'Add' } )
|
|
||||||
.nth(2)
|
|
||||||
.click();
|
|
||||||
}
|
}
|
||||||
await page.waitForSelector(
|
);
|
||||||
`input[name="attribute_names[${ i }]"]`
|
|
||||||
|
if ( tourWasDisplayed ) {
|
||||||
|
await test.step( 'Tour was displayed, so dismiss it.', async () => {
|
||||||
|
await page
|
||||||
|
.getByRole( 'button', { name: 'Close Tour' } )
|
||||||
|
.click();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
"Wait for the tour's dismissal to be saved",
|
||||||
|
async () => {
|
||||||
|
await page.waitForResponse(
|
||||||
|
( response ) =>
|
||||||
|
response.url().includes( '/users/' ) &&
|
||||||
|
response.status() === 200
|
||||||
|
);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
await page
|
|
||||||
.locator( `input[name="attribute_names[${ i }]"]` )
|
|
||||||
.first()
|
|
||||||
.type( `attr #${ i + 1 }` );
|
|
||||||
await page
|
|
||||||
.locator( `textarea[name="attribute_values[${ i }]"]` )
|
|
||||||
.first()
|
|
||||||
.type( 'val1 | val2' );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await page.getByRole( 'button', { name: 'Save attributes'} ).click( { clickCount: 3 });
|
await test.step( 'Add 3 attributes.', async () => {
|
||||||
|
for ( let i = 0; i < 3; i++ ) {
|
||||||
|
if ( i > 0 ) {
|
||||||
|
await test.step( "Click 'Add'.", async () => {
|
||||||
|
await page
|
||||||
|
.locator( '.add-attribute-container' )
|
||||||
|
.getByRole( 'button', { name: 'Add' } )
|
||||||
|
.click();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
// wait for the tour's dismissal to be saved
|
await test.step(
|
||||||
await page.waitForResponse(
|
`Add the attribute "attr #${
|
||||||
( response ) =>
|
i + 1
|
||||||
response.url().includes( '/post.php' ) &&
|
}" with values "val1 | val2"`,
|
||||||
response.status() === 200
|
async () => {
|
||||||
);
|
await test.step(
|
||||||
|
'Wait for the "Attribute name" input field to appear.',
|
||||||
|
async () => {
|
||||||
|
await page.waitForSelector(
|
||||||
|
`input[name="attribute_names[${ i }]"]`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Save before going to the Variations tab to prevent variations from all attributes to be automatically created
|
await test.step(
|
||||||
await page.locator( '#save-post' ).click();
|
`Type "attr #${
|
||||||
await expect(
|
i + 1
|
||||||
page.getByText( 'Product draft updated. ' )
|
}" in the "Attribute name" input field.`,
|
||||||
).toBeVisible();
|
async () => {
|
||||||
|
await page
|
||||||
|
.locator(
|
||||||
|
`input[name="attribute_names[${ i }]"]`
|
||||||
|
)
|
||||||
|
.first()
|
||||||
|
.type( `attr #${ i + 1 }` );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
await page.click( 'a[href="#variable_product_options"]' );
|
await test.step(
|
||||||
|
'Type the attribute values "val1 | val2".',
|
||||||
|
async () => {
|
||||||
|
await page
|
||||||
|
.locator(
|
||||||
|
`textarea[name="attribute_values[${ i }]"]`
|
||||||
|
)
|
||||||
|
.first()
|
||||||
|
.type( 'val1 | val2' );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// event listener for handling the link_all_variations confirmation dialog
|
await test.step(
|
||||||
page.on( 'dialog', ( dialog ) => dialog.accept() );
|
'Click "Save attributes".',
|
||||||
|
async () => {
|
||||||
|
await page
|
||||||
|
.getByRole( 'button', {
|
||||||
|
name: 'Save attributes',
|
||||||
|
} )
|
||||||
|
.click( { clickCount: 3 } );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// generate variations from all attributes
|
await test.step(
|
||||||
await page.click( 'button.generate_variations' );
|
"Wait for the tour's dismissal to be saved",
|
||||||
|
async () => {
|
||||||
// verify variations have the correct attribute values
|
await page.waitForResponse(
|
||||||
for ( let i = 0; i < 8; i++ ) {
|
( response ) =>
|
||||||
const val1 = 'val1';
|
response
|
||||||
const val2 = 'val2';
|
.url()
|
||||||
const attr3 = !! ( i % 2 ); // 0-1,4-5 / 2-3,6-7
|
.includes( '/post.php' ) &&
|
||||||
const attr2 = i % 4 > 1; // 0-3 / 4-7
|
response.status() === 200
|
||||||
const attr1 = i > 3;
|
);
|
||||||
await expect(
|
}
|
||||||
page.locator( `select[name="attribute_attr-1[${ i }]"]` )
|
);
|
||||||
).toHaveValue( attr1 ? val2 : val1 );
|
}
|
||||||
await expect(
|
);
|
||||||
page.locator( `select[name="attribute_attr-2[${ i }]"]` )
|
}
|
||||||
).toHaveValue( attr2 ? val2 : val1 );
|
|
||||||
await expect(
|
|
||||||
page.locator( `select[name="attribute_attr-3[${ i }]"]` )
|
|
||||||
).toHaveValue( attr3 ? val2 : val1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
await page.locator( '#save-post' ).click();
|
|
||||||
await expect( page.locator( '#message.notice-success' ) ).toContainText(
|
|
||||||
'Product draft updated.'
|
|
||||||
);
|
|
||||||
|
|
||||||
// set variation attributes and bulk edit variations
|
|
||||||
await page.click( 'a[href="#variable_product_options"]' );
|
|
||||||
|
|
||||||
// set the variation attributes
|
|
||||||
await page.click(
|
|
||||||
'#variable_product_options .toolbar-top a.expand_all'
|
|
||||||
);
|
|
||||||
await page.check( 'input[name="variable_is_virtual[0]"]' );
|
|
||||||
await page.fill(
|
|
||||||
'input[name="variable_regular_price[0]"]',
|
|
||||||
variationOnePrice
|
|
||||||
);
|
|
||||||
await page.check( 'input[name="variable_is_virtual[1]"]' );
|
|
||||||
await page.fill(
|
|
||||||
'input[name="variable_regular_price[1]"]',
|
|
||||||
variationTwoPrice
|
|
||||||
);
|
|
||||||
await page.check( 'input[name="variable_manage_stock[2]"]' );
|
|
||||||
await page.fill(
|
|
||||||
'input[name="variable_regular_price[2]"]',
|
|
||||||
variationThreePrice
|
|
||||||
);
|
|
||||||
await page.fill( 'input[name="variable_weight[2]"]', productWeight );
|
|
||||||
await page.fill( 'input[name="variable_length[2]"]', productLength );
|
|
||||||
await page.fill( 'input[name="variable_width[2]"]', productWidth );
|
|
||||||
await page.fill( 'input[name="variable_height[2]"]', productHeight );
|
|
||||||
await page.keyboard.press( 'ArrowUp' );
|
|
||||||
await page.click( 'button.save-variation-changes' );
|
|
||||||
|
|
||||||
// bulk-edit variations
|
|
||||||
await page.click(
|
|
||||||
'#variable_product_options .toolbar-top a.expand_all'
|
|
||||||
);
|
|
||||||
for ( let i = 0; i < 4; i++ ) {
|
|
||||||
const checkBox = page.locator(
|
|
||||||
`input[name="variable_is_downloadable[${ i }]"]`
|
|
||||||
);
|
|
||||||
await expect( checkBox ).not.toBeChecked();
|
|
||||||
}
|
|
||||||
await page.selectOption( '#field_to_edit', 'toggle_downloadable', {
|
|
||||||
force: true,
|
|
||||||
} );
|
} );
|
||||||
await page.click(
|
|
||||||
'#variable_product_options .toolbar-top a.expand_all'
|
await test.step(
|
||||||
|
'Save before going to the Variations tab to prevent variations from all attributes to be automatically created.',
|
||||||
|
async () => {
|
||||||
|
await page.locator( '#save-post' ).click();
|
||||||
|
}
|
||||||
);
|
);
|
||||||
for ( let i = 0; i < 4; i++ ) {
|
|
||||||
const checkBox = await page.locator(
|
|
||||||
`input[name="variable_is_downloadable[${ i }]"]`
|
|
||||||
);
|
|
||||||
await expect( checkBox ).toBeChecked();
|
|
||||||
}
|
|
||||||
|
|
||||||
await page.locator( '#save-post' ).click();
|
await test.step(
|
||||||
|
'Expect the "Product draft updated." notice to appear.',
|
||||||
|
async () => {
|
||||||
|
await expect(
|
||||||
|
page.getByText( 'Product draft updated. ' )
|
||||||
|
).toBeVisible();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// delete all variations
|
await test.step( 'Click on the "Variations" tab.', async () => {
|
||||||
await page.click( 'a[href="#variable_product_options"]' );
|
await page.click( 'a[href="#variable_product_options"]' );
|
||||||
await page.waitForLoadState( 'networkidle' );
|
|
||||||
await page.selectOption( '#field_to_edit', 'delete_all' );
|
|
||||||
await page.waitForSelector( '.woocommerce_variation', {
|
|
||||||
state: 'detached',
|
|
||||||
} );
|
} );
|
||||||
const variationsCount = await page.$$( '.woocommerce_variation' );
|
|
||||||
await expect( variationsCount ).toHaveLength( 0 );
|
await test.step(
|
||||||
|
'Click on the "Generate variations" button.',
|
||||||
|
async () => {
|
||||||
|
// event listener for handling the link_all_variations confirmation dialog
|
||||||
|
page.on( 'dialog', ( dialog ) => dialog.accept() );
|
||||||
|
|
||||||
|
await page.click( 'button.generate_variations' );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Expect variations to have the correct attribute values',
|
||||||
|
async () => {
|
||||||
|
for ( let i = 0; i < 8; i++ ) {
|
||||||
|
const val1 = 'val1';
|
||||||
|
const val2 = 'val2';
|
||||||
|
const attr3 = !! ( i % 2 ); // 0-1,4-5 / 2-3,6-7
|
||||||
|
const attr2 = i % 4 > 1; // 0-3 / 4-7
|
||||||
|
const attr1 = i > 3;
|
||||||
|
await expect(
|
||||||
|
page.locator(
|
||||||
|
`select[name="attribute_attr-1[${ i }]"]`
|
||||||
|
)
|
||||||
|
).toHaveValue( attr1 ? val2 : val1 );
|
||||||
|
await expect(
|
||||||
|
page.locator(
|
||||||
|
`select[name="attribute_attr-2[${ i }]"]`
|
||||||
|
)
|
||||||
|
).toHaveValue( attr2 ? val2 : val1 );
|
||||||
|
await expect(
|
||||||
|
page.locator(
|
||||||
|
`select[name="attribute_attr-3[${ i }]"]`
|
||||||
|
)
|
||||||
|
).toHaveValue( attr3 ? val2 : val1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step( 'Click "Save Draft" button.', async () => {
|
||||||
|
await page.locator( '#save-post' ).click();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Expect the "Product draft updated." notice to appear.',
|
||||||
|
async () => {
|
||||||
|
await expect(
|
||||||
|
page.locator( '#message.notice-success' )
|
||||||
|
).toContainText( 'Product draft updated.' );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can individually edit variations', async ( { page } ) => {
|
||||||
|
const variationRows = page.locator( '.woocommerce_variation' );
|
||||||
|
const firstVariation = variationRows.filter( {
|
||||||
|
hasText: `#${ fixedVariationIds[ 0 ] }`,
|
||||||
|
} );
|
||||||
|
const secondVariation = variationRows.filter( {
|
||||||
|
hasText: `#${ fixedVariationIds[ 1 ] }`,
|
||||||
|
} );
|
||||||
|
const thirdVariation = variationRows.filter( {
|
||||||
|
hasText: `#${ fixedVariationIds[ 2 ] }`,
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Go to the "Edit product" page.', async () => {
|
||||||
|
await page.goto(
|
||||||
|
`/wp-admin/post.php?post=${ fixedVariableProductId }&action=edit`
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Click on the "Variations" tab.', async () => {
|
||||||
|
await page.click( 'a[href="#variable_product_options"]' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Expand all variations.', async () => {
|
||||||
|
await page.click(
|
||||||
|
'#variable_product_options .toolbar-top a.expand_all'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Edit the first variation.', async () => {
|
||||||
|
await test.step( 'Check the "Virtual" checkbox.', async () => {
|
||||||
|
await firstVariation
|
||||||
|
.getByRole( 'checkbox', {
|
||||||
|
name: 'Virtual',
|
||||||
|
} )
|
||||||
|
.check();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
`Set regular price to "${ variationOnePrice }".`,
|
||||||
|
async () => {
|
||||||
|
await firstVariation
|
||||||
|
.getByRole( 'textbox', { name: 'Regular price' } )
|
||||||
|
.fill( variationOnePrice );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Edit the second variation.', async () => {
|
||||||
|
await test.step( 'Check the "Virtual" checkbox.', async () => {
|
||||||
|
await secondVariation
|
||||||
|
.getByRole( 'checkbox', {
|
||||||
|
name: 'Virtual',
|
||||||
|
} )
|
||||||
|
.check();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
`Set regular price to "${ variationTwoPrice }".`,
|
||||||
|
async () => {
|
||||||
|
await secondVariation
|
||||||
|
.getByRole( 'textbox', { name: 'Regular price' } )
|
||||||
|
.fill( variationTwoPrice );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Edit the third variation.', async () => {
|
||||||
|
await test.step( 'Check "Manage stock?"', async () => {
|
||||||
|
await thirdVariation
|
||||||
|
.getByRole( 'checkbox', { name: 'Manage stock?' } )
|
||||||
|
.check();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
`Set regular price to "${ variationThreePrice }".`,
|
||||||
|
async () => {
|
||||||
|
await thirdVariation
|
||||||
|
.getByRole( 'textbox', { name: 'Regular price' } )
|
||||||
|
.fill( variationThreePrice );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step( 'Set the weight and dimensions.', async () => {
|
||||||
|
await thirdVariation
|
||||||
|
.getByRole( 'textbox', { name: 'Weight' } )
|
||||||
|
.type( productWeight );
|
||||||
|
|
||||||
|
await thirdVariation
|
||||||
|
.getByRole( 'textbox', { name: 'Length' } )
|
||||||
|
.type( productLength );
|
||||||
|
|
||||||
|
await thirdVariation
|
||||||
|
.getByRole( 'textbox', { name: 'Width' } )
|
||||||
|
.type( productWidth );
|
||||||
|
|
||||||
|
await thirdVariation
|
||||||
|
.getByRole( 'textbox', { name: 'Height' } )
|
||||||
|
.type( productHeight );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Click "Save changes".', async () => {
|
||||||
|
await page.click( 'button.save-variation-changes' );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Click on the "Variations" tab.', async () => {
|
||||||
|
await page.click( 'a[href="#variable_product_options"]' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Expand all variations.', async () => {
|
||||||
|
await page.click(
|
||||||
|
'#variable_product_options .toolbar-top a.expand_all'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Expect the first variation to be virtual.',
|
||||||
|
async () => {
|
||||||
|
await expect(
|
||||||
|
firstVariation.getByRole( 'checkbox', {
|
||||||
|
name: 'Virtual',
|
||||||
|
} )
|
||||||
|
).toBeChecked();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
`Expect the regular price of the first variation to be "${ variationOnePrice }".`,
|
||||||
|
async () => {
|
||||||
|
await expect(
|
||||||
|
firstVariation.getByRole( 'textbox', {
|
||||||
|
name: 'Regular price',
|
||||||
|
} )
|
||||||
|
).toHaveValue( variationOnePrice );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Expect the second variation to be virtual.',
|
||||||
|
async () => {
|
||||||
|
await expect(
|
||||||
|
secondVariation.getByRole( 'checkbox', {
|
||||||
|
name: 'Virtual',
|
||||||
|
} )
|
||||||
|
).toBeChecked();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
`Expect the regular price of the second variation to be "${ variationTwoPrice }".`,
|
||||||
|
async () => {
|
||||||
|
await expect(
|
||||||
|
secondVariation.getByRole( 'textbox', {
|
||||||
|
name: 'Regular price',
|
||||||
|
} )
|
||||||
|
).toHaveValue( variationTwoPrice );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Expect the "Manage stock?" checkbox of the third variation to be checked.',
|
||||||
|
async () => {
|
||||||
|
await expect(
|
||||||
|
thirdVariation.getByRole( 'checkbox', {
|
||||||
|
name: 'Manage stock?',
|
||||||
|
} )
|
||||||
|
).toBeChecked();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
`Expect the regular price of the third variation to be "${ variationThreePrice }".`,
|
||||||
|
async () => {
|
||||||
|
await expect(
|
||||||
|
thirdVariation.getByRole( 'textbox', {
|
||||||
|
name: 'Regular price',
|
||||||
|
} )
|
||||||
|
).toHaveValue( variationThreePrice );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Expect the weight and dimensions of the third variation to be correct.',
|
||||||
|
async () => {
|
||||||
|
await expect(
|
||||||
|
thirdVariation.getByRole( 'textbox', { name: 'Weight' } )
|
||||||
|
).toHaveValue( productWeight );
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
thirdVariation.getByRole( 'textbox', { name: 'Length' } )
|
||||||
|
).toHaveValue( productLength );
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
thirdVariation.getByRole( 'textbox', { name: 'Width' } )
|
||||||
|
).toHaveValue( productWidth );
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
thirdVariation.getByRole( 'textbox', { name: 'Height' } )
|
||||||
|
).toHaveValue( productHeight );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can bulk edit variations', async ( { page } ) => {
|
||||||
|
await test.step( 'Go to the "Edit product" page.', async () => {
|
||||||
|
await page.goto(
|
||||||
|
`/wp-admin/post.php?post=${ fixedVariableProductId }&action=edit`
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Click on the "Variations" tab.', async () => {
|
||||||
|
await page.click( 'a[href="#variable_product_options"]' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Select the \'Toggle "Downloadable"\' bulk action.',
|
||||||
|
async () => {
|
||||||
|
await page.selectOption(
|
||||||
|
'#field_to_edit',
|
||||||
|
'toggle_downloadable'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step( 'Expand all variations.', async () => {
|
||||||
|
await page.click(
|
||||||
|
'#variable_product_options .toolbar-top a.expand_all'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Expect all "Downloadable" checkboxes to be checked.',
|
||||||
|
async () => {
|
||||||
|
const checkBoxes = page.locator(
|
||||||
|
'input[name^="variable_is_downloadable"]'
|
||||||
|
);
|
||||||
|
const count = await checkBoxes.count();
|
||||||
|
|
||||||
|
for ( let i = 0; i < count; i++ ) {
|
||||||
|
await expect( checkBoxes.nth( i ) ).toBeChecked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can delete all variations', async ( { page } ) => {
|
||||||
|
await test.step( 'Go to the "Edit product" page.', async () => {
|
||||||
|
await page.goto(
|
||||||
|
`/wp-admin/post.php?post=${ fixedVariableProductId }&action=edit`
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Click on the "Variations" tab.', async () => {
|
||||||
|
await page.click( 'a[href="#variable_product_options"]' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Select the bulk action "Delete all variations".',
|
||||||
|
async () => {
|
||||||
|
page.on( 'dialog', ( dialog ) => dialog.accept() );
|
||||||
|
await page.selectOption( '#field_to_edit', 'delete_all' );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Expect that there are no more variations.',
|
||||||
|
async () => {
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce_variation' )
|
||||||
|
).toHaveCount( 0 );
|
||||||
|
}
|
||||||
|
);
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'can manually add a variation, manage stock levels, set variation defaults and remove a variation', async ( {
|
test( 'can manually add a variation, manage stock levels, set variation defaults and remove a variation', async ( {
|
||||||
|
@ -249,11 +724,13 @@ test.describe( 'Add New Variable Product Page', () => {
|
||||||
.scrollIntoViewIfNeeded();
|
.scrollIntoViewIfNeeded();
|
||||||
|
|
||||||
// the tour only seems to display when not running headless, so just make sure
|
// the tour only seems to display when not running headless, so just make sure
|
||||||
if ( await page.locator( '.woocommerce-tour-kit-step__heading' ).isVisible() ) {
|
if (
|
||||||
// dismiss the variable product tour
|
|
||||||
await page
|
await page
|
||||||
.getByRole( 'button', { name: 'Close Tour' } )
|
.locator( '.woocommerce-tour-kit-step__heading' )
|
||||||
.click();
|
.isVisible()
|
||||||
|
) {
|
||||||
|
// dismiss the variable product tour
|
||||||
|
await page.getByRole( 'button', { name: 'Close Tour' } ).click();
|
||||||
|
|
||||||
// wait for the tour's dismissal to be saved
|
// wait for the tour's dismissal to be saved
|
||||||
await page.waitForResponse(
|
await page.waitForResponse(
|
||||||
|
|
Loading…
Reference in New Issue