Convert e2e tests to Playwright (#33462)
* Final updates for Playwright * Update config * Add uuid dependency * Increase retries to 2 * Update selectors on shipping page * Use baseURL instead of hard-coded URL for API * Clarify comment * Use baseURL instead of hard-coded URL * Check to see if an order was created before attempting to delete it * Add changelog * Turn on Playwright tests in GitHub * Increase timeout for CI execution * Update configuration options (minor edit) * Fix for checkout flaky test * Parse orderId from URL * Check for substring * Streamline email tests * Remove .only * Only clear email logs of messages for test * Get orderId from page element * Fix for test not waiting for reset * Add in second wait for Performance section * Change significance from minor to patch Co-authored-by: Jon Lane <jon.lane@automattic.com>
This commit is contained in:
parent
aed4763414
commit
0cebdf5277
|
@ -8,7 +8,7 @@ concurrency:
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
E2E_PLAYWRIGHT: ${{ false }}
|
E2E_PLAYWRIGHT: ${{ true }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
e2e-tests-run:
|
e2e-tests-run:
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Significance: patch
|
|
@ -28,9 +28,7 @@ module.exports = async ( config ) => {
|
||||||
await adminPage.fill( 'input[name="log"]', 'admin' );
|
await adminPage.fill( 'input[name="log"]', 'admin' );
|
||||||
await adminPage.fill( 'input[name="pwd"]', 'password' );
|
await adminPage.fill( 'input[name="pwd"]', 'password' );
|
||||||
await adminPage.click( 'text=Log In' );
|
await adminPage.click( 'text=Log In' );
|
||||||
await adminPage
|
await adminPage.context().storageState( { path: adminState } );
|
||||||
.context()
|
|
||||||
.storageState( { path: 'e2e/storage/adminState.json' } );
|
|
||||||
// While we're here, let's add a consumer token for API access
|
// While we're here, let's add a consumer token for API access
|
||||||
await adminPage.goto(
|
await adminPage.goto(
|
||||||
`${ baseURL }/wp-admin/admin.php?page=wc-settings&tab=advanced§ion=keys&create-key=1`
|
`${ baseURL }/wp-admin/admin.php?page=wc-settings&tab=advanced§ion=keys&create-key=1`
|
||||||
|
@ -51,8 +49,6 @@ module.exports = async ( config ) => {
|
||||||
await customerPage.fill( 'input[name="log"]', 'customer' );
|
await customerPage.fill( 'input[name="log"]', 'customer' );
|
||||||
await customerPage.fill( 'input[name="pwd"]', 'password' );
|
await customerPage.fill( 'input[name="pwd"]', 'password' );
|
||||||
await customerPage.click( 'text=Log In' );
|
await customerPage.click( 'text=Log In' );
|
||||||
await customerPage
|
await customerPage.context().storageState( { path: customerState } );
|
||||||
.context()
|
|
||||||
.storageState( { path: 'e2e/storage/customerState.json' } );
|
|
||||||
await browser.close();
|
await browser.close();
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
const { devices } = require( '@playwright/test' );
|
const { devices } = require( '@playwright/test' );
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
timeout: 20000,
|
timeout: 60 * 1000,
|
||||||
outputDir: './report',
|
outputDir: './report',
|
||||||
globalSetup: require.resolve( './global-setup' ),
|
globalSetup: require.resolve( './global-setup' ),
|
||||||
globalTeardown: require.resolve( './global-teardown' ),
|
globalTeardown: require.resolve( './global-teardown' ),
|
||||||
testDir: 'tests',
|
testDir: 'tests',
|
||||||
retries: 1,
|
retries: 2,
|
||||||
|
workers: 4,
|
||||||
reporter: [
|
reporter: [
|
||||||
[ 'list' ],
|
[ 'list' ],
|
||||||
[ 'html', { outputFolder: 'output' } ],
|
[ 'html', { outputFolder: 'output' } ],
|
||||||
|
@ -24,14 +25,6 @@ const config = {
|
||||||
name: 'Chrome',
|
name: 'Chrome',
|
||||||
use: { ...devices[ 'Desktop Chrome' ] },
|
use: { ...devices[ 'Desktop Chrome' ] },
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// name: 'Firefox',
|
|
||||||
// use: { ...devices['Desktop Firefox'] },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Webkit',
|
|
||||||
// use: { ...devices['Desktop Webkit'] },
|
|
||||||
// },
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
ID,Type,SKU,Name,Published,"Is featured?","Visibility in catalog","Short description",Description,"Date sale price starts","Date sale price ends","Tax status","Tax class","In stock?",Stock,"Backorders allowed?","Sold individually?","Weight (lbs)","Length (in)","Width (in)","Height (in)","Allow customer reviews?","Purchase note","Sale price","Regular price",Categories,Tags,"Shipping class",Images,"Download limit","Download expiry days",Parent,"Grouped products",Upsells,Cross-sells,"External URL","Button text",Position,"Attribute 1 name","Attribute 1 value(s)","Attribute 1 visible","Attribute 1 global","Attribute 2 name","Attribute 2 value(s)","Attribute 2 visible","Attribute 2 global","Meta: _wpcom_is_markdown","Download 1 name","Download 1 URL","Download 2 name","Download 2 URL"
|
ID,Type,SKU,Name,Published,"Is featured?","Visibility in catalog","Short description",Description,"Date sale price starts","Date sale price ends","Tax status","Tax class","In stock?",Stock,"Backorders allowed?","Sold individually?","Weight (lbs)","Length (in)","Width (in)","Height (in)","Allow customer reviews?","Purchase note","Sale price","Regular price",Categories,Tags,"Shipping class",Images,"Download limit","Download expiry days",Parent,"Grouped products",Upsells,Cross-sells,"External URL","Button text",Position,"Attribute 1 name","Attribute 1 value(s)","Attribute 1 visible","Attribute 1 global","Attribute 2 name","Attribute 2 value(s)","Attribute 2 visible","Attribute 2 global","Meta: _wpcom_is_markdown","Download 1 name","Download 1 URL","Download 2 name","Download 2 URL"
|
||||||
44,variable,woo-vneck-tee,"V-Neck T-Shirt",1,1,visible,"This is a variable product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,.5,24,1,2,1,,,,"Clothing > Tshirts",,,"https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vneck-tee-2.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-green-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-blue-1.jpg",,,,,,,,,0,Color,"Blue, Green, Red",1,1,Size,"Large, Medium, Small",1,1,1,,,,
|
44,variable,woo-vneck-tee,"Imported V-Neck T-Shirt",1,1,visible,"This is a variable product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,.5,24,1,2,1,,,,"Clothing > Tshirts",,,"https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vneck-tee-2.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-green-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-blue-1.jpg",,,,,,,,,0,Color,"Blue, Green, Red",1,1,Size,"Large, Medium, Small",1,1,1,,,,
|
||||||
45,variable,woo-hoodie,Hoodie,1,0,visible,"This is a variable product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,1.5,10,8,3,1,,,,"Clothing > Hoodies",,,"https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-2.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-blue-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-green-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg",,,,,,,,,0,Color,"Blue, Green, Red",1,1,Logo,"Yes, No",1,0,1,,,,
|
45,variable,woo-hoodie,"Imported Hoodie",1,0,visible,"This is a variable product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,1.5,10,8,3,1,,,,"Clothing > Hoodies",,,"https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-2.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-blue-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-green-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg",,,,,,,,,0,Color,"Blue, Green, Red",1,1,Logo,"Yes, No",1,0,1,,,,
|
||||||
46,simple,woo-hoodie-with-logo,"Hoodie with Logo",1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,2,10,6,3,1,,,45,"Clothing > Hoodies",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg,,,,,,,,,0,Color,Blue,1,1,,,,,1,,,,
|
46,simple,woo-hoodie-with-logo,"Imported Hoodie with Logo",1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,2,10,6,3,1,,,45,"Clothing > Hoodies",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg,,,,,,,,,0,Color,Blue,1,1,,,,,1,,,,
|
||||||
47,simple,woo-tshirt,T-Shirt,1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,.8,8,6,1,1,,,18,"Clothing > Tshirts",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/tshirt-2.jpg,,,,,,,,,0,Color,Gray,1,1,,,,,1,,,,
|
47,simple,woo-tshirt,"Imported T-Shirt",1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,.8,8,6,1,1,,,18,"Clothing > Tshirts",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/tshirt-2.jpg,,,,,,,,,0,Color,Gray,1,1,,,,,1,,,,
|
||||||
48,simple,woo-beanie,Beanie,1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,.2,4,5,.5,1,,18,20,"Clothing > Accessories",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-2.jpg,,,,,,,,,0,Color,Red,1,1,,,,,1,,,,
|
48,simple,woo-beanie,"Imported Beanie",1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,.2,4,5,.5,1,,18,20,"Clothing > Accessories",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-2.jpg,,,,,,,,,0,Color,Red,1,1,,,,,1,,,,
|
||||||
58,simple,woo-belt,Belt,1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,1.2,12,2,1.5,1,,55,65,"Clothing > Accessories",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/belt-2.jpg,,,,,,,,,0,,,,,,,,,1,,,,
|
58,simple,woo-belt,"Imported Belt",1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,1.2,12,2,1.5,1,,55,65,"Clothing > Accessories",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/belt-2.jpg,,,,,,,,,0,,,,,,,,,1,,,,
|
||||||
60,simple,woo-cap,Cap,1,1,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,0.6,8,6.5,4,1,,16,18,"Clothing > Accessories",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/cap-2.jpg,,,,,,,,,0,Color,Yellow,1,1,,,,,1,,,,
|
60,simple,woo-cap,"Imported Cap",1,1,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,0.6,8,6.5,4,1,,16,18,"Clothing > Accessories",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/cap-2.jpg,,,,,,,,,0,Color,Yellow,1,1,,,,,1,,,,
|
||||||
62,simple,woo-sunglasses,Sunglasses,1,1,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,.2,4,1.4,1,1,,,90,"Clothing > Accessories",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/sunglasses-2.jpg,,,,,,,,,0,,,,,,,,,1,,,,
|
62,simple,woo-sunglasses,"Imported Sunglasses",1,1,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,.2,4,1.4,1,1,,,90,"Clothing > Accessories",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/sunglasses-2.jpg,,,,,,,,,0,,,,,,,,,1,,,,
|
||||||
64,simple,woo-hoodie-with-pocket,"Hoodie with Pocket",1,1,hidden,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,3,10,8,2,1,,35,45,"Clothing > Hoodies",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-pocket-2.jpg,,,,,,,,,0,Color,Gray,1,1,,,,,1,,,,
|
64,simple,woo-hoodie-with-pocket,"Imported Hoodie with Pocket",1,1,hidden,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,3,10,8,2,1,,35,45,"Clothing > Hoodies",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-pocket-2.jpg,,,,,,,,,0,Color,Gray,1,1,,,,,1,,,,
|
||||||
66,simple,woo-hoodie-with-zipper,"Hoodie with Zipper",1,1,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,2,8,6,2,1,,,45,"Clothing > Hoodies",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-zipper-2.jpg,,,,,,,,,0,,,,,,,,,1,,,,
|
66,simple,woo-hoodie-with-zipper,"Imported Hoodie with Zipper",1,1,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,2,8,6,2,1,,,45,"Clothing > Hoodies",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-zipper-2.jpg,,,,,,,,,0,,,,,,,,,1,,,,
|
||||||
68,simple,woo-long-sleeve-tee,"Long Sleeve Tee",1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,1,7,5,1,1,,,25,"Clothing > Tshirts",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/long-sleeve-tee-2.jpg,,,,,,,,,0,Color,Green,1,1,,,,,1,,,,
|
68,simple,woo-long-sleeve-tee,"Imported Long Sleeve Tee",1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,1,7,5,1,1,,,25,"Clothing > Tshirts",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/long-sleeve-tee-2.jpg,,,,,,,,,0,Color,Green,1,1,,,,,1,,,,
|
||||||
70,simple,woo-polo,Polo,1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,.8,6,5,1,1,,,20,"Clothing > Tshirts",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/polo-2.jpg,,,,,,,,,0,Color,Blue,1,1,,,,,1,,,,
|
70,simple,woo-polo,"Imported Polo",1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,.8,6,5,1,1,,,20,"Clothing > Tshirts",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/polo-2.jpg,,,,,,,,,0,Color,Blue,1,1,,,,,1,,,,
|
||||||
73,"simple, downloadable, virtual",woo-album,Album,1,0,visible,"This is a simple, virtual product.","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,1,,,15,Music,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/album-1.jpg,1,1,,,,,,,0,,,,,,,,,1,"Single 1",https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg,"Single 2",https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/album.jpg
|
73,"simple, downloadable, virtual",woo-album,"Imported Album",1,0,visible,"This is a simple, virtual product.","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,1,,,15,Music,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/album-1.jpg,1,1,,,,,,,0,,,,,,,,,1,"Single 1",https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg,"Single 2",https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/album.jpg
|
||||||
75,"simple, downloadable, virtual",woo-single,Single,1,0,visible,"This is a simple, virtual product.","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,1,,2,3,Music,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/single-1.jpg,1,1,,,,,,,0,,,,,,,,,1,Single,https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg,,
|
75,"simple, downloadable, virtual",woo-single,"Imported Single",1,0,visible,"This is a simple, virtual product.","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,1,,2,3,Music,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/single-1.jpg,1,1,,,,,,,0,,,,,,,,,1,Single,https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg,,
|
||||||
76,variation,woo-vneck-tee-red,"V-Neck T-Shirt - Red",1,0,visible,,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,0,,,20,,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vneck-tee-2.jpg,,,woo-vneck-tee,,,,,,0,Color,Red,,1,Size,,,1,,,,,
|
76,variation,woo-vneck-tee-red,"Imported V-Neck T-Shirt - Red",1,0,visible,,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,0,,,20,,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vneck-tee-2.jpg,,,woo-vneck-tee,,,,,,0,Color,Red,,1,Size,,,1,,,,,
|
||||||
77,variation,woo-vneck-tee-green,"V-Neck T-Shirt - Green",1,0,visible,,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,0,,,20,,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-green-1.jpg,,,woo-vneck-tee,,,,,,0,Color,Green,,1,Size,,,1,,,,,
|
77,variation,woo-vneck-tee-green,"Imported V-Neck T-Shirt - Green",1,0,visible,,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,0,,,20,,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-green-1.jpg,,,woo-vneck-tee,,,,,,0,Color,Green,,1,Size,,,1,,,,,
|
||||||
78,variation,woo-vneck-tee-blue,"V-Neck T-Shirt - Blue",1,0,visible,,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,0,,,15,,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-blue-1.jpg,,,woo-vneck-tee,,,,,,0,Color,Blue,,1,Size,,,1,,,,,
|
78,variation,woo-vneck-tee-blue,"Imported V-Neck T-Shirt - Blue",1,0,visible,,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,0,,,15,,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-blue-1.jpg,,,woo-vneck-tee,,,,,,0,Color,Blue,,1,Size,,,1,,,,,
|
||||||
79,variation,woo-hoodie-red,"Hoodie - Red, No",1,0,visible,,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,0,,42,45,,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-2.jpg,,,woo-hoodie,,,,,,1,Color,Red,,1,Logo,No,,0,,,,,
|
79,variation,woo-hoodie-red,"Imported Hoodie - Red, No",1,0,visible,,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,0,,42,45,,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-2.jpg,,,woo-hoodie,,,,,,1,Color,Red,,1,Logo,No,,0,,,,,
|
||||||
80,variation,woo-hoodie-green,"Hoodie - Green, No",1,0,visible,,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,0,,,45,,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-green-1.jpg,,,woo-hoodie,,,,,,2,Color,Green,,1,Logo,No,,0,,,,,
|
80,variation,woo-hoodie-green,"Imported Hoodie - Green, No",1,0,visible,,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,0,,,45,,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-green-1.jpg,,,woo-hoodie,,,,,,2,Color,Green,,1,Logo,No,,0,,,,,
|
||||||
81,variation,woo-hoodie-blue,"Hoodie - Blue, No",1,0,visible,,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,0,,,45,,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-blue-1.jpg,,,woo-hoodie,,,,,,3,Color,Blue,,1,Logo,No,,0,,,,,
|
81,variation,woo-hoodie-blue,"Imported Hoodie - Blue, No",1,0,visible,,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,0,,,45,,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-blue-1.jpg,,,woo-hoodie,,,,,,3,Color,Blue,,1,Logo,No,,0,,,,,
|
||||||
83,simple,Woo-tshirt-logo,"T-Shirt with Logo",1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,.5,10,12,.5,1,,,18,"Clothing > Tshirts",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/t-shirt-with-logo-1.jpg,,,,,,,,,0,Color,Gray,1,1,,,,,1,,,,
|
83,simple,Woo-tshirt-logo,"Imported T-Shirt with Logo",1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,.5,10,12,.5,1,,,18,"Clothing > Tshirts",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/t-shirt-with-logo-1.jpg,,,,,,,,,0,Color,Gray,1,1,,,,,1,,,,
|
||||||
85,simple,Woo-beanie-logo,"Beanie with Logo",1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,.2,6,4,1,1,,18,20,"Clothing > Accessories",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-with-logo-1.jpg,,,,,,,,,0,Color,Red,1,1,,,,,1,,,,
|
85,simple,Woo-beanie-logo,"Imported Beanie with Logo",1,0,visible,"This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,.2,6,4,1,1,,18,20,"Clothing > Accessories",,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-with-logo-1.jpg,,,,,,,,,0,Color,Red,1,1,,,,,1,,,,
|
||||||
87,grouped,logo-collection,"Logo Collection",1,0,visible,"This is a grouped product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,,,,,1,,,,Clothing,,,"https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/logo-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-with-logo-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/t-shirt-with-logo-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg",,,,"woo-hoodie-with-logo, woo-tshirt, woo-beanie",,,,,0,,,,,,,,,1,,,,
|
87,grouped,logo-collection,"Imported Logo Collection",1,0,visible,"This is a grouped product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,,,,,1,,,,Clothing,,,"https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/logo-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-with-logo-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/t-shirt-with-logo-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg",,,,"woo-hoodie-with-logo, woo-tshirt, woo-beanie",,,,,0,,,,,,,,,1,,,,
|
||||||
89,external,wp-pennant,"WordPress Pennant",1,0,visible,"This is an external product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,,,,,1,,,11.05,Decor,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/pennant-1.jpg,,,,,,,https://mercantile.wordpress.org/product/wordpress-pennant/,"Buy on the WordPress swag store!",0,,,,,,,,,1,,,,
|
89,external,wp-pennant,"Imported WordPress Pennant",1,0,visible,"This is an external product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,taxable,,1,,0,0,,,,,1,,,11.05,Decor,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/pennant-1.jpg,,,,,,,https://mercantile.wordpress.org/product/wordpress-pennant/,"Buy on the WordPress swag store!",0,,,,,,,,,1,,,,
|
||||||
90,variation,woo-hoodie-blue-logo,"Hoodie - Blue, Yes",1,0,visible,,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,0,,,45,,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg,,,woo-hoodie,,,,,,0,Color,Blue,,1,Logo,Yes,,0,,,,,
|
90,variation,woo-hoodie-blue-logo,"Imported Hoodie - Blue, Yes",1,0,visible,,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,taxable,,1,,0,0,,,,,0,,,45,,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg,,,woo-hoodie,,,,,,0,Color,Blue,,1,Logo,Yes,,0,,,,,
|
||||||
|
|
|
|
@ -1,26 +1,26 @@
|
||||||
ID,Type,SKU,Name,Published,"Is featured?","Visibility in catalog","Short description",Description,"Date sale price starts","Date sale price ends","Tax status","Tax class","In stock?",Stock,"Backorders allowed?","Sold individually?","Weight (lbs)","Length (in)","Width (in)","Height (in)","Allow customer reviews?","Purchase note","Sale price","Regular price",Categories,Tags,"Shipping class",Images,"Download limit","Download expiry days",Parent,"Grouped products",Upsells,Cross-sells,"External URL","Button text",Position,"Attribute 1 name","Attribute 1 value(s)","Attribute 1 visible","Attribute 1 global","Attribute 2 name","Attribute 2 value(s)","Attribute 2 visible","Attribute 2 global","Meta: _wpcom_is_markdown","Download 1 name","Download 1 URL","Download 2 name","Download 2 URL"
|
ID,Type,SKU,Name,Published,"Is featured?","Visibility in catalog","Short description",Description,"Date sale price starts","Date sale price ends","Tax status","Tax class","In stock?",Stock,"Backorders allowed?","Sold individually?","Weight (lbs)","Length (in)","Width (in)","Height (in)","Allow customer reviews?","Purchase note","Sale price","Regular price",Categories,Tags,"Shipping class",Images,"Download limit","Download expiry days",Parent,"Grouped products",Upsells,Cross-sells,"External URL","Button text",Position,"Attribute 1 name","Attribute 1 value(s)","Attribute 1 visible","Attribute 1 global","Attribute 2 name","Attribute 2 value(s)","Attribute 2 visible","Attribute 2 global","Meta: _wpcom_is_markdown","Download 1 name","Download 1 URL","Download 2 name","Download 2 URL"
|
||||||
,variable,woo-vneck-tee,V-Neck T-Shirt Override,1,"1","visible","This is a variable product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",".5","24","1","2","1",,,,Clothing > Tshirts,,,"https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vneck-tee-2.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-green-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-blue-1.jpg",,,,,,,,,0,"Color","Blue, Green, Red","1","1","Size","Large, Medium, Small","1","1","1",,,,
|
,variable,woo-vneck-tee,Imported V-Neck T-Shirt Override,1,"1","visible","This is a variable product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",".5","24","1","2","1",,,,Clothing > Tshirts,,,"https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vneck-tee-2.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-green-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-blue-1.jpg",,,,,,,,,0,"Color","Blue, Green, Red","1","1","Size","Large, Medium, Small","1","1","1",,,,
|
||||||
,variable,woo-hoodie,Hoodie Override,1,"0","visible","This is a variable product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0","1.5","10","8","3","1",,,,Clothing > Hoodies,,,"https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-2.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-blue-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-green-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg",,,,,,,,,0,"Color","Blue, Green, Red","1","1","Logo","Yes, No","1","0","1",,,,
|
,variable,woo-hoodie,Imported Hoodie Override,1,"0","visible","This is a variable product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0","1.5","10","8","3","1",,,,Clothing > Hoodies,,,"https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-2.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-blue-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-green-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg",,,,,,,,,0,"Color","Blue, Green, Red","1","1","Logo","Yes, No","1","0","1",,,,
|
||||||
,simple,woo-hoodie-with-logo,Hoodie with Logo Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0","2","10","6","3","1",,,"145",Clothing > Hoodies,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg,,,,,,,,,0,"Color","Blue","1","1",,,,,"1",,,,
|
,simple,woo-hoodie-with-logo,Imported Hoodie with Logo Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0","2","10","6","3","1",,,"145",Clothing > Hoodies,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg,,,,,,,,,0,"Color","Blue","1","1",,,,,"1",,,,
|
||||||
,simple,woo-tshirt,T-Shirt Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",".8","8","6","1","1",,,"118",Clothing > Tshirts,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/tshirt-2.jpg,,,,,,,,,0,"Color","Gray","1","1",,,,,"1",,,,
|
,simple,woo-tshirt,Imported T-Shirt Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",".8","8","6","1","1",,,"118",Clothing > Tshirts,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/tshirt-2.jpg,,,,,,,,,0,"Color","Gray","1","1",,,,,"1",,,,
|
||||||
,simple,woo-beanie,Beanie Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",".2","4","5",".5","1",,"118","120",Clothing > Accessories,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-2.jpg,,,,,,,,,0,"Color","Red","1","1",,,,,"1",,,,
|
,simple,woo-beanie,Imported Beanie Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",".2","4","5",".5","1",,"118","120",Clothing > Accessories,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-2.jpg,,,,,,,,,0,"Color","Red","1","1",,,,,"1",,,,
|
||||||
,simple,woo-belt,Belt Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0","1.2","12","2","1.5","1",,"155","165",Clothing > Accessories,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/belt-2.jpg,,,,,,,,,0,,,,,,,,,"1",,,,
|
,simple,woo-belt,Imported Belt Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0","1.2","12","2","1.5","1",,"155","165",Clothing > Accessories,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/belt-2.jpg,,,,,,,,,0,,,,,,,,,"1",,,,
|
||||||
,simple,woo-cap,Cap Override,1,"1","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0","0.6","8","6.5","4","1",,"116","118",Clothing > Accessories,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/cap-2.jpg,,,,,,,,,0,"Color","Yellow","1","1",,,,,"1",,,,
|
,simple,woo-cap,Imported Cap Override,1,"1","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0","0.6","8","6.5","4","1",,"116","118",Clothing > Accessories,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/cap-2.jpg,,,,,,,,,0,"Color","Yellow","1","1",,,,,"1",,,,
|
||||||
,simple,woo-sunglasses,Sunglasses Override,1,"1","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",".2","4","1.4","1","1",,,"190",Clothing > Accessories,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/sunglasses-2.jpg,,,,,,,,,0,,,,,,,,,"1",,,,
|
,simple,woo-sunglasses,Imported Sunglasses Override,1,"1","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",".2","4","1.4","1","1",,,"190",Clothing > Accessories,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/sunglasses-2.jpg,,,,,,,,,0,,,,,,,,,"1",,,,
|
||||||
,simple,woo-hoodie-with-pocket,Hoodie with Pocket Override,1,"1","hidden","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0","3","10","8","2","1",,"135","145",Clothing > Hoodies,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-pocket-2.jpg,,,,,,,,,0,"Color","Gray","1","1",,,,,"1",,,,
|
,simple,woo-hoodie-with-pocket,Imported Hoodie with Pocket Override,1,"1","hidden","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0","3","10","8","2","1",,"135","145",Clothing > Hoodies,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-pocket-2.jpg,,,,,,,,,0,"Color","Gray","1","1",,,,,"1",,,,
|
||||||
,simple,woo-hoodie-with-zipper,Hoodie with Zipper Override,1,"1","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0","2","8","6","2","1",,,"145",Clothing > Hoodies,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-zipper-2.jpg,,,,,,,,,0,,,,,,,,,"1",,,,
|
,simple,woo-hoodie-with-zipper,Imported Hoodie with Zipper Override,1,"1","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0","2","8","6","2","1",,,"145",Clothing > Hoodies,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-zipper-2.jpg,,,,,,,,,0,,,,,,,,,"1",,,,
|
||||||
,simple,woo-long-sleeve-tee,Long Sleeve Tee Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0","1","7","5","1","1",,,"125",Clothing > Tshirts,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/long-sleeve-tee-2.jpg,,,,,,,,,0,"Color","Green","1","1",,,,,"1",,,,
|
,simple,woo-long-sleeve-tee,Imported Long Sleeve Tee Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0","1","7","5","1","1",,,"125",Clothing > Tshirts,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/long-sleeve-tee-2.jpg,,,,,,,,,0,"Color","Green","1","1",,,,,"1",,,,
|
||||||
,simple,woo-polo,Polo Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",".8","6","5","1","1",,,"120",Clothing > Tshirts,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/polo-2.jpg,,,,,,,,,0,"Color","Blue","1","1",,,,,"1",,,,
|
,simple,woo-polo,Imported Polo Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",".8","6","5","1","1",,,"120",Clothing > Tshirts,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/polo-2.jpg,,,,,,,,,0,"Color","Blue","1","1",,,,,"1",,,,
|
||||||
,"simple, downloadable, virtual",woo-album,Album Override,1,"0","visible","This is a simple, virtual product.","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"1",,,"115",Music,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/album-1.jpg,"1","1",,,,,,,0,,,,,,,,,"1","Single 1","https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg","Single 2","https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/album.jpg"
|
,"simple, downloadable, virtual",woo-album,Imported Album Override,1,"0","visible","This is a simple, virtual product.","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"1",,,"115",Music,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/album-1.jpg,"1","1",,,,,,,0,,,,,,,,,"1","Single 1","https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg","Single 2","https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/album.jpg"
|
||||||
,"simple, downloadable, virtual",woo-single,Single Override,1,"0","visible","This is a simple, virtual product.","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"1",,"12","13",Music,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/single-1.jpg,"1","1",,,,,,,0,,,,,,,,,"1","Single","https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg",,
|
,"simple, downloadable, virtual",woo-single,Imported Single Override,1,"0","visible","This is a simple, virtual product.","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"1",,"12","13",Music,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/single-1.jpg,"1","1",,,,,,,0,,,,,,,,,"1","Single","https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg",,
|
||||||
,variation,woo-vneck-tee-red,V-Neck T-Shirt - Red Override,1,"0","visible",,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"0",,,"120",,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vneck-tee-2.jpg,,,woo-vneck-tee,,,,,,0,"Color","Red",,"1","Size",,,"1",,,,,
|
,variation,woo-vneck-tee-red,Imported V-Neck T-Shirt - Red Override,1,"0","visible",,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"0",,,"120",,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vneck-tee-2.jpg,,,woo-vneck-tee,,,,,,0,"Color","Red",,"1","Size",,,"1",,,,,
|
||||||
,variation,woo-vneck-tee-green,V-Neck T-Shirt - Green Override,1,"0","visible",,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"0",,,"120",,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-green-1.jpg,,,woo-vneck-tee,,,,,,0,"Color","Green",,"1","Size",,,"1",,,,,
|
,variation,woo-vneck-tee-green,Imported V-Neck T-Shirt - Green Override,1,"0","visible",,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"0",,,"120",,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-green-1.jpg,,,woo-vneck-tee,,,,,,0,"Color","Green",,"1","Size",,,"1",,,,,
|
||||||
,variation,woo-vneck-tee-blue,V-Neck T-Shirt - Blue Override,1,"0","visible",,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"0",,,"115",,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-blue-1.jpg,,,woo-vneck-tee,,,,,,0,"Color","Blue",,"1","Size",,,"1",,,,,
|
,variation,woo-vneck-tee-blue,Imported V-Neck T-Shirt - Blue Override,1,"0","visible",,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"0",,,"115",,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/vnech-tee-blue-1.jpg,,,woo-vneck-tee,,,,,,0,"Color","Blue",,"1","Size",,,"1",,,,,
|
||||||
,variation,woo-hoodie-red,"Hoodie - Red, No Override",1,"0","visible",,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"0",,"142","145",,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-2.jpg,,,woo-hoodie,,,,,,1,"Color","Red",,"1","Logo","No",,"0",,,,,
|
,variation,woo-hoodie-red,"Imported Hoodie - Red, No Override",1,"0","visible",,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"0",,"142","145",,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-2.jpg,,,woo-hoodie,,,,,,1,"Color","Red",,"1","Logo","No",,"0",,,,,
|
||||||
,variation,woo-hoodie-green,"Hoodie - Green, No Override",1,"0","visible",,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"0",,,"145",,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-green-1.jpg,,,woo-hoodie,,,,,,2,"Color","Green",,"1","Logo","No",,"0",,,,,
|
,variation,woo-hoodie-green,"Imported Hoodie - Green, No Override",1,"0","visible",,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"0",,,"145",,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-green-1.jpg,,,woo-hoodie,,,,,,2,"Color","Green",,"1","Logo","No",,"0",,,,,
|
||||||
,variation,woo-hoodie-blue,"Hoodie - Blue, No Override",1,"0","visible",,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"0",,,"145",,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-blue-1.jpg,,,woo-hoodie,,,,,,3,"Color","Blue",,"1","Logo","No",,"0",,,,,
|
,variation,woo-hoodie-blue,"Imported Hoodie - Blue, No Override",1,"0","visible",,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"0",,,"145",,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-blue-1.jpg,,,woo-hoodie,,,,,,3,"Color","Blue",,"1","Logo","No",,"0",,,,,
|
||||||
,simple,Woo-tshirt-logo,T-Shirt with Logo Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",".5","10","12",".5","1",,,"118",Clothing > Tshirts,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/t-shirt-with-logo-1.jpg,,,,,,,,,0,"Color","Gray","1","1",,,,,"1",,,,
|
,simple,Woo-tshirt-logo,Imported T-Shirt with Logo Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",".5","10","12",".5","1",,,"118",Clothing > Tshirts,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/t-shirt-with-logo-1.jpg,,,,,,,,,0,"Color","Gray","1","1",,,,,"1",,,,
|
||||||
,simple,Woo-beanie-logo,Beanie with Logo Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",".2","6","4","1","1",,"118","120",Clothing > Accessories,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-with-logo-1.jpg,,,,,,,,,0,"Color","Red","1","1",,,,,"1",,,,
|
,simple,Woo-beanie-logo,Imported Beanie with Logo Override,1,"0","visible","This is a simple product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",".2","6","4","1","1",,"118","120",Clothing > Accessories,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-with-logo-1.jpg,,,,,,,,,0,"Color","Red","1","1",,,,,"1",,,,
|
||||||
,grouped,logo-collection,Logo Collection Override,1,"0","visible","This is a grouped product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",,,,,"1",,,,Clothing,,,"https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/logo-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-with-logo-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/t-shirt-with-logo-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg",,,,"woo-hoodie-with-logo, woo-tshirt, woo-beanie",,,,,0,,,,,,,,,"1",,,,
|
,grouped,logo-collection,Imported Logo Collection Override,1,"0","visible","This is a grouped product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",,,,,"1",,,,Clothing,,,"https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/logo-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-with-logo-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/t-shirt-with-logo-1.jpg, https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg",,,,"woo-hoodie-with-logo, woo-tshirt, woo-beanie",,,,,0,,,,,,,,,"1",,,,
|
||||||
,external,wp-pennant,WordPress Pennant Override,1,"0","visible","This is an external product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",,,,,"1",,,"111.05",Decor,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/pennant-1.jpg,,,,,,,"https://mercantile.wordpress.org/product/wordpress-pennant/","Buy on the WordPress swag store!",0,,,,,,,,,"1",,,,
|
,external,wp-pennant,Imported WordPress Pennant Override,1,"0","visible","This is an external product.","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",,,"taxable",,"1",,"0","0",,,,,"1",,,"111.05",Decor,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/pennant-1.jpg,,,,,,,"https://mercantile.wordpress.org/product/wordpress-pennant/","Buy on the WordPress swag store!",0,,,,,,,,,"1",,,,
|
||||||
,variation,woo-hoodie-blue-logo,"Hoodie - Blue, Yes Override",1,"0","visible",,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"0",,,"145",,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg,,,woo-hoodie,,,,,,0,"Color","Blue",,"1","Logo","Yes",,"0",,,,,
|
,variation,woo-hoodie-blue-logo,"Imported Hoodie - Blue, Yes Override",1,"0","visible",,"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sagittis orci ac odio dictum tincidunt. Donec ut metus leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed luctus, dui eu sagittis sodales, nulla nibh sagittis augue, vel porttitor diam enim non metus. Vestibulum aliquam augue neque. Phasellus tincidunt odio eget ullamcorper efficitur. Cras placerat ut turpis pellentesque vulputate. Nam sed consequat tortor. Curabitur finibus sapien dolor. Ut eleifend tellus nec erat pulvinar dignissim. Nam non arcu purus. Vivamus et massa massa.",,,"taxable",,"1",,"0","0",,,,,"0",,,"145",,,,https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-with-logo-2.jpg,,,woo-hoodie,,,,,,0,"Color","Blue",,"1","Logo","Yes",,"0",,,,,
|
||||||
|
|
|
|
@ -3,16 +3,16 @@ const { test, expect } = require( '@playwright/test' );
|
||||||
test.describe( 'Store owner can finish initial store setup', () => {
|
test.describe( 'Store owner can finish initial store setup', () => {
|
||||||
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
test( 'can enable tax rates and calculations', async ( { page } ) => {
|
test( 'can enable tax rates and calculations', async ( { page } ) => {
|
||||||
await page.goto( '/wp-admin/admin.php?page=wc-settings' );
|
await page.goto( 'wp-admin/admin.php?page=wc-settings' );
|
||||||
// Check the enable taxes checkbox
|
// Check the enable taxes checkbox
|
||||||
await page.check( '#woocommerce_calc_taxes' );
|
await page.check( '#woocommerce_calc_taxes' );
|
||||||
await page.click( 'text=Save changes' );
|
await page.click( 'text=Save changes' );
|
||||||
// Verify changes have been saved
|
// Verify changes have been saved
|
||||||
expect( page.isChecked( '#woocommerce_calc_taxes' ) ).toBeTruthy();
|
await expect( page.locator( '#woocommerce_calc_taxes' ) ).toBeChecked();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'can configure permalink settings', async ( { page } ) => {
|
test( 'can configure permalink settings', async ( { page } ) => {
|
||||||
await page.goto( '/wp-admin/options-permalink.php' );
|
await page.goto( 'wp-admin/options-permalink.php' );
|
||||||
// Select "Post name" option in common settings section
|
// Select "Post name" option in common settings section
|
||||||
await page.check( 'label >> text=Post name' );
|
await page.check( 'label >> text=Post name' );
|
||||||
// Select "Custom base" in product permalinks section
|
// Select "Custom base" in product permalinks section
|
||||||
|
@ -21,20 +21,14 @@ test.describe( 'Store owner can finish initial store setup', () => {
|
||||||
await page.fill( '#woocommerce_permalink_structure', '/product/' );
|
await page.fill( '#woocommerce_permalink_structure', '/product/' );
|
||||||
await page.click( '#submit' );
|
await page.click( '#submit' );
|
||||||
// Verify that settings have been saved
|
// Verify that settings have been saved
|
||||||
await page.waitForLoadState( 'networkidle' ); // not autowaiting for form submission
|
await expect(
|
||||||
const notice = await page.textContent(
|
page.locator( '#setting-error-settings_updated' )
|
||||||
'#setting-error-settings_updated'
|
).toContainText( 'Permalink structure updated.' );
|
||||||
|
await expect( page.locator( '#permalink_structure' ) ).toHaveValue(
|
||||||
|
'/%postname%/'
|
||||||
);
|
);
|
||||||
expect( notice ).toContain( 'Permalink structure updated.' );
|
await expect(
|
||||||
const postSlug = await page.getAttribute(
|
page.locator( '#woocommerce_permalink_structure' )
|
||||||
'#permalink_structure',
|
).toHaveValue( '/product/' );
|
||||||
'value'
|
|
||||||
);
|
|
||||||
expect( postSlug ).toBe( '/%postname%/' );
|
|
||||||
const wcSlug = await page.getAttribute(
|
|
||||||
'#woocommerce_permalink_structure',
|
|
||||||
'value'
|
|
||||||
);
|
|
||||||
expect( wcSlug ).toBe( '/product/' );
|
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -156,8 +156,9 @@ test.describe( 'Store owner can complete onboarding wizard', () => {
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
// !Changed from Japanese to Malta store, as Japanese Yen does not use decimals
|
||||||
test.describe(
|
test.describe(
|
||||||
'A japanese store can complete the selective bundle install but does not include WCPay.',
|
'A Malta store can complete the selective bundle install but does not include WCPay.',
|
||||||
() => {
|
() => {
|
||||||
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
|
|
||||||
|
@ -171,11 +172,11 @@ test.describe(
|
||||||
await page.click( '#woocommerce-select-control-0__control-input' );
|
await page.click( '#woocommerce-select-control-0__control-input' );
|
||||||
await page.fill(
|
await page.fill(
|
||||||
'#woocommerce-select-control-0__control-input',
|
'#woocommerce-select-control-0__control-input',
|
||||||
'Japan — Hokkaido'
|
'Malta'
|
||||||
);
|
);
|
||||||
await page.click( 'button >> text=Japan — Hokkaido' );
|
await page.click( 'button >> text=Malta' );
|
||||||
await page.fill( '#inspector-text-control-2', 'Sapporo' );
|
await page.fill( '#inspector-text-control-2', 'Valletta' );
|
||||||
await page.fill( '#inspector-text-control-3', '007-0852' );
|
await page.fill( '#inspector-text-control-3', 'VLT 1011' );
|
||||||
await page.fill(
|
await page.fill(
|
||||||
'#inspector-text-control-4',
|
'#inspector-text-control-4',
|
||||||
'admin@woocommercecoree2etestsuite.com'
|
'admin@woocommercecoree2etestsuite.com'
|
||||||
|
@ -294,29 +295,16 @@ test.describe( 'Store owner can go through setup Task List', () => {
|
||||||
|
|
||||||
test( 'can setup shipping', async ( { page } ) => {
|
test( 'can setup shipping', async ( { page } ) => {
|
||||||
await page.goto( '/wp-admin/admin.php?page=wc-admin' );
|
await page.goto( '/wp-admin/admin.php?page=wc-admin' );
|
||||||
// Close the welcome dialog if it's present
|
await page.click( 'text="Set up shipping"' );
|
||||||
await page.waitForLoadState( 'networkidle' ); // explictly wait because the welcome dialog loads last
|
|
||||||
const welcomeDialog = await page.$( '.components-modal__header' );
|
|
||||||
if ( welcomeDialog !== null ) {
|
|
||||||
await page.click(
|
|
||||||
'div.components-modal__header >> button.components-button'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
await expect( welcomeDialog ).not.toBeVisible();
|
|
||||||
await page
|
|
||||||
.locator( 'li[role="button"]:has-text("Set up shipping1 minute")' )
|
|
||||||
.click();
|
|
||||||
|
|
||||||
const shippingPage = await page.textContent( 'h1' );
|
// check if this is the first time (or if the test is being retried)
|
||||||
if ( shippingPage === 'Shipping' ) {
|
const currPage = page.url();
|
||||||
|
if ( currPage.indexOf( 'page=wc-settings&tab=shipping' ) > 0 ) {
|
||||||
// click the Add shipping zone button on the shipping settings page
|
// click the Add shipping zone button on the shipping settings page
|
||||||
await page.locator( '.page-title-action' ).click();
|
await page.locator( '.page-title-action' ).click();
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( 'h2', {
|
page.locator( 'div.woocommerce > form > h2' )
|
||||||
hasText: 'Shipping zones',
|
).toContainText( 'Shipping zones' );
|
||||||
} )
|
|
||||||
).toBeVisible();
|
|
||||||
} else {
|
} else {
|
||||||
await page.locator( 'button.components-button.is-primary' ).click();
|
await page.locator( 'button.components-button.is-primary' ).click();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,9 @@ test.describe( 'Analytics pages', () => {
|
||||||
await page.goto(
|
await page.goto(
|
||||||
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
// Grab all of the section headings
|
// Grab all of the section headings
|
||||||
const sections = await page.$$(
|
const sections = await page.$$(
|
||||||
'h2.woocommerce-section-header__title'
|
'h2.woocommerce-section-header__title'
|
||||||
|
@ -25,51 +28,6 @@ test.describe( 'Analytics pages', () => {
|
||||||
);
|
);
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'should allow a user to remove a section', async ( { page } ) => {
|
|
||||||
await page.goto(
|
|
||||||
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
|
||||||
);
|
|
||||||
// clicks the first button to the right of the Performance heading
|
|
||||||
await page
|
|
||||||
.locator( 'button:right-of(:text("Performance")) >> nth=0' )
|
|
||||||
.click();
|
|
||||||
await page.locator( 'text=Remove section' ).click();
|
|
||||||
// Grab all of the section headings
|
|
||||||
const sections = await page.$$(
|
|
||||||
'h2.woocommerce-section-header__title'
|
|
||||||
);
|
|
||||||
await expect( sections.length ).toEqual( 2 );
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
await page.locator( '//button[@title="Add more sections"]' ).click();
|
|
||||||
await page
|
|
||||||
.locator( '//button[@title="Add Performance section"]' )
|
|
||||||
.click();
|
|
||||||
await page.waitForLoadState( 'networkidle' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
test( 'should allow a user to add a section back in', async ( {
|
|
||||||
page,
|
|
||||||
} ) => {
|
|
||||||
await page.goto(
|
|
||||||
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
|
||||||
);
|
|
||||||
// button only shows when not all sections visible, so remove a section
|
|
||||||
await page
|
|
||||||
.locator( 'button:right-of(:text("Performance")) >> nth=0' )
|
|
||||||
.click();
|
|
||||||
await page.locator( 'text=Remove section' ).click();
|
|
||||||
|
|
||||||
// add section
|
|
||||||
await page.locator( '//button[@title="Add more sections"]' ).click();
|
|
||||||
await page
|
|
||||||
.locator( '//button[@title="Add Performance section"]' )
|
|
||||||
.click();
|
|
||||||
await expect(
|
|
||||||
page.locator( 'h2.woocommerce-section-header__title >> nth=2' )
|
|
||||||
).toContainText( 'Performance' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
test.describe( 'moving sections', () => {
|
test.describe( 'moving sections', () => {
|
||||||
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
|
|
||||||
|
@ -80,20 +38,16 @@ test.describe( 'Analytics pages', () => {
|
||||||
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
||||||
);
|
);
|
||||||
// check the top section
|
// check the top section
|
||||||
await page
|
await page.click(
|
||||||
.locator(
|
'//button[@title="Choose which analytics to display and the section name"]'
|
||||||
'button.components-button.woocommerce-ellipsis-menu__toggle >> nth=0'
|
);
|
||||||
)
|
|
||||||
.click();
|
|
||||||
await expect( page.locator( 'text=Move up' ) ).not.toBeVisible();
|
await expect( page.locator( 'text=Move up' ) ).not.toBeVisible();
|
||||||
await expect( page.locator( 'text=Move down' ) ).toBeVisible();
|
await expect( page.locator( 'text=Move down' ) ).toBeVisible();
|
||||||
|
|
||||||
// check the bottom section
|
// check the bottom section
|
||||||
await await page
|
await page.click(
|
||||||
.locator(
|
'//button[@title="Choose which leaderboards to display and other settings"]'
|
||||||
'button.components-button.woocommerce-ellipsis-menu__toggle >> nth=2'
|
);
|
||||||
)
|
|
||||||
.click();
|
|
||||||
await expect( page.locator( 'text=Move down' ) ).not.toBeVisible();
|
await expect( page.locator( 'text=Move down' ) ).not.toBeVisible();
|
||||||
await expect( page.locator( 'text=Move up' ) ).toBeVisible();
|
await expect( page.locator( 'text=Move up' ) ).toBeVisible();
|
||||||
} );
|
} );
|
||||||
|
@ -111,12 +65,10 @@ test.describe( 'Analytics pages', () => {
|
||||||
.locator( 'h2.woocommerce-section-header__title >> nth=1' )
|
.locator( 'h2.woocommerce-section-header__title >> nth=1' )
|
||||||
.innerText();
|
.innerText();
|
||||||
|
|
||||||
await page
|
await page.click(
|
||||||
.locator(
|
|
||||||
'button.components-button.woocommerce-ellipsis-menu__toggle >> nth=0'
|
'button.components-button.woocommerce-ellipsis-menu__toggle >> nth=0'
|
||||||
)
|
);
|
||||||
.click();
|
await page.click( 'text=Move down' );
|
||||||
await page.locator( 'text=Move down' ).click();
|
|
||||||
|
|
||||||
// second section becomes first section, first becomes second
|
// second section becomes first section, first becomes second
|
||||||
await expect(
|
await expect(
|
||||||
|
@ -140,12 +92,10 @@ test.describe( 'Analytics pages', () => {
|
||||||
.locator( 'h2.woocommerce-section-header__title >> nth=1' )
|
.locator( 'h2.woocommerce-section-header__title >> nth=1' )
|
||||||
.innerText();
|
.innerText();
|
||||||
|
|
||||||
await page
|
await page.click(
|
||||||
.locator(
|
|
||||||
'button.components-button.woocommerce-ellipsis-menu__toggle >> nth=1'
|
'button.components-button.woocommerce-ellipsis-menu__toggle >> nth=1'
|
||||||
)
|
);
|
||||||
.click();
|
await page.click( 'text=Move up' );
|
||||||
await page.locator( 'text=Move up' ).click();
|
|
||||||
|
|
||||||
// second section becomes first section, first becomes second
|
// second section becomes first section, first becomes second
|
||||||
await expect(
|
await expect(
|
||||||
|
@ -156,4 +106,54 @@ test.describe( 'Analytics pages', () => {
|
||||||
).toHaveText( firstSection );
|
).toHaveText( firstSection );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
test( 'should allow a user to remove a section', async ( { page } ) => {
|
||||||
|
await page.goto(
|
||||||
|
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
||||||
|
);
|
||||||
|
// clicks the first button to the right of the Performance heading
|
||||||
|
await page.click( 'button:right-of(:text("Performance")) >> nth=0' );
|
||||||
|
await page.click( 'text=Remove section' );
|
||||||
|
// Grab all of the section headings
|
||||||
|
const sections = await page.$$(
|
||||||
|
'h2.woocommerce-section-header__title'
|
||||||
|
);
|
||||||
|
await expect( sections.length ).toEqual( 2 );
|
||||||
|
|
||||||
|
// clean up
|
||||||
|
await page.click( '//button[@title="Add more sections"]' );
|
||||||
|
await page.click( '//button[@title="Add Performance section"]' );
|
||||||
|
await page.waitForSelector( 'h2:has-text("Performance")', {
|
||||||
|
state: 'visible',
|
||||||
|
} );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should allow a user to add a section back in', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto(
|
||||||
|
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
||||||
|
);
|
||||||
|
// button only shows when not all sections visible, so remove a section
|
||||||
|
await page.click( 'button:right-of(:text("Performance")) >> nth=0' );
|
||||||
|
await page.click( 'text=Remove section' );
|
||||||
|
|
||||||
|
// add section
|
||||||
|
await page.click( '//button[@title="Add more sections"]' );
|
||||||
|
await page.click( '//button[@title="Add Performance section"]' );
|
||||||
|
await expect(
|
||||||
|
page.locator( 'h2.woocommerce-section-header__title >> nth=2' )
|
||||||
|
).toContainText( 'Performance' );
|
||||||
|
|
||||||
|
// clean up by moving performance section back to the top
|
||||||
|
await page.click(
|
||||||
|
'//button[@title="Choose which analytics to display and the section name"]'
|
||||||
|
);
|
||||||
|
await page.click( 'text=Move up' );
|
||||||
|
await page.click(
|
||||||
|
'//button[@title="Choose which analytics to display and the section name"]'
|
||||||
|
);
|
||||||
|
await page.click( 'text=Move up' );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -24,7 +24,7 @@ test.describe( 'Analytics pages', () => {
|
||||||
`/wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2F${ urlTitle }`
|
`/wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2F${ urlTitle }`
|
||||||
);
|
);
|
||||||
const pageTitle = page.locator( 'h1' );
|
const pageTitle = page.locator( 'h1' );
|
||||||
await expect( pageTitle ).toHaveText( aPages );
|
await expect( pageTitle ).toContainText( aPages );
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( '#woocommerce-layout__primary' )
|
page.locator( '#woocommerce-layout__primary' )
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const { test, expect } = require( '@playwright/test' );
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
test.describe( 'Payment setup task', () => {
|
test.describe( 'Payment setup task', () => {
|
||||||
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
|
@ -12,6 +13,21 @@ test.describe( 'Payment setup task', () => {
|
||||||
await page.waitForLoadState( 'networkidle' );
|
await page.waitForLoadState( 'networkidle' );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'payment_gateways/bacs', {
|
||||||
|
enabled: false,
|
||||||
|
} );
|
||||||
|
await api.put( 'payment_gateways/cod', {
|
||||||
|
enabled: false,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
test( 'Can visit the payment setup task from the homescreen if the setup wizard has been skipped', async ( {
|
test( 'Can visit the payment setup task from the homescreen if the setup wizard has been skipped', async ( {
|
||||||
page,
|
page,
|
||||||
} ) => {
|
} ) => {
|
||||||
|
@ -23,13 +39,16 @@ test.describe( 'Payment setup task', () => {
|
||||||
test( 'Saving valid bank account transfer details enables the payment method', async ( {
|
test( 'Saving valid bank account transfer details enables the payment method', async ( {
|
||||||
page,
|
page,
|
||||||
} ) => {
|
} ) => {
|
||||||
|
// load the bank transfer page
|
||||||
await page.goto(
|
await page.goto(
|
||||||
'wp-admin/admin.php?page=wc-admin&task=payments&id=bacs'
|
'wp-admin/admin.php?page=wc-admin&task=payments&id=bacs'
|
||||||
);
|
);
|
||||||
|
// purposely no await -- close the help dialog if/when it appears
|
||||||
page.locator( '.components-button.is-small.has-icon' )
|
page.locator( '.components-button.is-small.has-icon' )
|
||||||
.click()
|
.click()
|
||||||
.catch( () => {} );
|
.catch( () => {} );
|
||||||
// purposely no await -- close the help dialog if/when it appears
|
|
||||||
|
// fill in bank transfer form
|
||||||
await page.fill( '//input[@placeholder="Account name"]', 'Savings' );
|
await page.fill( '//input[@placeholder="Account name"]', 'Savings' );
|
||||||
await page.fill( '//input[@placeholder="Account number"]', '1234' );
|
await page.fill( '//input[@placeholder="Account number"]', '1234' );
|
||||||
await page.fill( '//input[@placeholder="Bank name"]', 'Test Bank' );
|
await page.fill( '//input[@placeholder="Bank name"]', 'Test Bank' );
|
||||||
|
@ -37,46 +56,48 @@ test.describe( 'Payment setup task', () => {
|
||||||
await page.fill( '//input[@placeholder="IBAN"]', '12 3456 7890' );
|
await page.fill( '//input[@placeholder="IBAN"]', '12 3456 7890' );
|
||||||
await page.fill( '//input[@placeholder="BIC / Swift"]', 'ABBA' );
|
await page.fill( '//input[@placeholder="BIC / Swift"]', 'ABBA' );
|
||||||
await page.click( 'text=Save' );
|
await page.click( 'text=Save' );
|
||||||
|
|
||||||
|
// check that bank transfers were set up
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( 'div.components-snackbar__content' )
|
page.locator( 'div.components-snackbar__content' )
|
||||||
).toHaveText( 'Direct bank transfer details added successfully' );
|
).toContainText( 'Direct bank transfer details added successfully' );
|
||||||
await expect( page.locator( 'h1' ) ).toHaveText( 'Set up payments' );
|
|
||||||
|
await page.goto( 'wp-admin/admin.php?page=wc-settings&tab=checkout' );
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.locator(
|
page.locator(
|
||||||
'a:right-of(h3:has-text("Direct bank transfer")) >> nth=0'
|
'//tr[@data-gateway_id="bacs"]/td[@class="status"]/a'
|
||||||
)
|
)
|
||||||
).toHaveText( 'Manage' );
|
).toHaveClass( 'wc-payment-gateway-method-toggle-enabled' );
|
||||||
|
|
||||||
// clean up
|
|
||||||
await page.goto(
|
|
||||||
'wp-admin/admin.php?page=wc-settings&tab=checkout§ion=bacs'
|
|
||||||
);
|
|
||||||
await page.click( 'text="Enable bank transfer"' );
|
|
||||||
await page.click( 'text="Save changes"' );
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'Enabling cash on delivery enables the payment method', async ( {
|
test( 'Enabling cash on delivery enables the payment method', async ( {
|
||||||
page,
|
page,
|
||||||
} ) => {
|
} ) => {
|
||||||
await page.goto( 'wp-admin/admin.php?page=wc-admin&task=payments' );
|
await page.goto( 'wp-admin/admin.php?page=wc-admin&task=payments' );
|
||||||
|
|
||||||
|
// purposely no await -- close the help dialog if/when it appears
|
||||||
page.locator( '.components-button.is-small.has-icon' )
|
page.locator( '.components-button.is-small.has-icon' )
|
||||||
.click()
|
.click()
|
||||||
.catch( () => {} );
|
.catch( () => {} );
|
||||||
// purposely no await -- close the help dialog if/when it appears
|
|
||||||
await page.click( 'button:has-text("Enable")' ); // enable COD payment option
|
|
||||||
await page.goto( 'wp-admin/admin.php?page=wc-admin&task=payments' );
|
|
||||||
await expect( page.locator( 'h1' ) ).toHaveText( 'Set up payments' );
|
|
||||||
await expect(
|
|
||||||
page.locator(
|
|
||||||
'a:right-of(h3:has-text("Cash on delivery")) >> nth=0'
|
|
||||||
)
|
|
||||||
).toHaveText( 'Manage' );
|
|
||||||
|
|
||||||
// clean up
|
if ( await page.isVisible( 'text=Offline payment methods' ) ) {
|
||||||
await page.goto(
|
// other payment methods are already shown
|
||||||
'wp-admin/admin.php?page=wc-settings&tab=checkout§ion=cod'
|
} else {
|
||||||
|
// show other payment methods
|
||||||
|
await page.click( 'button.toggle-button' );
|
||||||
|
}
|
||||||
|
|
||||||
|
// enable COD payment option
|
||||||
|
await page.click(
|
||||||
|
'div.woocommerce-task-payment-cod > div.woocommerce-task-payment__footer > button'
|
||||||
);
|
);
|
||||||
await page.click( 'text="Enable cash on delivery"' );
|
await page.waitForLoadState( 'networkidle' );
|
||||||
await page.click( 'text="Save changes"' );
|
|
||||||
|
await page.goto( 'wp-admin/admin.php?page=wc-settings&tab=checkout' );
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator( '//tr[@data-gateway_id="cod"]/td[@class="status"]/a' )
|
||||||
|
).toHaveClass( 'wc-payment-gateway-method-toggle-enabled' );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -1,25 +1,32 @@
|
||||||
const { test, expect } = require( '@playwright/test' );
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
|
||||||
test( 'Load the home page', async ( { page } ) => {
|
test.describe(
|
||||||
|
'A basic set of tests to ensure WP, wp-admin and my-account load',
|
||||||
|
() => {
|
||||||
|
test( 'Load the home page', async ( { page } ) => {
|
||||||
await page.goto( '/' );
|
await page.goto( '/' );
|
||||||
const title = page.locator( 'h1.site-title' );
|
const title = page.locator( 'h1.site-title' );
|
||||||
await expect( title ).toHaveText( 'WooCommerce Core E2E Test Suite' );
|
await expect( title ).toHaveText(
|
||||||
} );
|
'WooCommerce Core E2E Test Suite'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
test.describe( 'Sign in as admin', () => {
|
test.describe( 'Sign in as admin', () => {
|
||||||
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
test( 'Load wp-admin', async ( { page } ) => {
|
test( 'Load wp-admin', async ( { page } ) => {
|
||||||
await page.goto( '/wp-admin' );
|
await page.goto( '/wp-admin' );
|
||||||
const title = page.locator( 'div.wrap > h1' );
|
const title = page.locator( 'div.wrap > h1' );
|
||||||
await expect( title ).toHaveText( 'Dashboard' );
|
await expect( title ).toHaveText( 'Dashboard' );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test.describe( 'Sign in as customer', () => {
|
test.describe( 'Sign in as customer', () => {
|
||||||
test.use( { storageState: 'e2e/storage/customerState.json' } );
|
test.use( { storageState: 'e2e/storage/customerState.json' } );
|
||||||
test( 'Load customer my account page', async ( { page } ) => {
|
test( 'Load customer my account page', async ( { page } ) => {
|
||||||
await page.goto( '/my-account' );
|
await page.goto( '/my-account' );
|
||||||
const title = page.locator( 'h1.entry-title' );
|
const title = page.locator( 'h1.entry-title' );
|
||||||
await expect( title ).toHaveText( 'My account' );
|
await expect( title ).toHaveText( 'My account' );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
|
@ -1,14 +1,32 @@
|
||||||
const { test, expect } = require( '@playwright/test' );
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
const couponCode = `code-${ new Date().getTime().toString() }`;
|
||||||
|
|
||||||
test.describe( 'Add New Coupon Page', () => {
|
test.describe( 'Add New Coupon Page', () => {
|
||||||
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.get( 'coupons' ).then( ( response ) => {
|
||||||
|
for ( let i = 0; i < response.data.length; i++ ) {
|
||||||
|
if ( response.data[ i ].code === couponCode ) {
|
||||||
|
api.delete( `coupons/${ response.data[ i ].id }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
test( 'can create new coupon', async ( { page } ) => {
|
test( 'can create new coupon', async ( { page } ) => {
|
||||||
await page.goto( 'wp-admin/post-new.php?post_type=shop_coupon' );
|
await page.goto( 'wp-admin/post-new.php?post_type=shop_coupon' );
|
||||||
await page.fill(
|
await page.fill( '#title', couponCode );
|
||||||
'#title',
|
|
||||||
`code-${ new Date().getTime().toString() }`
|
|
||||||
);
|
|
||||||
await page.fill( '#woocommerce-coupon-description', 'test coupon' );
|
await page.fill( '#woocommerce-coupon-description', 'test coupon' );
|
||||||
|
|
||||||
await page.fill( '#coupon_amount', '100' );
|
await page.fill( '#coupon_amount', '100' );
|
||||||
|
@ -18,8 +36,5 @@ test.describe( 'Add New Coupon Page', () => {
|
||||||
await expect( page.locator( 'div.notice.notice-success' ) ).toHaveText(
|
await expect( page.locator( 'div.notice.notice-success' ) ).toHaveText(
|
||||||
'Coupon updated.Dismiss this notice.'
|
'Coupon updated.Dismiss this notice.'
|
||||||
);
|
);
|
||||||
|
|
||||||
// delete the coupon
|
|
||||||
await page.dispatchEvent( 'a.submitdelete', 'click' );
|
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
const { test, expect } = require( '@playwright/test' );
|
const { test, expect } = require( '@playwright/test' );
|
||||||
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
const simpleProductName = 'Add new order simple product';
|
||||||
|
const variableProductName = 'Add new order variable product';
|
||||||
|
const externalProductName = 'Add new order external product';
|
||||||
|
const groupedProductName = 'Add new order grouped product';
|
||||||
const taxClasses = [
|
const taxClasses = [
|
||||||
{
|
{
|
||||||
name: 'Tax Class Simple',
|
name: 'Tax Class Simple',
|
||||||
|
@ -30,13 +34,14 @@ const taxRates = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const taxClassSlugs = [];
|
const taxClassSlugs = [];
|
||||||
const taxTotals = [ '$10.00', '$60.00', '$240.00' ];
|
const taxTotals = [ '10.00', '20.00', '240.00' ];
|
||||||
let simpleProductId,
|
let simpleProductId,
|
||||||
variableProductId,
|
variableProductId,
|
||||||
externalProductId,
|
externalProductId,
|
||||||
subProductAId,
|
subProductAId,
|
||||||
subProductBId,
|
subProductBId,
|
||||||
groupedProductId;
|
groupedProductId,
|
||||||
|
orderId;
|
||||||
|
|
||||||
test.describe( 'WooCommerce Orders > Add new order', () => {
|
test.describe( 'WooCommerce Orders > Add new order', () => {
|
||||||
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
|
@ -53,41 +58,32 @@ test.describe( 'WooCommerce Orders > Add new order', () => {
|
||||||
value: 'yes',
|
value: 'yes',
|
||||||
} );
|
} );
|
||||||
// add tax classes
|
// add tax classes
|
||||||
let a = 0;
|
for ( let i = 0; i < taxClasses.length; i++ ) {
|
||||||
for ( const tax in taxClasses ) {
|
await api
|
||||||
api.post( 'taxes/classes', taxClasses[ tax ] ).then(
|
.post( 'taxes/classes', taxClasses[ i ] )
|
||||||
( response ) => {
|
.then( ( response ) => {
|
||||||
taxClassSlugs[ a ] = response.data.slug;
|
taxClassSlugs[ i ] = response.data.slug;
|
||||||
a++;
|
} );
|
||||||
// add tax rates
|
|
||||||
for ( const rate in taxRates ) {
|
|
||||||
api.post( 'taxes', taxRates[ rate ] );
|
|
||||||
}
|
}
|
||||||
|
// attach rates to the classes
|
||||||
|
for ( let i = 0; i < taxRates.length; i++ ) {
|
||||||
|
await api.post( 'taxes', taxRates[ i ] );
|
||||||
}
|
}
|
||||||
);
|
// create simple product
|
||||||
}
|
await api
|
||||||
// make sure the taxes are all created before creating products
|
.post( 'products', {
|
||||||
api.get( 'taxes/classes' ).then( ( response ) => {
|
name: simpleProductName,
|
||||||
while ( true ) {
|
|
||||||
if ( Object.keys( response.data ).length === 3 ) {
|
|
||||||
api.post( 'products', {
|
|
||||||
name: 'Simple Product 273722',
|
|
||||||
type: 'simple',
|
type: 'simple',
|
||||||
regular_price: '100',
|
regular_price: '100',
|
||||||
tax_class: 'Tax Class Simple',
|
tax_class: 'Tax Class Simple',
|
||||||
} ).then( ( resp ) => {
|
} )
|
||||||
|
.then( ( resp ) => {
|
||||||
simpleProductId = resp.data.id;
|
simpleProductId = resp.data.id;
|
||||||
} );
|
} );
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
// create simple product
|
|
||||||
|
|
||||||
// create variable product
|
// create variable product
|
||||||
const variations = [
|
const variations = [
|
||||||
{
|
{
|
||||||
regular_price: '200',
|
regular_price: '100',
|
||||||
attributes: [
|
attributes: [
|
||||||
{
|
{
|
||||||
name: 'Size',
|
name: 'Size',
|
||||||
|
@ -101,7 +97,7 @@ test.describe( 'WooCommerce Orders > Add new order', () => {
|
||||||
tax_class: 'Tax Class Variable',
|
tax_class: 'Tax Class Variable',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
regular_price: '300',
|
regular_price: '100',
|
||||||
attributes: [
|
attributes: [
|
||||||
{
|
{
|
||||||
name: 'Size',
|
name: 'Size',
|
||||||
|
@ -117,7 +113,7 @@ test.describe( 'WooCommerce Orders > Add new order', () => {
|
||||||
];
|
];
|
||||||
await api
|
await api
|
||||||
.post( 'products', {
|
.post( 'products', {
|
||||||
name: 'Variable Product 024611',
|
name: variableProductName,
|
||||||
type: 'variable',
|
type: 'variable',
|
||||||
tax_class: 'Tax Class Variable',
|
tax_class: 'Tax Class Variable',
|
||||||
} )
|
} )
|
||||||
|
@ -133,7 +129,7 @@ test.describe( 'WooCommerce Orders > Add new order', () => {
|
||||||
// create external product
|
// create external product
|
||||||
await api
|
await api
|
||||||
.post( 'products', {
|
.post( 'products', {
|
||||||
name: 'External product 786794',
|
name: externalProductName,
|
||||||
regular_price: '800',
|
regular_price: '800',
|
||||||
tax_class: 'Tax Class External',
|
tax_class: 'Tax Class External',
|
||||||
external_url: 'https://wordpress.org/plugins/woocommerce',
|
external_url: 'https://wordpress.org/plugins/woocommerce',
|
||||||
|
@ -156,7 +152,7 @@ test.describe( 'WooCommerce Orders > Add new order', () => {
|
||||||
} );
|
} );
|
||||||
await api
|
await api
|
||||||
.post( 'products', {
|
.post( 'products', {
|
||||||
name: 'Grouped Product 858012',
|
name: groupedProductName,
|
||||||
regular_price: '29.99',
|
regular_price: '29.99',
|
||||||
grouped_products: [ subProductAId, subProductBId ],
|
grouped_products: [ subProductAId, subProductBId ],
|
||||||
type: 'grouped',
|
type: 'grouped',
|
||||||
|
@ -167,22 +163,26 @@ test.describe( 'WooCommerce Orders > Add new order', () => {
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test.afterAll( async ( { baseURL } ) => {
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
// cleans up all products after run
|
|
||||||
const api = new wcApi( {
|
const api = new wcApi( {
|
||||||
url: baseURL,
|
url: baseURL,
|
||||||
consumerKey: process.env.CONSUMER_KEY,
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
consumerSecret: process.env.CONSUMER_SECRET,
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
version: 'wc/v3',
|
version: 'wc/v3',
|
||||||
} );
|
} );
|
||||||
await api.delete( `products/${ simpleProductId }`, { force: true } );
|
// cleans up all products after run
|
||||||
await api.delete( `products/${ variableProductId }`, { force: true } );
|
await api.post( 'products/batch', {
|
||||||
await api.delete( `products/${ externalProductId }`, { force: true } );
|
delete: [
|
||||||
await api.delete( `products/${ subProductAId }`, { force: true } );
|
simpleProductId,
|
||||||
await api.delete( `products/${ subProductBId }`, { force: true } );
|
variableProductId,
|
||||||
await api.delete( `products/${ groupedProductId }`, { force: true } );
|
externalProductId,
|
||||||
|
subProductAId,
|
||||||
|
subProductBId,
|
||||||
|
groupedProductId,
|
||||||
|
],
|
||||||
|
} );
|
||||||
// clean up tax classes and rates
|
// clean up tax classes and rates
|
||||||
for ( const key in taxClassSlugs ) {
|
for ( let i = 0; i < taxClassSlugs.length; i++ ) {
|
||||||
await api.delete( `taxes/classes/${ taxClassSlugs[ key ] }`, {
|
await api.delete( `taxes/classes/${ taxClassSlugs[ i ] }`, {
|
||||||
force: true,
|
force: true,
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
@ -190,6 +190,11 @@ test.describe( 'WooCommerce Orders > Add new order', () => {
|
||||||
await api.put( 'settings/general/woocommerce_calc_taxes', {
|
await api.put( 'settings/general/woocommerce_calc_taxes', {
|
||||||
value: 'no',
|
value: 'no',
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
// if we're only running the second test, there's no orderId created
|
||||||
|
if ( orderId ) {
|
||||||
|
await api.delete( `orders/${ orderId }`, { force: true } );
|
||||||
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'can create new order', async ( { page } ) => {
|
test( 'can create new order', async ( { page } ) => {
|
||||||
|
@ -198,6 +203,18 @@ test.describe( 'WooCommerce Orders > Add new order', () => {
|
||||||
'Add new order'
|
'Add new order'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
// get order ID from the page
|
||||||
|
const orderHtmlElement = await page.$(
|
||||||
|
'h2.woocommerce-order-data__heading'
|
||||||
|
);
|
||||||
|
const orderText = await page.evaluate(
|
||||||
|
( element ) => element.textContent,
|
||||||
|
orderHtmlElement
|
||||||
|
);
|
||||||
|
orderId = orderText.match( /([0-9])\w+/ );
|
||||||
|
orderId = orderId[ 0 ].toString();
|
||||||
|
|
||||||
await page.selectOption( '#order_status', 'wc-processing' );
|
await page.selectOption( '#order_status', 'wc-processing' );
|
||||||
await page.fill( 'input[name=order_date]', '2018-12-13' );
|
await page.fill( 'input[name=order_date]', '2018-12-13' );
|
||||||
await page.fill( 'input[name=order_date_hour]', '18' );
|
await page.fill( 'input[name=order_date_hour]', '18' );
|
||||||
|
@ -231,7 +248,7 @@ test.describe( 'WooCommerce Orders > Add new order', () => {
|
||||||
await page.click( 'text=Search for a product…' );
|
await page.click( 'text=Search for a product…' );
|
||||||
await page.type(
|
await page.type(
|
||||||
'input:below(:text("Search for a product…"))',
|
'input:below(:text("Search for a product…"))',
|
||||||
'Simple Product 273722'
|
simpleProductName
|
||||||
);
|
);
|
||||||
await page.click(
|
await page.click(
|
||||||
'li.select2-results__option.select2-results__option--highlighted'
|
'li.select2-results__option.select2-results__option--highlighted'
|
||||||
|
@ -240,7 +257,7 @@ test.describe( 'WooCommerce Orders > Add new order', () => {
|
||||||
await page.click( 'text=Search for a product…' );
|
await page.click( 'text=Search for a product…' );
|
||||||
await page.type(
|
await page.type(
|
||||||
'input:below(:text("Search for a product…"))',
|
'input:below(:text("Search for a product…"))',
|
||||||
'Variable Product 024611'
|
variableProductName
|
||||||
);
|
);
|
||||||
await page.click(
|
await page.click(
|
||||||
'li.select2-results__option.select2-results__option--highlighted'
|
'li.select2-results__option.select2-results__option--highlighted'
|
||||||
|
@ -249,7 +266,7 @@ test.describe( 'WooCommerce Orders > Add new order', () => {
|
||||||
await page.click( 'text=Search for a product…' );
|
await page.click( 'text=Search for a product…' );
|
||||||
await page.type(
|
await page.type(
|
||||||
'input:below(:text("Search for a product…"))',
|
'input:below(:text("Search for a product…"))',
|
||||||
'Grouped Product 858012'
|
groupedProductName
|
||||||
);
|
);
|
||||||
await page.click(
|
await page.click(
|
||||||
'li.select2-results__option.select2-results__option--highlighted'
|
'li.select2-results__option.select2-results__option--highlighted'
|
||||||
|
@ -258,7 +275,7 @@ test.describe( 'WooCommerce Orders > Add new order', () => {
|
||||||
await page.click( 'text=Search for a product…' );
|
await page.click( 'text=Search for a product…' );
|
||||||
await page.type(
|
await page.type(
|
||||||
'input:below(:text("Search for a product…"))',
|
'input:below(:text("Search for a product…"))',
|
||||||
'External product 786794'
|
externalProductName
|
||||||
);
|
);
|
||||||
await page.click(
|
await page.click(
|
||||||
'li.select2-results__option.select2-results__option--highlighted'
|
'li.select2-results__option.select2-results__option--highlighted'
|
||||||
|
@ -268,16 +285,16 @@ test.describe( 'WooCommerce Orders > Add new order', () => {
|
||||||
|
|
||||||
// assert that products added
|
// assert that products added
|
||||||
await expect( page.locator( 'td.name > a >> nth=0' ) ).toContainText(
|
await expect( page.locator( 'td.name > a >> nth=0' ) ).toContainText(
|
||||||
'Simple Product 273722'
|
simpleProductName
|
||||||
);
|
);
|
||||||
await expect( page.locator( 'td.name > a >> nth=1' ) ).toContainText(
|
await expect( page.locator( 'td.name > a >> nth=1' ) ).toContainText(
|
||||||
'Variable Product 024611'
|
variableProductName
|
||||||
);
|
);
|
||||||
await expect( page.locator( 'td.name > a >> nth=2' ) ).toContainText(
|
await expect( page.locator( 'td.name > a >> nth=2' ) ).toContainText(
|
||||||
'Grouped Product 858012'
|
groupedProductName
|
||||||
);
|
);
|
||||||
await expect( page.locator( 'td.name > a >> nth=3' ) ).toContainText(
|
await expect( page.locator( 'td.name > a >> nth=3' ) ).toContainText(
|
||||||
'External product 786794'
|
externalProductName
|
||||||
);
|
);
|
||||||
|
|
||||||
// Recalculate taxes
|
// Recalculate taxes
|
||||||
|
|
|
@ -3,6 +3,23 @@ const { test, expect } = require( '@playwright/test' );
|
||||||
test.describe( 'Merchant can add shipping classes', () => {
|
test.describe( 'Merchant can add shipping classes', () => {
|
||||||
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
|
|
||||||
|
test.afterEach( async ( { page } ) => {
|
||||||
|
// no api endpoints for shipping classes, so use the UI to cleanup
|
||||||
|
await page.goto(
|
||||||
|
'wp-admin/admin.php?page=wc-settings&tab=shipping§ion=classes'
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.dispatchEvent(
|
||||||
|
'.wc-shipping-class-delete >> nth=0',
|
||||||
|
'click'
|
||||||
|
);
|
||||||
|
await page.dispatchEvent(
|
||||||
|
'.wc-shipping-class-delete >> nth=0',
|
||||||
|
'click'
|
||||||
|
);
|
||||||
|
await page.dispatchEvent( 'text=Save shipping classes', 'click' );
|
||||||
|
} );
|
||||||
|
|
||||||
test( 'can add shipping classes', async ( { page } ) => {
|
test( 'can add shipping classes', async ( { page } ) => {
|
||||||
await page.goto(
|
await page.goto(
|
||||||
'wp-admin/admin.php?page=wc-settings&tab=shipping§ion=classes'
|
'wp-admin/admin.php?page=wc-settings&tab=shipping§ion=classes'
|
||||||
|
@ -54,16 +71,5 @@ test.describe( 'Merchant can add shipping classes', () => {
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up
|
|
||||||
await page.dispatchEvent(
|
|
||||||
'.wc-shipping-class-delete >> nth=0',
|
|
||||||
'click'
|
|
||||||
);
|
|
||||||
await page.dispatchEvent(
|
|
||||||
'.wc-shipping-class-delete >> nth=0',
|
|
||||||
'click'
|
|
||||||
);
|
|
||||||
await page.dispatchEvent( 'text=Save shipping classes', 'click' );
|
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -1,38 +1,59 @@
|
||||||
const { test, expect } = require( '@playwright/test' );
|
const { test, expect } = require( '@playwright/test' );
|
||||||
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
const sanFranciscoZIP = '94107';
|
const maynePostal = 'V0N 2J0';
|
||||||
const shippingZoneNameUS = 'US with Flat rate';
|
const shippingZoneNameFlatRate = 'Canada with Flat rate';
|
||||||
const shippingZoneNameFL = 'CA with Free shipping';
|
const shippingZoneNameFreeShip = 'BC with Free shipping';
|
||||||
const shippingZoneNameSF = 'SF with Local pickup';
|
const shippingZoneNameLocalPickup = 'Mayne Island with Local pickup';
|
||||||
let productId;
|
|
||||||
|
|
||||||
test.describe( 'WooCommerce Shipping Settings - Add new shipping zone', () => {
|
test.describe( 'WooCommerce Shipping Settings - Add new shipping zone', () => {
|
||||||
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
|
|
||||||
test( 'add shipping zone for San Francisco with free Local pickup', async ( {
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.get( 'shipping/zones' ).then( ( response ) => {
|
||||||
|
for ( let i = 0; i < response.data.length; i++ ) {
|
||||||
|
if (
|
||||||
|
response.data[ i ].name === shippingZoneNameFlatRate ||
|
||||||
|
response.data[ i ].name === shippingZoneNameFreeShip ||
|
||||||
|
response.data[ i ].name === shippingZoneNameLocalPickup
|
||||||
|
) {
|
||||||
|
api.delete( `shipping/zones/${ response.data[ i ].id }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'add shipping zone for Mayne Island with free Local pickup', async ( {
|
||||||
page,
|
page,
|
||||||
} ) => {
|
} ) => {
|
||||||
await page.goto( 'wp-admin/admin.php?page=wc-settings&tab=shipping' );
|
await page.goto( 'wp-admin/admin.php?page=wc-settings&tab=shipping' );
|
||||||
if ( await page.isVisible( `text=${ shippingZoneNameSF }` ) ) {
|
if ( await page.isVisible( `text=${ shippingZoneNameLocalPickup }` ) ) {
|
||||||
// this shipping zone already exists, don't create it
|
// this shipping zone already exists, don't create it
|
||||||
} else {
|
} else {
|
||||||
await page.goto(
|
await page.goto(
|
||||||
'wp-admin/admin.php?page=wc-settings&tab=shipping&zone_id=new'
|
'wp-admin/admin.php?page=wc-settings&tab=shipping&zone_id=new'
|
||||||
);
|
);
|
||||||
await page.fill( '#zone_name', shippingZoneNameSF );
|
await page.fill( '#zone_name', shippingZoneNameLocalPickup );
|
||||||
|
|
||||||
await page.click( '.select2-search__field' );
|
await page.click( '.select2-search__field' );
|
||||||
await page.type(
|
await page.type(
|
||||||
'.select2-search__field',
|
'.select2-search__field',
|
||||||
'California, United States'
|
'British Columbia, Canada'
|
||||||
);
|
);
|
||||||
await page.click(
|
await page.click(
|
||||||
'.select2-results__option.select2-results__option--highlighted'
|
'.select2-results__option.select2-results__option--highlighted'
|
||||||
);
|
);
|
||||||
|
|
||||||
await page.click( '.wc-shipping-zone-postcodes-toggle' );
|
await page.click( '.wc-shipping-zone-postcodes-toggle' );
|
||||||
await page.fill( '#zone_postcodes', sanFranciscoZIP );
|
await page.fill( '#zone_postcodes', maynePostal );
|
||||||
|
|
||||||
await page.click( 'text=Add shipping method' );
|
await page.click( 'text=Add shipping method' );
|
||||||
|
|
||||||
|
@ -49,32 +70,32 @@ test.describe( 'WooCommerce Shipping Settings - Add new shipping zone', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
||||||
/SF with Local pickup.*/
|
/Mayne Island with Local pickup.*/
|
||||||
);
|
);
|
||||||
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
||||||
/California, 94107.*/
|
/British Columbia, V0N 2J0.*/
|
||||||
);
|
);
|
||||||
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
||||||
/Local pickup.*/
|
/Local pickup.*/
|
||||||
);
|
);
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'add shipping zone for California with Free shipping', async ( {
|
test( 'add shipping zone for British Columbia with Free shipping', async ( {
|
||||||
page,
|
page,
|
||||||
} ) => {
|
} ) => {
|
||||||
await page.goto( 'wp-admin/admin.php?page=wc-settings&tab=shipping' );
|
await page.goto( 'wp-admin/admin.php?page=wc-settings&tab=shipping' );
|
||||||
if ( await page.isVisible( `text=${ shippingZoneNameFL }` ) ) {
|
if ( await page.isVisible( `text=${ shippingZoneNameFreeShip }` ) ) {
|
||||||
// this shipping zone already exists, don't create it
|
// this shipping zone already exists, don't create it
|
||||||
} else {
|
} else {
|
||||||
await page.goto(
|
await page.goto(
|
||||||
'wp-admin/admin.php?page=wc-settings&tab=shipping&zone_id=new'
|
'wp-admin/admin.php?page=wc-settings&tab=shipping&zone_id=new'
|
||||||
);
|
);
|
||||||
await page.fill( '#zone_name', shippingZoneNameFL );
|
await page.fill( '#zone_name', shippingZoneNameFreeShip );
|
||||||
|
|
||||||
await page.click( '.select2-search__field' );
|
await page.click( '.select2-search__field' );
|
||||||
await page.type(
|
await page.type(
|
||||||
'.select2-search__field',
|
'.select2-search__field',
|
||||||
'California, United States'
|
'British Columbia, Canada'
|
||||||
);
|
);
|
||||||
await page.click(
|
await page.click(
|
||||||
'.select2-results__option.select2-results__option--highlighted'
|
'.select2-results__option.select2-results__option--highlighted'
|
||||||
|
@ -94,28 +115,28 @@ test.describe( 'WooCommerce Shipping Settings - Add new shipping zone', () => {
|
||||||
await page.reload(); // Playwright runs so fast, the location shows up as "Everywhere" at first
|
await page.reload(); // Playwright runs so fast, the location shows up as "Everywhere" at first
|
||||||
}
|
}
|
||||||
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
||||||
/CA with Free shipping.*/
|
/BC with Free shipping.*/
|
||||||
);
|
);
|
||||||
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
||||||
/California.*/
|
/British Columbia.*/
|
||||||
);
|
);
|
||||||
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
||||||
/Free shipping.*/
|
/Free shipping.*/
|
||||||
);
|
);
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'add shipping zone for the US with Flat rate', async ( { page } ) => {
|
test( 'add shipping zone for Canada with Flat rate', async ( { page } ) => {
|
||||||
await page.goto( 'wp-admin/admin.php?page=wc-settings&tab=shipping' );
|
await page.goto( 'wp-admin/admin.php?page=wc-settings&tab=shipping' );
|
||||||
if ( await page.isVisible( `text=${ shippingZoneNameUS }` ) ) {
|
if ( await page.isVisible( `text=${ shippingZoneNameFlatRate }` ) ) {
|
||||||
// this shipping zone already exists, don't create it
|
// this shipping zone already exists, don't create it
|
||||||
} else {
|
} else {
|
||||||
await page.goto(
|
await page.goto(
|
||||||
'wp-admin/admin.php?page=wc-settings&tab=shipping&zone_id=new'
|
'wp-admin/admin.php?page=wc-settings&tab=shipping&zone_id=new'
|
||||||
);
|
);
|
||||||
await page.fill( '#zone_name', shippingZoneNameUS );
|
await page.fill( '#zone_name', shippingZoneNameFlatRate );
|
||||||
|
|
||||||
await page.click( '.select2-search__field' );
|
await page.click( '.select2-search__field' );
|
||||||
await page.type( '.select2-search__field', 'United States' );
|
await page.type( '.select2-search__field', 'Canada' );
|
||||||
await page.click(
|
await page.click(
|
||||||
'.select2-results__option.select2-results__option--highlighted'
|
'.select2-results__option.select2-results__option--highlighted'
|
||||||
);
|
);
|
||||||
|
@ -138,10 +159,10 @@ test.describe( 'WooCommerce Shipping Settings - Add new shipping zone', () => {
|
||||||
await page.reload(); // Playwright runs so fast, the location shows up as "Everywhere" at first
|
await page.reload(); // Playwright runs so fast, the location shows up as "Everywhere" at first
|
||||||
}
|
}
|
||||||
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
||||||
/US with Flat rate*/
|
/Canada with Flat rate*/
|
||||||
);
|
);
|
||||||
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
||||||
/United States \(US\).*/
|
/Canada.*/
|
||||||
);
|
);
|
||||||
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
await expect( page.locator( '.wc-shipping-zones' ) ).toHaveText(
|
||||||
/Flat rate.*/
|
/Flat rate.*/
|
||||||
|
@ -151,109 +172,171 @@ test.describe( 'WooCommerce Shipping Settings - Add new shipping zone', () => {
|
||||||
|
|
||||||
test.describe( 'Verifies shipping options from customer perspective', () => {
|
test.describe( 'Verifies shipping options from customer perspective', () => {
|
||||||
// note: tests are being run in an unauthenticated state (not as admin)
|
// note: tests are being run in an unauthenticated state (not as admin)
|
||||||
test.beforeAll( async () => {
|
let productId, shippingFreeId, shippingFlatId, shippingLocalId;
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
// need to add a product to the store so that we can order it and check shipping options
|
// need to add a product to the store so that we can order it and check shipping options
|
||||||
const api = new wcApi( {
|
const api = new wcApi( {
|
||||||
url: 'http://localhost:8084',
|
url: baseURL,
|
||||||
consumerKey: process.env.CONSUMER_KEY,
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
consumerSecret: process.env.CONSUMER_SECRET,
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
version: 'wc/v3',
|
version: 'wc/v3',
|
||||||
} );
|
} );
|
||||||
api.post( 'products', {
|
await api
|
||||||
|
.post( 'products', {
|
||||||
name: 'Shipping options are the best',
|
name: 'Shipping options are the best',
|
||||||
type: 'simple',
|
type: 'simple',
|
||||||
regular_price: '25.99',
|
regular_price: '25.99',
|
||||||
} ).then( ( response ) => {
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
productId = response.data.id;
|
productId = response.data.id;
|
||||||
} );
|
} );
|
||||||
|
// create shipping zones
|
||||||
|
await api
|
||||||
|
.post( 'shipping/zones', {
|
||||||
|
name: shippingZoneNameLocalPickup,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
shippingLocalId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api
|
||||||
|
.post( 'shipping/zones', {
|
||||||
|
name: shippingZoneNameFreeShip,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
shippingFreeId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api
|
||||||
|
.post( 'shipping/zones', {
|
||||||
|
name: shippingZoneNameFlatRate,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
shippingFlatId = response.data.id;
|
||||||
|
} );
|
||||||
|
// set shipping zone locations
|
||||||
|
await api.put( `shipping/zones/${ shippingFlatId }/locations`, [
|
||||||
|
{
|
||||||
|
code: 'CA',
|
||||||
|
},
|
||||||
|
] );
|
||||||
|
await api.put( `shipping/zones/${ shippingFreeId }/locations`, [
|
||||||
|
{
|
||||||
|
code: 'CA:BC',
|
||||||
|
type: 'state',
|
||||||
|
},
|
||||||
|
] );
|
||||||
|
await api.put( `shipping/zones/${ shippingLocalId }/locations`, [
|
||||||
|
{
|
||||||
|
code: 'V0N 2J0',
|
||||||
|
type: 'postcode',
|
||||||
|
},
|
||||||
|
] );
|
||||||
|
// set shipping zone methods
|
||||||
|
await api.post( `shipping/zones/${ shippingFlatId }/methods`, {
|
||||||
|
method_id: 'flat_rate',
|
||||||
|
settings: {
|
||||||
|
cost: '10.00',
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
await api.post( `shipping/zones/${ shippingFreeId }/methods`, {
|
||||||
|
method_id: 'free_shipping',
|
||||||
|
} );
|
||||||
|
await api.post( `shipping/zones/${ shippingLocalId }/methods`, {
|
||||||
|
method_id: 'local_pickup',
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test.afterAll( async () => {
|
test.beforeEach( async ( { context, page } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
context.clearCookies();
|
||||||
|
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
const api = new wcApi( {
|
const api = new wcApi( {
|
||||||
url: 'http://localhost:8084',
|
url: baseURL,
|
||||||
consumerKey: process.env.CONSUMER_KEY,
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
consumerSecret: process.env.CONSUMER_SECRET,
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
version: 'wc/v3',
|
version: 'wc/v3',
|
||||||
} );
|
} );
|
||||||
api.delete( `products/${ productId }`, { force: true } );
|
await api.delete( `products/${ productId }`, { force: true } );
|
||||||
|
await api.delete( `shipping/zones/${ shippingFlatId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `shipping/zones/${ shippingFreeId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `shipping/zones/${ shippingLocalId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'allows customer to benefit from a free Local pickup if in SF', async ( {
|
test( 'allows customer to benefit from a free Local pickup if on Mayne Island', async ( {
|
||||||
page,
|
page,
|
||||||
} ) => {
|
} ) => {
|
||||||
await page.goto( '/shop' );
|
await page.goto( 'cart/' );
|
||||||
await page.click( 'text=Add to cart' );
|
await page.click( 'a.shipping-calculator-button' );
|
||||||
await page.click( 'text=View cart' );
|
await page.selectOption( '#calc_shipping_country', 'CA' );
|
||||||
|
await page.selectOption( '#calc_shipping_state', 'BC' );
|
||||||
await page.click( 'text=Change address' );
|
await page.fill( '#calc_shipping_postcode', maynePostal );
|
||||||
await page.fill( '#calc_shipping_postcode', '94107' );
|
|
||||||
await page.click( 'button[name=calc_shipping]' );
|
await page.click( 'button[name=calc_shipping]' );
|
||||||
await page.waitForSelector( 'button[name=calc_shipping]', {
|
await page.waitForSelector( 'button[name=calc_shipping]', {
|
||||||
state: 'hidden',
|
state: 'hidden',
|
||||||
} );
|
} );
|
||||||
|
|
||||||
expect(
|
await expect(
|
||||||
await page.textContent(
|
page.locator( '.shipping ul#shipping_method > li > label' )
|
||||||
'.shipping ul#shipping_method > li > label'
|
).toContainText( 'Local pickup' );
|
||||||
)
|
await expect(
|
||||||
).toBe( 'Local pickup' );
|
page.locator( 'td[data-title="Total"] > strong > .amount > bdi' )
|
||||||
expect(
|
).toContainText( '25.99' );
|
||||||
await page.textContent(
|
|
||||||
'td[data-title="Total"] > strong > .amount > bdi'
|
|
||||||
)
|
|
||||||
).toBe( '$25.99' );
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'allows customer to benefit from a free Free shipping if in CA', async ( {
|
test( 'allows customer to benefit from a free Free shipping if in BC', async ( {
|
||||||
page,
|
page,
|
||||||
} ) => {
|
} ) => {
|
||||||
await page.goto( '/shop' );
|
await page.goto( 'cart/' );
|
||||||
await page.click( 'text=Add to cart' );
|
|
||||||
await page.click( 'text=View cart' );
|
|
||||||
|
|
||||||
await page.click( 'text=Change address' );
|
await page.click( 'a.shipping-calculator-button' );
|
||||||
await page.fill( '#calc_shipping_postcode', '94000' );
|
await page.selectOption( '#calc_shipping_country', 'CA' );
|
||||||
|
await page.selectOption( '#calc_shipping_state', 'BC' );
|
||||||
await page.click( 'button[name=calc_shipping]' );
|
await page.click( 'button[name=calc_shipping]' );
|
||||||
await page.waitForSelector( 'button[name=calc_shipping]', {
|
await page.waitForSelector( 'button[name=calc_shipping]', {
|
||||||
state: 'hidden',
|
state: 'hidden',
|
||||||
} );
|
} );
|
||||||
|
|
||||||
expect(
|
await expect(
|
||||||
await page.textContent(
|
page.locator( '.shipping ul#shipping_method > li > label' )
|
||||||
'.shipping ul#shipping_method > li > label'
|
).toContainText( 'Free shipping' );
|
||||||
)
|
await expect(
|
||||||
).toBe( 'Free shipping' );
|
page.locator( 'td[data-title="Total"] > strong > .amount > bdi' )
|
||||||
expect(
|
).toContainText( '25.99' );
|
||||||
await page.textContent(
|
|
||||||
'td[data-title="Total"] > strong > .amount > bdi'
|
|
||||||
)
|
|
||||||
).toBe( '$25.99' );
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'allows customer to pay for a Flat rate shipping method', async ( {
|
test( 'allows customer to pay for a Flat rate shipping method', async ( {
|
||||||
page,
|
page,
|
||||||
} ) => {
|
} ) => {
|
||||||
await page.goto( '/shop' );
|
await page.goto( 'cart/' );
|
||||||
await page.click( 'text=Add to cart' );
|
|
||||||
await page.click( 'text=View cart' );
|
|
||||||
|
|
||||||
await page.click( 'text=Change address' );
|
await page.click( 'a.shipping-calculator-button' );
|
||||||
await page.selectOption( '#calc_shipping_state', 'NY' );
|
await page.selectOption( '#calc_shipping_country', 'CA' );
|
||||||
await page.fill( '#calc_shipping_postcode', '10010' );
|
await page.selectOption( '#calc_shipping_state', 'AB' );
|
||||||
|
await page.fill( '#calc_shipping_postcode', 'T2T 1B3' );
|
||||||
await page.click( 'button[name=calc_shipping]' );
|
await page.click( 'button[name=calc_shipping]' );
|
||||||
await page.waitForSelector( 'button[name=calc_shipping]', {
|
await page.waitForSelector( 'button[name=calc_shipping]', {
|
||||||
state: 'hidden',
|
state: 'hidden',
|
||||||
} );
|
} );
|
||||||
|
|
||||||
expect(
|
await expect(
|
||||||
await page.textContent(
|
page.locator( '.shipping ul#shipping_method > li > label' )
|
||||||
'.shipping ul#shipping_method > li > label'
|
).toContainText( 'Flat rate:' );
|
||||||
)
|
await expect(
|
||||||
).toBe( 'Flat rate: $10.00' );
|
page.locator( '.shipping ul#shipping_method > li > label' )
|
||||||
expect(
|
).toContainText( '10.00' );
|
||||||
await page.textContent(
|
await expect(
|
||||||
'td[data-title="Total"] > strong > .amount > bdi'
|
page.locator( 'td[data-title="Total"] > strong > .amount > bdi' )
|
||||||
)
|
).toContainText( '35.99' );
|
||||||
).toBe( '$35.99' );
|
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -20,10 +20,13 @@ test.describe( 'Add New Simple Product Page', () => {
|
||||||
// and the flat rate shipping method to that zone
|
// and the flat rate shipping method to that zone
|
||||||
await api
|
await api
|
||||||
.post( 'shipping/zones', {
|
.post( 'shipping/zones', {
|
||||||
name: 'Everywhere',
|
name: 'Somewhere',
|
||||||
} )
|
} )
|
||||||
.then( ( response ) => {
|
.then( ( response ) => {
|
||||||
shippingZoneId = response.data.id;
|
shippingZoneId = response.data.id;
|
||||||
|
api.put( `shipping/zones/${ shippingZoneId }/locations`, [
|
||||||
|
{ code: 'CN' },
|
||||||
|
] );
|
||||||
api.post( `shipping/zones/${ shippingZoneId }/methods`, {
|
api.post( `shipping/zones/${ shippingZoneId }/methods`, {
|
||||||
method_id: 'flat_rate',
|
method_id: 'flat_rate',
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -34,8 +34,6 @@ test.describe( 'Add New Variable Product Page', () => {
|
||||||
) {
|
) {
|
||||||
api.delete( `products/${ product.id }`, {
|
api.delete( `products/${ product.id }`, {
|
||||||
force: true,
|
force: true,
|
||||||
} ).then( () => {
|
|
||||||
// nothing to do here.
|
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,8 +288,8 @@ test.describe( 'Add New Variable Product Page', () => {
|
||||||
|
|
||||||
// remove a variation
|
// remove a variation
|
||||||
page.on( 'dialog', ( dialog ) => dialog.accept() );
|
page.on( 'dialog', ( dialog ) => dialog.accept() );
|
||||||
await page.click( '.remove_variation.delete', { force: true } );
|
await page.hover( '.woocommerce_variation' );
|
||||||
await page.click( '.remove_variation.delete' ); // have to do this twice to get the link to appear
|
await page.click( '.remove_variation.delete' );
|
||||||
await expect( page.locator( '.woocommerce_variation' ) ).toHaveCount(
|
await expect( page.locator( '.woocommerce_variation' ) ).toHaveCount(
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,6 +4,8 @@ const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
let productId, couponId, orderId;
|
let productId, couponId, orderId;
|
||||||
|
|
||||||
const productPrice = '9.99';
|
const productPrice = '9.99';
|
||||||
|
const productName = 'Apply Coupon Product';
|
||||||
|
const couponCode = '5off';
|
||||||
const couponAmount = '5';
|
const couponAmount = '5';
|
||||||
const discountedPrice = ( productPrice - couponAmount ).toString();
|
const discountedPrice = ( productPrice - couponAmount ).toString();
|
||||||
|
|
||||||
|
@ -20,7 +22,7 @@ test.describe( 'WooCommerce Orders > Apply Coupon', () => {
|
||||||
// create a simple product
|
// create a simple product
|
||||||
await api
|
await api
|
||||||
.post( 'products', {
|
.post( 'products', {
|
||||||
name: 'Simple Product',
|
name: productName,
|
||||||
type: 'simple',
|
type: 'simple',
|
||||||
regular_price: productPrice,
|
regular_price: productPrice,
|
||||||
} )
|
} )
|
||||||
|
@ -30,7 +32,7 @@ test.describe( 'WooCommerce Orders > Apply Coupon', () => {
|
||||||
// create a $5 off coupon
|
// create a $5 off coupon
|
||||||
await api
|
await api
|
||||||
.post( 'coupons', {
|
.post( 'coupons', {
|
||||||
code: '5off',
|
code: couponCode,
|
||||||
discount_type: 'fixed_product',
|
discount_type: 'fixed_product',
|
||||||
amount: couponAmount,
|
amount: couponAmount,
|
||||||
} )
|
} )
|
||||||
|
@ -48,7 +50,7 @@ test.describe( 'WooCommerce Orders > Apply Coupon', () => {
|
||||||
],
|
],
|
||||||
coupon_lines: [
|
coupon_lines: [
|
||||||
{
|
{
|
||||||
code: '5off',
|
code: couponCode,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} )
|
} )
|
||||||
|
@ -81,7 +83,7 @@ test.describe( 'WooCommerce Orders > Apply Coupon', () => {
|
||||||
await page.click( 'text=Search for a product…' );
|
await page.click( 'text=Search for a product…' );
|
||||||
await page.type(
|
await page.type(
|
||||||
'input:below(:text("Search for a product…"))',
|
'input:below(:text("Search for a product…"))',
|
||||||
'Simple Product'
|
productName
|
||||||
);
|
);
|
||||||
await page.click(
|
await page.click(
|
||||||
'li.select2-results__option.select2-results__option--highlighted'
|
'li.select2-results__option.select2-results__option--highlighted'
|
||||||
|
@ -90,10 +92,10 @@ test.describe( 'WooCommerce Orders > Apply Coupon', () => {
|
||||||
await page.click( 'button#btn-ok' );
|
await page.click( 'button#btn-ok' );
|
||||||
|
|
||||||
// apply coupon
|
// apply coupon
|
||||||
page.on( 'dialog', ( dialog ) => dialog.accept( '5off' ) );
|
page.on( 'dialog', ( dialog ) => dialog.accept( couponCode ) );
|
||||||
await page.click( 'button.add-coupon' );
|
await page.click( 'button.add-coupon' );
|
||||||
|
|
||||||
await expect( page.locator( 'text=5off' ) ).toBeVisible();
|
await expect( page.locator( `text=${ couponCode }` ) ).toBeVisible();
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( '.wc-order-totals td.label >> nth=1' )
|
page.locator( '.wc-order-totals td.label >> nth=1' )
|
||||||
).toContainText( 'Coupon(s)' );
|
).toContainText( 'Coupon(s)' );
|
||||||
|
@ -111,7 +113,7 @@ test.describe( 'WooCommerce Orders > Apply Coupon', () => {
|
||||||
test( 'can remove a coupon', async ( { page } ) => {
|
test( 'can remove a coupon', async ( { page } ) => {
|
||||||
await page.goto( `/wp-admin/post.php?post=${ orderId }&action=edit` );
|
await page.goto( `/wp-admin/post.php?post=${ orderId }&action=edit` );
|
||||||
// assert that there is a coupon on the order
|
// assert that there is a coupon on the order
|
||||||
await expect( page.locator( 'text=5off' ) ).toBeVisible();
|
await expect( page.locator( `text=${ couponCode }` ) ).toBeVisible();
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( '.wc-order-totals td.label >> nth=1' )
|
page.locator( '.wc-order-totals td.label >> nth=1' )
|
||||||
).toContainText( 'Coupon(s)' );
|
).toContainText( 'Coupon(s)' );
|
||||||
|
@ -128,12 +130,14 @@ test.describe( 'WooCommerce Orders > Apply Coupon', () => {
|
||||||
await page.dispatchEvent( 'a.remove-coupon', 'click' ); // have to use dispatchEvent because nothing visible to click on
|
await page.dispatchEvent( 'a.remove-coupon', 'click' ); // have to use dispatchEvent because nothing visible to click on
|
||||||
|
|
||||||
// make sure the coupon was removed
|
// make sure the coupon was removed
|
||||||
await expect( page.locator( 'text=5off' ) ).not.toBeVisible();
|
await expect(
|
||||||
|
page.locator( `text=${ couponCode }` )
|
||||||
|
).not.toBeVisible();
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( '.wc-order-totals td.label >> nth=1' )
|
page.locator( '.wc-order-totals td.label >> nth=1' )
|
||||||
).toContainText( 'Order Total' );
|
).toContainText( 'Order Total' );
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( '.wc-order-totals td.total >> nth=1' )
|
page.locator( '.wc-order-totals td.total >> nth=1' )
|
||||||
).toContainText( '$9.99' );
|
).toContainText( productPrice );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -2,11 +2,11 @@ const { test, expect } = require( '@playwright/test' );
|
||||||
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
const uuid = require( 'uuid' );
|
const uuid = require( 'uuid' );
|
||||||
|
|
||||||
let orderId;
|
test.describe( 'Edit order', () => {
|
||||||
|
|
||||||
test.describe( 'WooCommerce Orders > Edit order', () => {
|
|
||||||
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
|
|
||||||
|
let orderId;
|
||||||
|
|
||||||
test.beforeAll( async ( { baseURL } ) => {
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
const api = new wcApi( {
|
const api = new wcApi( {
|
||||||
url: baseURL,
|
url: baseURL,
|
||||||
|
@ -86,9 +86,7 @@ test.describe( 'WooCommerce Orders > Edit order', () => {
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test.describe(
|
test.describe( 'Edit order > Downloadable product permissions', () => {
|
||||||
'WooCommerce Orders > Edit order > Downloadable product permissions',
|
|
||||||
() => {
|
|
||||||
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
|
|
||||||
const productName = 'TDP 001';
|
const productName = 'TDP 001';
|
||||||
|
@ -97,7 +95,7 @@ test.describe(
|
||||||
email: 'john.doe@example.com',
|
email: 'john.doe@example.com',
|
||||||
};
|
};
|
||||||
|
|
||||||
let productId, product2Id, noProductOrderId;
|
let orderId, productId, product2Id, noProductOrderId;
|
||||||
|
|
||||||
test.beforeEach( async ( { baseURL } ) => {
|
test.beforeEach( async ( { baseURL } ) => {
|
||||||
const api = new wcApi( {
|
const api = new wcApi( {
|
||||||
|
@ -193,21 +191,15 @@ test.describe(
|
||||||
await page.click( 'button.grant_access' );
|
await page.click( 'button.grant_access' );
|
||||||
|
|
||||||
// verify new downloadable product permission details
|
// verify new downloadable product permission details
|
||||||
await expect( page.locator( 'h3.fixed' ) ).toContainText(
|
await expect( page.locator( 'h3.fixed' ) ).toContainText( productName );
|
||||||
productName
|
|
||||||
);
|
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( 'input[name="downloads_remaining[1]"]' )
|
page.locator( 'input[name="downloads_remaining[1]"]' )
|
||||||
).toHaveAttribute( 'placeholder', 'Unlimited' );
|
).toHaveAttribute( 'placeholder', 'Unlimited' );
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( 'input[name="access_expires[1]"]' )
|
page.locator( 'input[name="access_expires[1]"]' )
|
||||||
).toHaveAttribute( 'placeholder', 'Never' );
|
).toHaveAttribute( 'placeholder', 'Never' );
|
||||||
await expect(
|
await expect( page.locator( 'button.revoke_access' ) ).toBeVisible();
|
||||||
page.locator( 'button.revoke_access' )
|
await expect( page.locator( 'a:has-text("Copy link")' ) ).toBeVisible();
|
||||||
).toBeVisible();
|
|
||||||
await expect(
|
|
||||||
page.locator( 'a:has-text("Copy link")' )
|
|
||||||
).toBeVisible();
|
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( 'a:has-text("View report")' )
|
page.locator( 'a:has-text("View report")' )
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
|
@ -217,9 +209,7 @@ test.describe(
|
||||||
page,
|
page,
|
||||||
} ) => {
|
} ) => {
|
||||||
// open the order that already has a product assigned
|
// open the order that already has a product assigned
|
||||||
await page.goto(
|
await page.goto( `wp-admin/post.php?post=${ orderId }&action=edit` );
|
||||||
`wp-admin/post.php?post=${ orderId }&action=edit`
|
|
||||||
);
|
|
||||||
|
|
||||||
// add downloadable product permissions
|
// add downloadable product permissions
|
||||||
await page.type( 'input.select2-search__field', product2Name );
|
await page.type( 'input.select2-search__field', product2Name );
|
||||||
|
@ -240,16 +230,12 @@ test.describe(
|
||||||
).toHaveAttribute( 'placeholder', 'Never' );
|
).toHaveAttribute( 'placeholder', 'Never' );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'can edit downloadable product permissions', async ( {
|
test( 'can edit downloadable product permissions', async ( { page } ) => {
|
||||||
page,
|
|
||||||
} ) => {
|
|
||||||
const expectedDownloadsRemaining = '10';
|
const expectedDownloadsRemaining = '10';
|
||||||
const expectedDownloadsExpirationDate = '2050-01-01';
|
const expectedDownloadsExpirationDate = '2050-01-01';
|
||||||
|
|
||||||
// open the order that already has a product assigned
|
// open the order that already has a product assigned
|
||||||
await page.goto(
|
await page.goto( `wp-admin/post.php?post=${ orderId }&action=edit` );
|
||||||
`wp-admin/post.php?post=${ orderId }&action=edit`
|
|
||||||
);
|
|
||||||
|
|
||||||
// expand product download permissions
|
// expand product download permissions
|
||||||
await page.click( 'h3.fixed' );
|
await page.click( 'h3.fixed' );
|
||||||
|
@ -275,13 +261,9 @@ test.describe(
|
||||||
).toHaveValue( expectedDownloadsExpirationDate );
|
).toHaveValue( expectedDownloadsExpirationDate );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'can revoke downloadable product permissions', async ( {
|
test( 'can revoke downloadable product permissions', async ( { page } ) => {
|
||||||
page,
|
|
||||||
} ) => {
|
|
||||||
// open the order that already has a product assigned
|
// open the order that already has a product assigned
|
||||||
await page.goto(
|
await page.goto( `wp-admin/post.php?post=${ orderId }&action=edit` );
|
||||||
`wp-admin/post.php?post=${ orderId }&action=edit`
|
|
||||||
);
|
|
||||||
|
|
||||||
// expand product download permissions
|
// expand product download permissions
|
||||||
await page.click( 'h3.fixed' );
|
await page.click( 'h3.fixed' );
|
||||||
|
@ -305,9 +287,7 @@ test.describe(
|
||||||
'Sorry, you have reached your download limit for this file';
|
'Sorry, you have reached your download limit for this file';
|
||||||
|
|
||||||
// open the order that already has a product assigned
|
// open the order that already has a product assigned
|
||||||
await page.goto(
|
await page.goto( `wp-admin/post.php?post=${ orderId }&action=edit` );
|
||||||
`wp-admin/post.php?post=${ orderId }&action=edit`
|
|
||||||
);
|
|
||||||
|
|
||||||
// set the download limit to 0
|
// set the download limit to 0
|
||||||
// expand product download permissions
|
// expand product download permissions
|
||||||
|
@ -336,9 +316,7 @@ test.describe(
|
||||||
const expectedReason = 'Sorry, this download has expired';
|
const expectedReason = 'Sorry, this download has expired';
|
||||||
|
|
||||||
// open the order that already has a product assigned
|
// open the order that already has a product assigned
|
||||||
await page.goto(
|
await page.goto( `wp-admin/post.php?post=${ orderId }&action=edit` );
|
||||||
`wp-admin/post.php?post=${ orderId }&action=edit`
|
|
||||||
);
|
|
||||||
|
|
||||||
// set the download limit to 0
|
// set the download limit to 0
|
||||||
// expand product download permissions
|
// expand product download permissions
|
||||||
|
@ -360,5 +338,4 @@ test.describe(
|
||||||
expectedReason
|
expectedReason
|
||||||
);
|
);
|
||||||
} );
|
} );
|
||||||
}
|
} );
|
||||||
);
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ test.describe( 'Merchant > Order Action emails received', () => {
|
||||||
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
|
|
||||||
const customerBilling = {
|
const customerBilling = {
|
||||||
email: 'john.doe@example.com',
|
email: 'john.doe.merchant.test@example.com',
|
||||||
};
|
};
|
||||||
const adminEmail = 'admin@woocommercecoree2etestsuite.com';
|
const adminEmail = 'admin@woocommercecoree2etestsuite.com';
|
||||||
const storeName = 'WooCommerce Core E2E Test Suite';
|
const storeName = 'WooCommerce Core E2E Test Suite';
|
||||||
|
@ -29,7 +29,11 @@ test.describe( 'Merchant > Order Action emails received', () => {
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test.beforeEach( async ( { page } ) => {
|
test.beforeEach( async ( { page } ) => {
|
||||||
await page.goto( 'wp-admin/tools.php?page=wpml_plugin_log' );
|
await page.goto(
|
||||||
|
`wp-admin/tools.php?page=wpml_plugin_log&s=${ encodeURIComponent(
|
||||||
|
customerBilling.email
|
||||||
|
) }`
|
||||||
|
);
|
||||||
// clear out the email logs before each test
|
// clear out the email logs before each test
|
||||||
while ( ( await page.$( '#bulk-action-selector-top' ) ) !== null ) {
|
while ( ( await page.$( '#bulk-action-selector-top' ) ) !== null ) {
|
||||||
await page.click( '#cb-select-all-1' );
|
await page.click( '#cb-select-all-1' );
|
||||||
|
@ -46,6 +50,7 @@ test.describe( 'Merchant > Order Action emails received', () => {
|
||||||
version: 'wc/v3',
|
version: 'wc/v3',
|
||||||
} );
|
} );
|
||||||
await api.delete( `orders/${ orderId }`, { force: true } );
|
await api.delete( `orders/${ orderId }`, { force: true } );
|
||||||
|
await api.delete( `orders/${ newOrderId }`, { force: true } );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'can receive new order email', async ( { page, baseURL } ) => {
|
test( 'can receive new order email', async ( { page, baseURL } ) => {
|
||||||
|
@ -65,16 +70,18 @@ test.describe( 'Merchant > Order Action emails received', () => {
|
||||||
.then( ( response ) => {
|
.then( ( response ) => {
|
||||||
newOrderId = response.data.id;
|
newOrderId = response.data.id;
|
||||||
} );
|
} );
|
||||||
|
// search to narrow it down to just the messages we want
|
||||||
await page.goto( 'wp-admin/tools.php?page=wpml_plugin_log' );
|
await page.goto(
|
||||||
|
`wp-admin/tools.php?page=wpml_plugin_log&s=${ encodeURIComponent(
|
||||||
|
customerBilling.email
|
||||||
|
) }`
|
||||||
|
);
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( 'td.column-receiver >> nth=1' )
|
page.locator( 'td.column-receiver >> nth=1' )
|
||||||
).toContainText( adminEmail );
|
).toContainText( adminEmail );
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( 'td.column-subject >> nth=1' )
|
page.locator( 'td.column-subject >> nth=1' )
|
||||||
).toContainText( `[${ storeName }]: New order #${ newOrderId }` );
|
).toContainText( `[${ storeName }]: New order #${ newOrderId }` );
|
||||||
|
|
||||||
await api.delete( `orders/${ newOrderId }`, { force: true } );
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'can resend new order notification', async ( { page } ) => {
|
test( 'can resend new order notification', async ( { page } ) => {
|
||||||
|
@ -87,8 +94,12 @@ test.describe( 'Merchant > Order Action emails received', () => {
|
||||||
await page.click( 'button.wc-reload' );
|
await page.click( 'button.wc-reload' );
|
||||||
await page.waitForLoadState( 'networkidle' );
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
// confirm the message was delivered in the logs
|
// search to narrow it down to just the messages we want
|
||||||
await page.goto( 'wp-admin/tools.php?page=wpml_plugin_log' );
|
await page.goto(
|
||||||
|
`wp-admin/tools.php?page=wpml_plugin_log&s=${ encodeURIComponent(
|
||||||
|
customerBilling.email
|
||||||
|
) }`
|
||||||
|
);
|
||||||
await expect( page.locator( 'td.column-receiver' ) ).toContainText(
|
await expect( page.locator( 'td.column-receiver' ) ).toContainText(
|
||||||
adminEmail
|
adminEmail
|
||||||
);
|
);
|
||||||
|
@ -105,7 +116,11 @@ test.describe( 'Merchant > Order Action emails received', () => {
|
||||||
await page.waitForLoadState( 'networkidle' );
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
// confirm the message was delivered in the logs
|
// confirm the message was delivered in the logs
|
||||||
await page.goto( 'wp-admin/tools.php?page=wpml_plugin_log' );
|
await page.goto(
|
||||||
|
`wp-admin/tools.php?page=wpml_plugin_log&s=${ encodeURIComponent(
|
||||||
|
customerBilling.email
|
||||||
|
) }`
|
||||||
|
);
|
||||||
await expect( page.locator( 'td.column-receiver' ) ).toContainText(
|
await expect( page.locator( 'td.column-receiver' ) ).toContainText(
|
||||||
customerBilling.email
|
customerBilling.email
|
||||||
);
|
);
|
||||||
|
|
|
@ -226,7 +226,7 @@ test.describe( 'WooCommerce Orders > Refund and restock an order item', () => {
|
||||||
|
|
||||||
// Update the order
|
// Update the order
|
||||||
await page.click( 'button.save_order' );
|
await page.click( 'button.save_order' );
|
||||||
await expect( page.locator( 'div.notice-success' ) ).toHaveText(
|
await expect( page.locator( 'div.notice-success' ) ).toContainText(
|
||||||
'Order updated.'
|
'Order updated.'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
const { test, expect } = require( '@playwright/test' );
|
const { test, expect } = require( '@playwright/test' );
|
||||||
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
const searchString = 'John Doe';
|
const searchString = 'James Doe';
|
||||||
const itemName = 'Wanted Product';
|
const itemName = 'Wanted Product';
|
||||||
|
|
||||||
const customerBilling = {
|
const customerBilling = {
|
||||||
first_name: 'John',
|
first_name: 'James',
|
||||||
last_name: 'Doe',
|
last_name: 'Doe',
|
||||||
company: 'Automattic',
|
company: 'Automattic',
|
||||||
country: 'US',
|
country: 'US',
|
||||||
|
@ -15,7 +15,7 @@ const customerBilling = {
|
||||||
state: 'CA',
|
state: 'CA',
|
||||||
postcode: '94107',
|
postcode: '94107',
|
||||||
phone: '123456789',
|
phone: '123456789',
|
||||||
email: 'john.doe@example.com',
|
email: 'john.doe.ordersearch@example.com',
|
||||||
};
|
};
|
||||||
const customerShipping = {
|
const customerShipping = {
|
||||||
first_name: 'Tim',
|
first_name: 'Tim',
|
||||||
|
@ -28,7 +28,7 @@ const customerShipping = {
|
||||||
state: 'NY',
|
state: 'NY',
|
||||||
postcode: '14201',
|
postcode: '14201',
|
||||||
phone: '123456789',
|
phone: '123456789',
|
||||||
email: 'john.doe@example.com',
|
email: 'john.doe.ordersearch@example.com',
|
||||||
};
|
};
|
||||||
|
|
||||||
const queries = [
|
const queries = [
|
||||||
|
@ -76,9 +76,9 @@ test.describe( 'WooCommerce Orders > Search orders', () => {
|
||||||
// update customer info
|
// update customer info
|
||||||
await api
|
await api
|
||||||
.post( 'customers', {
|
.post( 'customers', {
|
||||||
email: 'john.doe@example.com',
|
email: customerBilling.email,
|
||||||
first_name: 'John',
|
first_name: customerBilling.first_name,
|
||||||
last_name: 'Doe',
|
last_name: customerBilling.last_name,
|
||||||
username: 'john.doe',
|
username: 'john.doe',
|
||||||
billing: customerBilling,
|
billing: customerBilling,
|
||||||
shipping: customerShipping,
|
shipping: customerShipping,
|
||||||
|
@ -134,8 +134,9 @@ test.describe( 'WooCommerce Orders > Search orders', () => {
|
||||||
await page.fill( '#post-search-input', queries[ i ][ 0 ] );
|
await page.fill( '#post-search-input', queries[ i ][ 0 ] );
|
||||||
await page.click( '#search-submit' );
|
await page.click( '#search-submit' );
|
||||||
|
|
||||||
|
// always check the last item, in case of multiples
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( '.order_number > a.order-view' )
|
page.locator( '.order_number > a.order-view >> nth=-1' )
|
||||||
).toContainText( `#${ orderId } ${ searchString }` );
|
).toContainText( `#${ orderId } ${ searchString }` );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,13 +56,12 @@ test.describe( 'WooCommerce Orders > Filter Order by Status', () => {
|
||||||
await page.goto( 'wp-admin/edit.php?post_type=shop_order' );
|
await page.goto( 'wp-admin/edit.php?post_type=shop_order' );
|
||||||
|
|
||||||
await page.click( 'li.all > a' );
|
await page.click( 'li.all > a' );
|
||||||
await page.click( 'th#order_number > a' ); // ensure we're sorting in the right order
|
// because tests are running in parallel, we can't know how many orders there
|
||||||
let i = 0;
|
// are beyond the ones we created here.
|
||||||
for ( const [ statusText ] of orderStatus ) {
|
for ( let i = 0; i < orderStatus.length; i++ ) {
|
||||||
await expect(
|
const statusTag = 'text=' + orderStatus[ i ][ 0 ];
|
||||||
page.locator( `${ statusColumnTextSelector } >> nth=${ i }` )
|
const countElements = await page.locator( statusTag ).count();
|
||||||
).toContainText( statusText );
|
await expect( countElements ).toBeGreaterThan( 0 );
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -73,9 +72,10 @@ test.describe( 'WooCommerce Orders > Filter Order by Status', () => {
|
||||||
await page.goto( 'wp-admin/edit.php?post_type=shop_order' );
|
await page.goto( 'wp-admin/edit.php?post_type=shop_order' );
|
||||||
|
|
||||||
await page.click( `li.${ orderStatus[ i ][ 1 ] }` );
|
await page.click( `li.${ orderStatus[ i ][ 1 ] }` );
|
||||||
await expect(
|
const countElements = await page
|
||||||
page.locator( statusColumnTextSelector )
|
.locator( statusColumnTextSelector )
|
||||||
).toContainText( orderStatus[ i ][ 0 ] );
|
.count();
|
||||||
|
await expect( countElements ).toBeGreaterThan( 0 );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -7,46 +7,47 @@ const filePathOverride = path.resolve(
|
||||||
);
|
);
|
||||||
|
|
||||||
const productIds = [];
|
const productIds = [];
|
||||||
|
const categoryIds = [];
|
||||||
|
|
||||||
const productNames = [
|
const productNames = [
|
||||||
'V-Neck T-Shirt',
|
'Imported V-Neck T-Shirt',
|
||||||
'Hoodie',
|
'Imported Hoodie',
|
||||||
'Hoodie with Logo',
|
'Imported Hoodie with Logo',
|
||||||
'T-Shirt',
|
'Imported T-Shirt',
|
||||||
'Beanie',
|
'Imported Beanie',
|
||||||
'Belt',
|
'Imported Belt',
|
||||||
'Cap',
|
'Imported Cap',
|
||||||
'Sunglasses',
|
'Imported Sunglasses',
|
||||||
'Hoodie with Pocket',
|
'Imported Hoodie with Pocket',
|
||||||
'Hoodie with Zipper',
|
'Imported Hoodie with Zipper',
|
||||||
'Long Sleeve Tee',
|
'Imported Long Sleeve Tee',
|
||||||
'Polo',
|
'Imported Polo',
|
||||||
'Album',
|
'Imported Album',
|
||||||
'Single',
|
'Imported Single',
|
||||||
'T-Shirt with Logo',
|
'Imported T-Shirt with Logo',
|
||||||
'Beanie with Logo',
|
'Imported Beanie with Logo',
|
||||||
'Logo Collection',
|
'Imported Logo Collection',
|
||||||
'WordPress Pennant',
|
'Imported WordPress Pennant',
|
||||||
];
|
];
|
||||||
const productNamesOverride = [
|
const productNamesOverride = [
|
||||||
'V-Neck T-Shirt Override',
|
'Imported V-Neck T-Shirt Override',
|
||||||
'Hoodie Override',
|
'Imported Hoodie Override',
|
||||||
'Hoodie with Logo Override',
|
'Imported Hoodie with Logo Override',
|
||||||
'T-Shirt Override',
|
'Imported T-Shirt Override',
|
||||||
'Beanie Override',
|
'Imported Beanie Override',
|
||||||
'Belt Override',
|
'Imported Belt Override',
|
||||||
'Cap Override',
|
'Imported Cap Override',
|
||||||
'Sunglasses Override',
|
'Imported Sunglasses Override',
|
||||||
'Hoodie with Pocket Override',
|
'Imported Hoodie with Pocket Override',
|
||||||
'Hoodie with Zipper Override',
|
'Imported Hoodie with Zipper Override',
|
||||||
'Long Sleeve Tee Override',
|
'Imported Long Sleeve Tee Override',
|
||||||
'Polo Override',
|
'Imported Polo Override',
|
||||||
'Album Override',
|
'Imported Album Override',
|
||||||
'Single Override',
|
'Imported Single Override',
|
||||||
'T-Shirt with Logo Override',
|
'Imported T-Shirt with Logo Override',
|
||||||
'Beanie with Logo Override',
|
'Imported Beanie with Logo Override',
|
||||||
'Logo Collection Override',
|
'Imported Logo Collection Override',
|
||||||
'WordPress Pennant Override',
|
'Imported WordPress Pennant Override',
|
||||||
];
|
];
|
||||||
const productPricesOverride = [
|
const productPricesOverride = [
|
||||||
'$111.05',
|
'$111.05',
|
||||||
|
@ -77,6 +78,15 @@ const productPricesOverride = [
|
||||||
'$115.00',
|
'$115.00',
|
||||||
'$120.00',
|
'$120.00',
|
||||||
];
|
];
|
||||||
|
const productCategories = [
|
||||||
|
'Clothing',
|
||||||
|
'Hoodies',
|
||||||
|
'Tshirts',
|
||||||
|
'Accessories',
|
||||||
|
'Music',
|
||||||
|
'Decor',
|
||||||
|
];
|
||||||
|
|
||||||
const errorMessage =
|
const errorMessage =
|
||||||
'Invalid file type. The importer supports CSV and TXT file formats.';
|
'Invalid file type. The importer supports CSV and TXT file formats.';
|
||||||
|
|
||||||
|
@ -91,7 +101,7 @@ test.describe( 'Import Products from a CSV file', () => {
|
||||||
version: 'wc/v3',
|
version: 'wc/v3',
|
||||||
} );
|
} );
|
||||||
// get a list of all products
|
// get a list of all products
|
||||||
await api.get( 'products?per_page=20' ).then( ( response ) => {
|
await api.get( 'products?per_page=50' ).then( ( response ) => {
|
||||||
for ( let i = 0; i < response.data.length; i++ ) {
|
for ( let i = 0; i < response.data.length; i++ ) {
|
||||||
// if the product is one we imported, add it to the array
|
// if the product is one we imported, add it to the array
|
||||||
for ( let j = 0; j < productNamesOverride.length; j++ ) {
|
for ( let j = 0; j < productNamesOverride.length; j++ ) {
|
||||||
|
@ -105,6 +115,21 @@ test.describe( 'Import Products from a CSV file', () => {
|
||||||
} );
|
} );
|
||||||
// batch delete all products in the array
|
// batch delete all products in the array
|
||||||
await api.post( 'products/batch', { delete: [ ...productIds ] } );
|
await api.post( 'products/batch', { delete: [ ...productIds ] } );
|
||||||
|
// get a list of all product categories
|
||||||
|
await api.get( 'products/categories' ).then( ( response ) => {
|
||||||
|
for ( let i = 0; i < response.data.length; i++ ) {
|
||||||
|
// if the product category is one that was created, add it to the array
|
||||||
|
for ( let j = 0; j < productCategories.length; j++ ) {
|
||||||
|
if ( response.data[ i ].name === productCategories[ j ] ) {
|
||||||
|
categoryIds.push( response.data[ i ].id );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
// batch delete all categories in the array
|
||||||
|
await api.post( 'products/categories/batch', {
|
||||||
|
delete: [ ...categoryIds ],
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'should show error message if you go without providing CSV file', async ( {
|
test( 'should show error message if you go without providing CSV file', async ( {
|
||||||
|
@ -145,8 +170,15 @@ test.describe( 'Import Products from a CSV file', () => {
|
||||||
// View the products
|
// View the products
|
||||||
await page.click( 'text=View products' );
|
await page.click( 'text=View products' );
|
||||||
|
|
||||||
|
// Search for "import" to narrow the results to just the products we imported
|
||||||
|
await page.fill( '#post-search-input', 'Imported' );
|
||||||
|
await page.click( '#search-submit' );
|
||||||
|
|
||||||
// Compare imported products to what's expected
|
// Compare imported products to what's expected
|
||||||
await page.waitForSelector( 'a.row-title' );
|
await page.waitForSelector( 'a.row-title', {
|
||||||
|
state: 'visible',
|
||||||
|
timeout: 120000, // search can take a while
|
||||||
|
} );
|
||||||
const productTitles = await page.$$eval( 'a.row-title', ( elements ) =>
|
const productTitles = await page.$$eval( 'a.row-title', ( elements ) =>
|
||||||
elements.map( ( item ) => item.innerHTML )
|
elements.map( ( item ) => item.innerHTML )
|
||||||
);
|
);
|
||||||
|
@ -176,11 +208,15 @@ test.describe( 'Import Products from a CSV file', () => {
|
||||||
// Confirm that the import is done
|
// Confirm that the import is done
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( '.woocommerce-importer-done' )
|
page.locator( '.woocommerce-importer-done' )
|
||||||
).toContainText( 'Import complete!', { timeout: 120000 } );
|
).toContainText( 'Import complete!', { timeout: 120000 } ); // import can take a while
|
||||||
|
|
||||||
// View the products
|
// View the products
|
||||||
await page.click( 'text=View products' );
|
await page.click( 'text=View products' );
|
||||||
|
|
||||||
|
// Search for "import" to narrow the results to just the products we imported
|
||||||
|
await page.fill( '#post-search-input', 'Imported' );
|
||||||
|
await page.click( '#search-submit' );
|
||||||
|
|
||||||
// Compare imported products to what's expected
|
// Compare imported products to what's expected
|
||||||
await page.waitForSelector( 'a.row-title' );
|
await page.waitForSelector( 'a.row-title' );
|
||||||
const productTitles = await page.$$eval( 'a.row-title', ( elements ) =>
|
const productTitles = await page.$$eval( 'a.row-title', ( elements ) =>
|
||||||
|
|
|
@ -2,7 +2,7 @@ const { test, expect } = require( '@playwright/test' );
|
||||||
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
let productId;
|
let productId;
|
||||||
const productName = 'Simple product to search';
|
const productName = 'Unique thing that we sell';
|
||||||
const productPrice = '9.99';
|
const productPrice = '9.99';
|
||||||
|
|
||||||
test.describe( 'Products > Search and View a product', () => {
|
test.describe( 'Products > Search and View a product', () => {
|
||||||
|
@ -46,6 +46,7 @@ test.describe( 'Products > Search and View a product', () => {
|
||||||
|
|
||||||
await page.fill( '#post-search-input', searchString );
|
await page.fill( '#post-search-input', searchString );
|
||||||
await page.click( '#search-submit' );
|
await page.click( '#search-submit' );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
await expect( page.locator( '.row-title' ) ).toContainText(
|
await expect( page.locator( '.row-title' ) ).toContainText(
|
||||||
productName
|
productName
|
||||||
|
|
|
@ -28,7 +28,7 @@ test.describe( 'WooCommerce Products > Downloadable Product Settings', () => {
|
||||||
await page.click( 'text=Save changes' );
|
await page.click( 'text=Save changes' );
|
||||||
|
|
||||||
// Verify that settings have been saved
|
// Verify that settings have been saved
|
||||||
await expect( page.locator( 'div.inline' ) ).toContainText(
|
await expect( page.locator( 'div.updated.inline' ) ).toContainText(
|
||||||
'Your settings have been saved.'
|
'Your settings have been saved.'
|
||||||
);
|
);
|
||||||
await expect(
|
await expect(
|
||||||
|
@ -64,7 +64,7 @@ test.describe( 'WooCommerce Products > Downloadable Product Settings', () => {
|
||||||
await page.click( 'text=Save changes' );
|
await page.click( 'text=Save changes' );
|
||||||
|
|
||||||
// Verify that settings have been saved
|
// Verify that settings have been saved
|
||||||
await expect( page.locator( 'div.inline' ) ).toContainText(
|
await expect( page.locator( 'div.updated.inline' ) ).toContainText(
|
||||||
'Your settings have been saved.'
|
'Your settings have been saved.'
|
||||||
);
|
);
|
||||||
await expect(
|
await expect(
|
||||||
|
@ -89,7 +89,7 @@ test.describe( 'WooCommerce Products > Downloadable Product Settings', () => {
|
||||||
await page.click( 'text=Save changes' );
|
await page.click( 'text=Save changes' );
|
||||||
|
|
||||||
// Verify that settings have been saved
|
// Verify that settings have been saved
|
||||||
await expect( page.locator( 'div.inline' ) ).toContainText(
|
await expect( page.locator( 'div.updated.inline' ) ).toContainText(
|
||||||
'Your settings have been saved.'
|
'Your settings have been saved.'
|
||||||
);
|
);
|
||||||
await expect(
|
await expect(
|
||||||
|
|
|
@ -30,7 +30,7 @@ test.describe( 'WooCommerce General Settings', () => {
|
||||||
await page.click( 'text=Save changes' );
|
await page.click( 'text=Save changes' );
|
||||||
|
|
||||||
// confirm setting saved
|
// confirm setting saved
|
||||||
await expect( page.locator( 'div.inline' ) ).toContainText(
|
await expect( page.locator( 'div.updated.inline' ) ).toContainText(
|
||||||
'Your settings have been saved.'
|
'Your settings have been saved.'
|
||||||
);
|
);
|
||||||
await expect(
|
await expect(
|
||||||
|
@ -45,7 +45,7 @@ test.describe( 'WooCommerce General Settings', () => {
|
||||||
await page.click( 'text=Save changes' );
|
await page.click( 'text=Save changes' );
|
||||||
|
|
||||||
// verify the settings have been saved
|
// verify the settings have been saved
|
||||||
await expect( page.locator( 'div.inline' ) ).toContainText(
|
await expect( page.locator( 'div.updated.inline' ) ).toContainText(
|
||||||
'Your settings have been saved.'
|
'Your settings have been saved.'
|
||||||
);
|
);
|
||||||
await expect(
|
await expect(
|
||||||
|
@ -68,7 +68,7 @@ test.describe( 'WooCommerce General Settings', () => {
|
||||||
await page.click( 'text=Save changes' );
|
await page.click( 'text=Save changes' );
|
||||||
|
|
||||||
// verify that settings have been saved
|
// verify that settings have been saved
|
||||||
await expect( page.locator( 'div.inline' ) ).toContainText(
|
await expect( page.locator( 'div.updated.inline' ) ).toContainText(
|
||||||
'Your settings have been saved.'
|
'Your settings have been saved.'
|
||||||
);
|
);
|
||||||
await expect(
|
await expect(
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const { test, expect } = require( '@playwright/test' );
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
test.describe( 'WooCommerce Tax Settings', () => {
|
test.describe( 'WooCommerce Tax Settings > enable', () => {
|
||||||
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
|
|
||||||
test( 'can enable tax calculation', async ( { page } ) => {
|
test( 'can enable tax calculation', async ( { page } ) => {
|
||||||
|
@ -16,7 +17,7 @@ test.describe( 'WooCommerce Tax Settings', () => {
|
||||||
await page.click( 'text=Save changes' );
|
await page.click( 'text=Save changes' );
|
||||||
|
|
||||||
// Verify that settings have been saved
|
// Verify that settings have been saved
|
||||||
await expect( page.locator( 'div.inline' ) ).toContainText(
|
await expect( page.locator( 'div.updated.inline' ) ).toContainText(
|
||||||
'Your settings have been saved.'
|
'Your settings have been saved.'
|
||||||
);
|
);
|
||||||
await expect( page.locator( '#woocommerce_calc_taxes' ) ).toBeChecked();
|
await expect( page.locator( '#woocommerce_calc_taxes' ) ).toBeChecked();
|
||||||
|
@ -26,6 +27,33 @@ test.describe( 'WooCommerce Tax Settings', () => {
|
||||||
page.locator( 'a.nav-tab:has-text("Tax")' )
|
page.locator( 'a.nav-tab:has-text("Tax")' )
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
} );
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.describe( 'WooCommerce Tax Settings', () => {
|
||||||
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/general/woocommerce_calc_taxes', {
|
||||||
|
value: 'yes',
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
test.afterEach( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/general/woocommerce_calc_taxes', {
|
||||||
|
value: 'no',
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
test( 'can set tax options', async ( { page } ) => {
|
test( 'can set tax options', async ( { page } ) => {
|
||||||
await page.goto( 'wp-admin/admin.php?page=wc-settings&tab=tax' );
|
await page.goto( 'wp-admin/admin.php?page=wc-settings&tab=tax' );
|
||||||
|
@ -53,7 +81,7 @@ test.describe( 'WooCommerce Tax Settings', () => {
|
||||||
await page.click( 'text=Save changes' );
|
await page.click( 'text=Save changes' );
|
||||||
|
|
||||||
// Verify that settings have been saved
|
// Verify that settings have been saved
|
||||||
await expect( page.locator( 'div.inline' ) ).toContainText(
|
await expect( page.locator( 'div.updated.inline' ) ).toContainText(
|
||||||
'Your settings have been saved.'
|
'Your settings have been saved.'
|
||||||
);
|
);
|
||||||
await expect(
|
await expect(
|
||||||
|
@ -88,7 +116,7 @@ test.describe( 'WooCommerce Tax Settings', () => {
|
||||||
await page.click( 'text=Save changes' );
|
await page.click( 'text=Save changes' );
|
||||||
|
|
||||||
// Verify that the settings have been saved
|
// Verify that the settings have been saved
|
||||||
await expect( page.locator( 'div.inline' ) ).toContainText(
|
await expect( page.locator( 'div.updated.inline' ) ).toContainText(
|
||||||
'Your settings have been saved.'
|
'Your settings have been saved.'
|
||||||
);
|
);
|
||||||
await expect( page.locator( '#woocommerce_tax_classes' ) ).toHaveValue(
|
await expect( page.locator( '#woocommerce_tax_classes' ) ).toHaveValue(
|
||||||
|
@ -100,7 +128,7 @@ test.describe( 'WooCommerce Tax Settings', () => {
|
||||||
await page.click( 'text=Save changes' );
|
await page.click( 'text=Save changes' );
|
||||||
|
|
||||||
// Verify that the settings have been saved
|
// Verify that the settings have been saved
|
||||||
await expect( page.locator( 'div.inline' ) ).toContainText(
|
await expect( page.locator( 'div.updated.inline' ) ).toContainText(
|
||||||
'Your settings have been saved.'
|
'Your settings have been saved.'
|
||||||
);
|
);
|
||||||
await expect(
|
await expect(
|
||||||
|
@ -178,7 +206,7 @@ test.describe( 'WooCommerce Tax Settings', () => {
|
||||||
await page.click( 'text=Save changes' );
|
await page.click( 'text=Save changes' );
|
||||||
|
|
||||||
// Verify that settings have been saved
|
// Verify that settings have been saved
|
||||||
await expect( page.locator( 'div.inline' ) ).toContainText(
|
await expect( page.locator( 'div.updated.inline' ) ).toContainText(
|
||||||
'Your settings have been saved.'
|
'Your settings have been saved.'
|
||||||
);
|
);
|
||||||
await expect( page.locator( '#woocommerce_tax_classes' ) ).toHaveValue(
|
await expect( page.locator( '#woocommerce_tax_classes' ) ).toHaveValue(
|
||||||
|
|
|
@ -0,0 +1,220 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
const firstProductName = 'First Product';
|
||||||
|
const firstProductPrice = '9.99';
|
||||||
|
const secondProductName = 'Second Product';
|
||||||
|
const secondProductPrice = '4.99';
|
||||||
|
const fourProductsTotal = +firstProductPrice * 4;
|
||||||
|
const twoProductsTotal = +firstProductPrice + +secondProductPrice;
|
||||||
|
const firstProductWithFlatRate = +firstProductPrice + 5;
|
||||||
|
const fourProductsWithFlatRate = +fourProductsTotal + 5;
|
||||||
|
const twoProductsWithFlatRate = +twoProductsTotal + 5;
|
||||||
|
|
||||||
|
const shippingZoneNameDE = 'Germany Free Shipping';
|
||||||
|
const shippingCountryDE = 'DE';
|
||||||
|
const shippingZoneNameFR = 'France Flat Local';
|
||||||
|
const shippingCountryFR = 'FR';
|
||||||
|
|
||||||
|
test.describe( 'Cart Calculate Shipping', () => {
|
||||||
|
let firstProductId, secondProductId, shippingZoneDEId, shippingZoneFRId;
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add products
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: firstProductName,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: firstProductPrice,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
firstProductId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: secondProductName,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: secondProductPrice,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
secondProductId = response.data.id;
|
||||||
|
} );
|
||||||
|
// create shipping zones
|
||||||
|
await api
|
||||||
|
.post( 'shipping/zones', {
|
||||||
|
name: shippingZoneNameDE,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
shippingZoneDEId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api
|
||||||
|
.post( 'shipping/zones', {
|
||||||
|
name: shippingZoneNameFR,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
shippingZoneFRId = response.data.id;
|
||||||
|
} );
|
||||||
|
// set shipping zone locations
|
||||||
|
await api.put( `shipping/zones/${ shippingZoneDEId }/locations`, [
|
||||||
|
{
|
||||||
|
code: shippingCountryDE,
|
||||||
|
},
|
||||||
|
] );
|
||||||
|
await api.put( `shipping/zones/${ shippingZoneFRId }/locations`, [
|
||||||
|
{
|
||||||
|
code: shippingCountryFR,
|
||||||
|
},
|
||||||
|
] );
|
||||||
|
// set shipping zone methods
|
||||||
|
await api.post( `shipping/zones/${ shippingZoneDEId }/methods`, {
|
||||||
|
method_id: 'free_shipping',
|
||||||
|
} );
|
||||||
|
await api.post( `shipping/zones/${ shippingZoneFRId }/methods`, {
|
||||||
|
method_id: 'flat_rate',
|
||||||
|
settings: {
|
||||||
|
cost: '5.00',
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
await api.post( `shipping/zones/${ shippingZoneFRId }/methods`, {
|
||||||
|
method_id: 'local_pickup',
|
||||||
|
} );
|
||||||
|
// confirm that we allow shipping to any country
|
||||||
|
api.put( 'settings/general/woocommerce_allowed_countries', {
|
||||||
|
value: 'all',
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { page, context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
context.clearCookies();
|
||||||
|
|
||||||
|
// all tests use the first product
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ firstProductId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ firstProductId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ secondProductId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `shipping/zones/${ shippingZoneDEId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `shipping/zones/${ shippingZoneFRId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'allows customer to calculate Free Shipping if in Germany', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
// Set shipping country to Germany
|
||||||
|
await page.click( 'a.shipping-calculator-button' );
|
||||||
|
await page.selectOption( '#calc_shipping_country', shippingCountryDE );
|
||||||
|
await page.click( 'button[name="calc_shipping"]' );
|
||||||
|
|
||||||
|
// Verify shipping costs
|
||||||
|
await expect(
|
||||||
|
page.locator( '.shipping ul#shipping_method > li' )
|
||||||
|
).toContainText( 'Free shipping' );
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
firstProductPrice
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'allows customer to calculate Flat rate and Local pickup if in France', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
// Set shipping country to France
|
||||||
|
await page.click( 'a.shipping-calculator-button' );
|
||||||
|
await page.selectOption( '#calc_shipping_country', shippingCountryFR );
|
||||||
|
await page.click( 'button[name="calc_shipping"]' );
|
||||||
|
|
||||||
|
// Verify shipping costs
|
||||||
|
await expect( page.locator( '.shipping .amount' ) ).toContainText(
|
||||||
|
'$5.00'
|
||||||
|
);
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
`$${ firstProductWithFlatRate }`
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set shipping to local pickup instead of flat rate
|
||||||
|
await page.click( 'text=Local pickup' );
|
||||||
|
|
||||||
|
// Verify updated shipping costs
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
`$${ firstProductPrice }`
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should show correct total cart price after updating quantity', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await page.fill( 'input.qty', '4' );
|
||||||
|
await page.click( 'text=Update cart' );
|
||||||
|
|
||||||
|
// Set shipping country to France
|
||||||
|
await page.click( 'a.shipping-calculator-button' );
|
||||||
|
await page.selectOption( '#calc_shipping_country', shippingCountryFR );
|
||||||
|
await page.click( 'button[name="calc_shipping"]' );
|
||||||
|
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
`$${ fourProductsWithFlatRate }`
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should show correct total cart price with 2 products and flat rate', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ secondProductId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await page.click( 'a.shipping-calculator-button' );
|
||||||
|
await page.selectOption( '#calc_shipping_country', shippingCountryFR );
|
||||||
|
await page.click( 'button[name="calc_shipping"]' );
|
||||||
|
|
||||||
|
await expect( page.locator( '.shipping .amount' ) ).toContainText(
|
||||||
|
'$5.00'
|
||||||
|
);
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
`$${ twoProductsWithFlatRate }`
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should show correct total cart price with 2 products without flat rate', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ secondProductId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
|
// Set shipping country to Spain
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await page.click( 'a.shipping-calculator-button' );
|
||||||
|
await page.selectOption( '#calc_shipping_country', 'ES' );
|
||||||
|
await page.click( 'button[name="calc_shipping"]' );
|
||||||
|
|
||||||
|
// Verify shipping costs
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
`$${ twoProductsTotal }`
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,177 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
const firstProductName = 'Coupon test product';
|
||||||
|
const coupons = [
|
||||||
|
{
|
||||||
|
code: 'fixed-cart-off',
|
||||||
|
discount_type: 'fixed_cart',
|
||||||
|
amount: '5.00',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'percent-off',
|
||||||
|
discount_type: 'percent',
|
||||||
|
amount: '50',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'fixed-product-off',
|
||||||
|
discount_type: 'fixed_product',
|
||||||
|
amount: '7.00',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const discounts = [ '$5.00', '$10.00', '$7.00' ];
|
||||||
|
const totals = [ '$15.00', '$10.00', '$13.00' ];
|
||||||
|
|
||||||
|
test.describe( 'Cart applying coupons', () => {
|
||||||
|
let firstProductId;
|
||||||
|
const couponBatchId = new Array();
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add product
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: firstProductName,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: '20.00',
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
firstProductId = response.data.id;
|
||||||
|
} );
|
||||||
|
// add coupons
|
||||||
|
await api
|
||||||
|
.post( 'coupons/batch', {
|
||||||
|
create: coupons,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
for ( let i = 0; i < response.data.create.length; i++ ) {
|
||||||
|
couponBatchId.push( response.data.create[ i ].id );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { page, context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
context.clearCookies();
|
||||||
|
|
||||||
|
// all tests use the first product
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ firstProductId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ firstProductId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.post( 'coupons/batch', { delete: [ ...couponBatchId ] } );
|
||||||
|
} );
|
||||||
|
|
||||||
|
for ( let i = 0; i < coupons.length; i++ ) {
|
||||||
|
test( `allows cart to apply coupon of type ${ coupons[ i ].discount_type }`, async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await page.fill( '#coupon_code', coupons[ i ].code );
|
||||||
|
await page.click( 'text=Apply coupon' );
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-message' )
|
||||||
|
).toContainText( 'Coupon code applied successfully.' );
|
||||||
|
// Checks the coupon amount is credited properly
|
||||||
|
await expect(
|
||||||
|
page.locator( '.cart-discount .amount' )
|
||||||
|
).toContainText( discounts[ i ] );
|
||||||
|
// Checks that the cart total is updated
|
||||||
|
await expect(
|
||||||
|
page.locator( '.order-total .amount' )
|
||||||
|
).toContainText( totals[ i ] );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
test( 'prevents cart applying same coupon twice', async ( { page } ) => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await page.fill( '#coupon_code', coupons[ 0 ].code );
|
||||||
|
await page.click( 'text=Apply coupon' );
|
||||||
|
// successful first time
|
||||||
|
await expect( page.locator( '.woocommerce-message' ) ).toContainText(
|
||||||
|
'Coupon code applied successfully.'
|
||||||
|
);
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
// try to apply the same coupon
|
||||||
|
await page.fill( '#coupon_code', coupons[ 0 ].code );
|
||||||
|
await page.click( 'text=Apply coupon' );
|
||||||
|
// error received
|
||||||
|
await expect( page.locator( '.woocommerce-error' ) ).toContainText(
|
||||||
|
'Coupon code already applied!'
|
||||||
|
);
|
||||||
|
// check cart total
|
||||||
|
await expect( page.locator( '.cart-discount .amount' ) ).toContainText(
|
||||||
|
discounts[ 0 ]
|
||||||
|
);
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
totals[ 0 ]
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'allows cart to apply multiple coupons', async ( { page } ) => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await page.fill( '#coupon_code', coupons[ 0 ].code );
|
||||||
|
await page.click( 'text=Apply coupon' );
|
||||||
|
// successful
|
||||||
|
await expect( page.locator( '.woocommerce-message' ) ).toContainText(
|
||||||
|
'Coupon code applied successfully.'
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
await page.fill( '#coupon_code', coupons[ 2 ].code );
|
||||||
|
await page.click( 'text=Apply coupon' );
|
||||||
|
// successful
|
||||||
|
await expect( page.locator( '.woocommerce-message' ) ).toContainText(
|
||||||
|
'Coupon code applied successfully.'
|
||||||
|
);
|
||||||
|
// check cart total
|
||||||
|
await expect(
|
||||||
|
page.locator( '.cart-discount .amount >> nth=0' )
|
||||||
|
).toContainText( discounts[ 0 ] );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.cart-discount .amount >> nth=1' )
|
||||||
|
).toContainText( discounts[ 2 ] );
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
'$8.00'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'restores cart total when coupons are removed', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await page.fill( '#coupon_code', coupons[ 0 ].code );
|
||||||
|
await page.click( 'text=Apply coupon' );
|
||||||
|
|
||||||
|
// confirm numbers
|
||||||
|
await expect( page.locator( '.cart-discount .amount' ) ).toContainText(
|
||||||
|
discounts[ 0 ]
|
||||||
|
);
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
totals[ 0 ]
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.click( 'a.woocommerce-remove-coupon' );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
'$20.00'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,79 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
test.describe( 'Cart > Redirect to cart from shop', () => {
|
||||||
|
let productId;
|
||||||
|
const productName = 'A redirect product test';
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add products
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: productName,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: '17.99',
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
productId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.put(
|
||||||
|
'settings/products/woocommerce_cart_redirect_after_add',
|
||||||
|
{
|
||||||
|
value: 'yes',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
context.clearCookies();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ productId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.put(
|
||||||
|
'settings/products/woocommerce_cart_redirect_after_add',
|
||||||
|
{
|
||||||
|
value: 'no',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can redirect user to cart from shop page', async ( { page } ) => {
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
await page.click( `a:below(:text("${ productName }"))` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
|
await expect( page.url() ).toContain( '/cart/' );
|
||||||
|
await expect( page.locator( 'td.product-name' ) ).toContainText(
|
||||||
|
productName
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can redirect user to cart from detail page', async ( { page } ) => {
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
await page.click( `text=${ productName }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
|
await page.click( 'text=Add to cart' );
|
||||||
|
|
||||||
|
await expect( page.url() ).toContain( '/cart/' );
|
||||||
|
await expect( page.locator( 'td.product-name' ) ).toContainText(
|
||||||
|
productName
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,152 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
const productName = 'Cart product test';
|
||||||
|
const productPrice = '13.99';
|
||||||
|
const twoProductPrice = +productPrice * 2;
|
||||||
|
|
||||||
|
test.describe( 'Cart page', () => {
|
||||||
|
let productId;
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add products
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: productName,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: productPrice,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
productId = response.data.id;
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
context.clearCookies();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ productId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should display no item in the cart', async ( { page } ) => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await expect( page.locator( '.cart-empty' ) ).toContainText(
|
||||||
|
'Your cart is currently empty.'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should add the product to the cart from the shop page', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
await page.click( `a:below(:text("${ productName }"))` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await expect( page.locator( 'td.product-name' ) ).toContainText(
|
||||||
|
productName
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should increase item quantity when "Add to cart" of the same product is clicked', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
await page.click( `a:below(:text("${ productName }"))` );
|
||||||
|
// Once the view cart link is visible, item has been added
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
// Click add to cart a second time (load the shop in case redirection enabled)
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
await page.click( `a:below(:text("${ productName }"))` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await expect( page.locator( 'input.qty' ) ).toHaveValue( '2' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should update quantity when updated via quantity input', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
await page.click( `a:below(:text("${ productName }"))` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await page.fill( 'input.qty', '2' );
|
||||||
|
await page.click( 'text=Update cart' );
|
||||||
|
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
`$${ twoProductPrice }`
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should remove the item from the cart when remove is clicked', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
await page.click( `a:below(:text("${ productName }"))` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
|
||||||
|
// make sure that the product is in the cart
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
`$${ productPrice }`
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.click( 'a.remove' );
|
||||||
|
|
||||||
|
await expect( page.locator( 'p.woocommerce-info' ) ).toContainText(
|
||||||
|
'Your cart is currently empty.'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should update subtotal in cart totals when adding product to the cart', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
await page.click( `a:below(:text("${ productName }"))` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await expect( page.locator( '.cart-subtotal .amount' ) ).toContainText(
|
||||||
|
`$${ productPrice }`
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.fill( 'input.qty', '2' );
|
||||||
|
await page.click( 'text=Update cart' );
|
||||||
|
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
`$${ twoProductPrice }`
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should go to the checkout page when "Proceed to Checkout" is clicked', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
await page.click( `a:below(:text("${ productName }"))` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
|
||||||
|
await page.click( '.checkout-button' );
|
||||||
|
|
||||||
|
await expect( page.locator( '#order_review' ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,179 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
const firstProductName = 'Coupon checkout test product';
|
||||||
|
const coupons = [
|
||||||
|
{
|
||||||
|
code: 'fixed-cart-off-checkout',
|
||||||
|
discount_type: 'fixed_cart',
|
||||||
|
amount: '5.00',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'percent-off-checkout',
|
||||||
|
discount_type: 'percent',
|
||||||
|
amount: '50',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'fixed-product-off-checkout',
|
||||||
|
discount_type: 'fixed_product',
|
||||||
|
amount: '7.00',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const discounts = [ '$5.00', '$10.00', '$7.00' ];
|
||||||
|
const totals = [ '$15.00', '$10.00', '$13.00' ];
|
||||||
|
|
||||||
|
test.describe( 'Checkout coupons', () => {
|
||||||
|
let firstProductId;
|
||||||
|
const couponBatchId = new Array();
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add product
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: firstProductName,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: '20.00',
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
firstProductId = response.data.id;
|
||||||
|
} );
|
||||||
|
// add coupons
|
||||||
|
await api
|
||||||
|
.post( 'coupons/batch', {
|
||||||
|
create: coupons,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
for ( let i = 0; i < response.data.create.length; i++ ) {
|
||||||
|
couponBatchId.push( response.data.create[ i ].id );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { page, context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
context.clearCookies();
|
||||||
|
|
||||||
|
// all tests use the first product
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ firstProductId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ firstProductId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.post( 'coupons/batch', { delete: [ ...couponBatchId ] } );
|
||||||
|
} );
|
||||||
|
|
||||||
|
for ( let i = 0; i < coupons.length; i++ ) {
|
||||||
|
test( `allows checkout to apply coupon of type ${ coupons[ i ].discount_type }`, async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await page.click( 'text=Click here to enter your code' );
|
||||||
|
await page.fill( '#coupon_code', coupons[ i ].code );
|
||||||
|
await page.click( 'text=Apply coupon' );
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-message' )
|
||||||
|
).toContainText( 'Coupon code applied successfully.' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.cart-discount .amount' )
|
||||||
|
).toContainText( discounts[ i ] );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.order-total .amount' )
|
||||||
|
).toContainText( totals[ i ] );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
test( 'prevents checkout applying same coupon twice', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await page.click( 'text=Click here to enter your code' );
|
||||||
|
await page.fill( '#coupon_code', coupons[ 0 ].code );
|
||||||
|
await page.click( 'text=Apply coupon' );
|
||||||
|
// successful first time
|
||||||
|
await expect( page.locator( '.woocommerce-message' ) ).toContainText(
|
||||||
|
'Coupon code applied successfully.'
|
||||||
|
);
|
||||||
|
// try to apply the same coupon
|
||||||
|
await page.click( 'text=Click here to enter your code' );
|
||||||
|
await page.fill( '#coupon_code', coupons[ 0 ].code );
|
||||||
|
await page.click( 'text=Apply coupon' );
|
||||||
|
// error received
|
||||||
|
await expect( page.locator( '.woocommerce-error' ) ).toContainText(
|
||||||
|
'Coupon code already applied!'
|
||||||
|
);
|
||||||
|
// check cart total
|
||||||
|
await expect( page.locator( '.cart-discount .amount' ) ).toContainText(
|
||||||
|
discounts[ 0 ]
|
||||||
|
);
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
totals[ 0 ]
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'allows checkout to apply multiple coupons', async ( { page } ) => {
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await page.click( 'text=Click here to enter your code' );
|
||||||
|
await page.fill( '#coupon_code', coupons[ 0 ].code );
|
||||||
|
await page.click( 'text=Apply coupon' );
|
||||||
|
// successful
|
||||||
|
await expect( page.locator( '.woocommerce-message' ) ).toContainText(
|
||||||
|
'Coupon code applied successfully.'
|
||||||
|
);
|
||||||
|
await page.click( 'text=Click here to enter your code' );
|
||||||
|
await page.fill( '#coupon_code', coupons[ 2 ].code );
|
||||||
|
await page.click( 'text=Apply coupon' );
|
||||||
|
// successful
|
||||||
|
await expect( page.locator( '.woocommerce-message' ) ).toContainText(
|
||||||
|
'Coupon code applied successfully.'
|
||||||
|
);
|
||||||
|
// check cart total
|
||||||
|
await expect(
|
||||||
|
page.locator( '.cart-discount .amount >> nth=0' )
|
||||||
|
).toContainText( discounts[ 0 ] );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.cart-discount .amount >> nth=1' )
|
||||||
|
).toContainText( discounts[ 2 ] );
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
'$8.00'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'restores checkout total when coupons are removed', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await page.click( 'text=Click here to enter your code' );
|
||||||
|
await page.fill( '#coupon_code', coupons[ 0 ].code );
|
||||||
|
await page.click( 'text=Apply coupon' );
|
||||||
|
|
||||||
|
// confirm numbers
|
||||||
|
await expect( page.locator( '.cart-discount .amount' ) ).toContainText(
|
||||||
|
discounts[ 0 ]
|
||||||
|
);
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
totals[ 0 ]
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.click( 'a.woocommerce-remove-coupon' );
|
||||||
|
|
||||||
|
await expect( page.locator( '.order-total .amount' ) ).toContainText(
|
||||||
|
'$20.00'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,146 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
const billingEmail = 'marge-test-account@example.com';
|
||||||
|
|
||||||
|
test.describe( 'Shopper Checkout Create Account', () => {
|
||||||
|
let productId, orderId, shippingZoneId;
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add product
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: 'Checkout Create Account',
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: '19.99',
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
productId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.put(
|
||||||
|
'settings/account/woocommerce_enable_signup_and_login_from_checkout',
|
||||||
|
{
|
||||||
|
value: 'yes',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
await api
|
||||||
|
.post( 'shipping/zones', {
|
||||||
|
name: 'Free Shipping CA',
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
shippingZoneId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.put( `shipping/zones/${ shippingZoneId }/locations`, [
|
||||||
|
{
|
||||||
|
code: 'US:CA',
|
||||||
|
type: 'state',
|
||||||
|
},
|
||||||
|
] );
|
||||||
|
await api.post( `shipping/zones/${ shippingZoneId }/methods`, {
|
||||||
|
method_id: 'free_shipping',
|
||||||
|
} );
|
||||||
|
await api.put( 'payment_gateways/cod', {
|
||||||
|
enabled: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ productId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
if ( orderId ) {
|
||||||
|
await api.delete( `orders/${ orderId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
await api.put(
|
||||||
|
'settings/account/woocommerce_enable_signup_and_login_from_checkout',
|
||||||
|
{
|
||||||
|
value: 'no',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
await api.delete( `shipping/zones/${ shippingZoneId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.put( 'payment_gateways/cod', {
|
||||||
|
enabled: false,
|
||||||
|
} );
|
||||||
|
// clear out the customer we create during the test
|
||||||
|
await api.get( 'customers' ).then( ( response ) => {
|
||||||
|
for ( let i = 0; i < response.data.length; i++ ) {
|
||||||
|
if ( response.data[ i ].billing.email === billingEmail ) {
|
||||||
|
api.delete( `customers/${ response.data[ i ].id }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { page, context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
context.clearCookies();
|
||||||
|
|
||||||
|
// all tests use the first product
|
||||||
|
await page.goto( `shop/?add-to-cart=${ productId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can create an account during checkout', async ( { page } ) => {
|
||||||
|
await page.goto( 'checkout/' );
|
||||||
|
await page.fill( '#billing_first_name', 'Marge' );
|
||||||
|
await page.fill( '#billing_last_name', 'Simpson' );
|
||||||
|
await page.fill( '#billing_address_1', '742 Evergreen Terrace' );
|
||||||
|
await page.fill( '#billing_address_2', 'c/o Maggie Simpson' );
|
||||||
|
await page.fill( '#billing_city', 'Springfield' );
|
||||||
|
await page.fill( '#billing_postcode', '97403' );
|
||||||
|
await page.fill( '#billing_phone', '123456789' );
|
||||||
|
await page.fill( '#billing_email', billingEmail );
|
||||||
|
|
||||||
|
await page.check( '#createaccount' );
|
||||||
|
|
||||||
|
await page.click( '#place_order' );
|
||||||
|
|
||||||
|
await expect( page.locator( 'h1.entry-title' ) ).toContainText(
|
||||||
|
'Order received'
|
||||||
|
);
|
||||||
|
|
||||||
|
// get order ID from the page
|
||||||
|
const orderReceivedHtmlElement = await page.$(
|
||||||
|
'.woocommerce-order-overview__order.order'
|
||||||
|
);
|
||||||
|
const orderReceivedText = await page.evaluate(
|
||||||
|
( element ) => element.textContent,
|
||||||
|
orderReceivedHtmlElement
|
||||||
|
);
|
||||||
|
orderId = orderReceivedText.split( /(\s+)/ )[ 6 ].toString();
|
||||||
|
|
||||||
|
await page.goto( '/my-account/' );
|
||||||
|
// confirms that an account was created
|
||||||
|
await expect( page.locator( 'h1.entry-title' ) ).toContainText(
|
||||||
|
'My account'
|
||||||
|
);
|
||||||
|
await page.click( 'text=Logout' );
|
||||||
|
// sign in as admin to confirm account creation
|
||||||
|
await page.fill( '#username', 'admin' );
|
||||||
|
await page.fill( '#password', 'password' );
|
||||||
|
await page.click( 'text=Log in' );
|
||||||
|
|
||||||
|
await page.goto( 'wp-admin/users.php' );
|
||||||
|
await expect( page.locator( 'tbody#the-list' ) ).toContainText(
|
||||||
|
billingEmail
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,186 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
const first_name = 'Jane';
|
||||||
|
const last_name = 'Smith';
|
||||||
|
const address_1 = '123 Anywhere St.';
|
||||||
|
const address_2 = 'Apartment 42';
|
||||||
|
const city = 'New York';
|
||||||
|
const state = 'NY';
|
||||||
|
const postcode = '10010';
|
||||||
|
const country = 'US';
|
||||||
|
const phone = '(555) 777-7777';
|
||||||
|
|
||||||
|
test.describe( 'Shopper Checkout Login Account', () => {
|
||||||
|
let productId, orderId, shippingZoneId;
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add product
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: 'Checkout Login Account',
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: '19.99',
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
productId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.put(
|
||||||
|
'settings/account/woocommerce_enable_checkout_login_reminder',
|
||||||
|
{
|
||||||
|
value: 'yes',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// add a shipping zone and method
|
||||||
|
await api
|
||||||
|
.post( 'shipping/zones', {
|
||||||
|
name: 'Free Shipping New York',
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
shippingZoneId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.put( `shipping/zones/${ shippingZoneId }/locations`, [
|
||||||
|
{
|
||||||
|
code: 'US:NY',
|
||||||
|
type: 'state',
|
||||||
|
},
|
||||||
|
] );
|
||||||
|
await api.post( `shipping/zones/${ shippingZoneId }/methods`, {
|
||||||
|
method_id: 'free_shipping',
|
||||||
|
} );
|
||||||
|
// update customer billing details.
|
||||||
|
await api.put( 'customers/2', {
|
||||||
|
billing: {
|
||||||
|
first_name,
|
||||||
|
last_name,
|
||||||
|
address_1,
|
||||||
|
address_2,
|
||||||
|
city,
|
||||||
|
state,
|
||||||
|
postcode,
|
||||||
|
country,
|
||||||
|
phone,
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
// enable a payment method
|
||||||
|
await api.put( 'payment_gateways/cod', {
|
||||||
|
enabled: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ productId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
if ( orderId ) {
|
||||||
|
await api.delete( `orders/${ orderId }`, { force: true } );
|
||||||
|
}
|
||||||
|
await api.put(
|
||||||
|
'settings/account/woocommerce_enable_checkout_login_reminder',
|
||||||
|
{
|
||||||
|
value: 'no',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// reset the customer account to how it was at the start
|
||||||
|
await api.put( 'customers/2', {
|
||||||
|
billing: {
|
||||||
|
address_1: '',
|
||||||
|
address_2: '',
|
||||||
|
city: '',
|
||||||
|
state: '',
|
||||||
|
postcode: '',
|
||||||
|
country: '',
|
||||||
|
phone: '',
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
// disable payment method
|
||||||
|
await api.put( 'payment_gateways/cod', {
|
||||||
|
enabled: false,
|
||||||
|
} );
|
||||||
|
// delete shipping
|
||||||
|
await api.delete( `shipping/zones/${ shippingZoneId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { page, context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
context.clearCookies();
|
||||||
|
|
||||||
|
// all tests use the first product
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can login to an existing account during checkout', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await page.click( 'text=Click here to login' );
|
||||||
|
|
||||||
|
// fill in the customer account info
|
||||||
|
await page.fill( '#username', 'customer' );
|
||||||
|
await page.fill( '#password', 'password' );
|
||||||
|
await page.click( 'button[name="login"]' );
|
||||||
|
|
||||||
|
// billing form should pre-populate
|
||||||
|
await expect( page.locator( '#billing_first_name' ) ).toHaveValue(
|
||||||
|
first_name
|
||||||
|
);
|
||||||
|
await expect( page.locator( '#billing_last_name' ) ).toHaveValue(
|
||||||
|
last_name
|
||||||
|
);
|
||||||
|
await expect( page.locator( '#billing_address_1' ) ).toHaveValue(
|
||||||
|
address_1
|
||||||
|
);
|
||||||
|
await expect( page.locator( '#billing_address_2' ) ).toHaveValue(
|
||||||
|
address_2
|
||||||
|
);
|
||||||
|
await expect( page.locator( '#billing_city' ) ).toHaveValue( city );
|
||||||
|
await expect( page.locator( '#billing_state' ) ).toHaveValue( state );
|
||||||
|
await expect( page.locator( '#billing_postcode' ) ).toHaveValue(
|
||||||
|
postcode
|
||||||
|
);
|
||||||
|
await expect( page.locator( '#billing_phone' ) ).toHaveValue( phone );
|
||||||
|
|
||||||
|
// place an order
|
||||||
|
await page.click( 'text=Place order' );
|
||||||
|
await expect( page.locator( 'h1.entry-title' ) ).toContainText(
|
||||||
|
'Order received'
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
// get order ID from the page
|
||||||
|
const orderReceivedHtmlElement = await page.$(
|
||||||
|
'.woocommerce-order-overview__order.order'
|
||||||
|
);
|
||||||
|
const orderReceivedText = await page.evaluate(
|
||||||
|
( element ) => element.textContent,
|
||||||
|
orderReceivedHtmlElement
|
||||||
|
);
|
||||||
|
orderId = orderReceivedText.split( /(\s+)/ )[ 6 ].toString();
|
||||||
|
|
||||||
|
await expect( page.locator( 'ul > li.email' ) ).toContainText(
|
||||||
|
'customer@woocommercecoree2etestsuite.com'
|
||||||
|
);
|
||||||
|
|
||||||
|
// check my account page
|
||||||
|
await page.goto( '/my-account/' );
|
||||||
|
await expect( page.url() ).toContain( 'my-account/' );
|
||||||
|
await expect( page.locator( 'h1.entry-title' ) ).toContainText(
|
||||||
|
'My account'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,332 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
const guestEmail = 'checkout-guest@example.com';
|
||||||
|
const customerEmail = 'checkout-customer@example.com';
|
||||||
|
|
||||||
|
test.describe( 'Checkout page', () => {
|
||||||
|
const singleProductPrice = '9.99';
|
||||||
|
const simpleProductName = 'Checkout Page Product';
|
||||||
|
const twoProductPrice = ( singleProductPrice * 2 ).toString();
|
||||||
|
const threeProductPrice = ( singleProductPrice * 3 ).toString();
|
||||||
|
|
||||||
|
let guestOrderId, customerOrderId, productId, shippingZoneId;
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add product
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: simpleProductName,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: singleProductPrice,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
productId = response.data.id;
|
||||||
|
} );
|
||||||
|
// add a shipping zone and method
|
||||||
|
await api
|
||||||
|
.post( 'shipping/zones', {
|
||||||
|
name: 'Free Shipping Oregon',
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
shippingZoneId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.put( `shipping/zones/${ shippingZoneId }/locations`, [
|
||||||
|
{
|
||||||
|
code: 'US:OR',
|
||||||
|
type: 'state',
|
||||||
|
},
|
||||||
|
] );
|
||||||
|
await api.post( `shipping/zones/${ shippingZoneId }/methods`, {
|
||||||
|
method_id: 'free_shipping',
|
||||||
|
} );
|
||||||
|
// enable bank transfers and COD for payment
|
||||||
|
await api.put( 'payment_gateways/bacs', {
|
||||||
|
enabled: true,
|
||||||
|
} );
|
||||||
|
await api.put( 'payment_gateways/cod', {
|
||||||
|
enabled: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ productId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `shipping/zones/${ shippingZoneId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.put( 'payment_gateways/bacs', {
|
||||||
|
enabled: false,
|
||||||
|
} );
|
||||||
|
await api.put( 'payment_gateways/cod', {
|
||||||
|
enabled: false,
|
||||||
|
} );
|
||||||
|
// delete the orders we created
|
||||||
|
if ( guestOrderId ) {
|
||||||
|
await api.delete( `orders/${ guestOrderId }`, { force: true } );
|
||||||
|
}
|
||||||
|
if ( customerOrderId ) {
|
||||||
|
await api.delete( `orders/${ customerOrderId }`, { force: true } );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
context.clearCookies();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should display cart items in order review', async ( { page } ) => {
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
|
||||||
|
await expect( page.locator( 'td.product-name' ) ).toContainText(
|
||||||
|
simpleProductName
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
|
||||||
|
'1'
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'td.product-total' ) ).toContainText(
|
||||||
|
singleProductPrice
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'allows customer to choose available payment methods', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
// this time we're going to add two products to the cart
|
||||||
|
for ( let i = 1; i < 3; i++ ) {
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
}
|
||||||
|
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
|
||||||
|
'2'
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'td.product-total' ) ).toContainText(
|
||||||
|
twoProductPrice
|
||||||
|
);
|
||||||
|
|
||||||
|
// check the payment methods
|
||||||
|
await expect( page.locator( '#payment_method_bacs' ) ).toBeEnabled();
|
||||||
|
await expect( page.locator( '#payment_method_cod' ) ).toBeEnabled();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'allows customer to fill billing details', async ( { page } ) => {
|
||||||
|
// this time we're going to add three products to the cart
|
||||||
|
for ( let i = 1; i < 4; i++ ) {
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
}
|
||||||
|
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
|
||||||
|
'3'
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'td.product-total' ) ).toContainText(
|
||||||
|
threeProductPrice
|
||||||
|
);
|
||||||
|
|
||||||
|
// asserting that you can fill in the billing details
|
||||||
|
await expect( page.locator( '#billing_first_name' ) ).toBeEditable();
|
||||||
|
await expect( page.locator( '#billing_last_name' ) ).toBeEditable();
|
||||||
|
await expect( page.locator( '#billing_company' ) ).toBeEditable();
|
||||||
|
await expect( page.locator( '#billing_country' ) ).toBeEnabled();
|
||||||
|
await expect( page.locator( '#billing_address_1' ) ).toBeEditable();
|
||||||
|
await expect( page.locator( '#billing_address_2' ) ).toBeEditable();
|
||||||
|
await expect( page.locator( '#billing_city' ) ).toBeEditable();
|
||||||
|
await expect( page.locator( '#billing_state' ) ).toBeEnabled();
|
||||||
|
await expect( page.locator( '#billing_postcode' ) ).toBeEditable();
|
||||||
|
await expect( page.locator( '#billing_phone' ) ).toBeEditable();
|
||||||
|
await expect( page.locator( '#billing_email' ) ).toBeEditable();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'allows customer to fill shipping details', async ( { page } ) => {
|
||||||
|
for ( let i = 1; i < 3; i++ ) {
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
}
|
||||||
|
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
|
||||||
|
'2'
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'td.product-total' ) ).toContainText(
|
||||||
|
twoProductPrice
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.click( '#ship-to-different-address' );
|
||||||
|
|
||||||
|
// asserting that you can fill in the shipping details
|
||||||
|
await expect( page.locator( '#shipping_first_name' ) ).toBeEditable();
|
||||||
|
await expect( page.locator( '#shipping_last_name' ) ).toBeEditable();
|
||||||
|
await expect( page.locator( '#shipping_company' ) ).toBeEditable();
|
||||||
|
await expect( page.locator( '#shipping_country' ) ).toBeEnabled();
|
||||||
|
await expect( page.locator( '#shipping_address_1' ) ).toBeEditable();
|
||||||
|
await expect( page.locator( '#shipping_address_2' ) ).toBeEditable();
|
||||||
|
await expect( page.locator( '#shipping_city' ) ).toBeEditable();
|
||||||
|
await expect( page.locator( '#shipping_state' ) ).toBeEnabled();
|
||||||
|
await expect( page.locator( '#shipping_postcode' ) ).toBeEditable();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'allows guest customer to place an order', async ( { page } ) => {
|
||||||
|
for ( let i = 1; i < 3; i++ ) {
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
}
|
||||||
|
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
|
||||||
|
'2'
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'td.product-total' ) ).toContainText(
|
||||||
|
twoProductPrice
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.fill( '#billing_first_name', 'Lisa' );
|
||||||
|
await page.fill( '#billing_last_name', 'Simpson' );
|
||||||
|
await page.fill( '#billing_address_1', '123 Evergreen Terrace' );
|
||||||
|
await page.fill( '#billing_city', 'Springfield' );
|
||||||
|
await page.selectOption( '#billing_state', 'OR' );
|
||||||
|
await page.fill( '#billing_postcode', '97403' );
|
||||||
|
await page.fill( '#billing_phone', '555 555-5555' );
|
||||||
|
await page.fill( '#billing_email', guestEmail );
|
||||||
|
|
||||||
|
await page.click( 'text=Cash on delivery' );
|
||||||
|
await expect( page.locator( 'div.payment_method_cod' ) ).toBeVisible();
|
||||||
|
|
||||||
|
await page.click( 'text=Place order' );
|
||||||
|
|
||||||
|
await expect( page.locator( 'h1.entry-title' ) ).toContainText(
|
||||||
|
'Order received'
|
||||||
|
);
|
||||||
|
|
||||||
|
// get order ID from the page
|
||||||
|
const orderReceivedHtmlElement = await page.$(
|
||||||
|
'.woocommerce-order-overview__order.order'
|
||||||
|
);
|
||||||
|
const orderReceivedText = await page.evaluate(
|
||||||
|
( element ) => element.textContent,
|
||||||
|
orderReceivedHtmlElement
|
||||||
|
);
|
||||||
|
guestOrderId = await orderReceivedText.split( /(\s+)/ )[ 6 ].toString();
|
||||||
|
|
||||||
|
await page.goto( 'wp-login.php' );
|
||||||
|
await page.fill( 'input[name="log"]', 'admin' );
|
||||||
|
await page.fill( 'input[name="pwd"]', 'password' );
|
||||||
|
await page.click( 'text=Log In' );
|
||||||
|
|
||||||
|
// load the order placed as a guest
|
||||||
|
await page.goto(
|
||||||
|
`wp-admin/post.php?post=${ guestOrderId }&action=edit`
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator( 'h2.woocommerce-order-data__heading' )
|
||||||
|
).toContainText( `Order #${ guestOrderId } details` );
|
||||||
|
await expect( page.locator( '.wc-order-item-name' ) ).toContainText(
|
||||||
|
simpleProductName
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'td.quantity >> nth=0' ) ).toContainText(
|
||||||
|
'2'
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'td.item_cost >> nth=0' ) ).toContainText(
|
||||||
|
singleProductPrice
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'td.line_cost >> nth=0' ) ).toContainText(
|
||||||
|
twoProductPrice
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'allows existing customer to place order', async ( { page } ) => {
|
||||||
|
await page.goto( 'wp-admin/' );
|
||||||
|
await page.fill( 'input[name="log"]', 'customer' );
|
||||||
|
await page.fill( 'input[name="pwd"]', 'password' );
|
||||||
|
await page.click( 'text=Log In' );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
for ( let i = 1; i < 3; i++ ) {
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
}
|
||||||
|
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
|
||||||
|
'2'
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'td.product-total' ) ).toContainText(
|
||||||
|
twoProductPrice
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.fill( '#billing_first_name', 'Homer' );
|
||||||
|
await page.fill( '#billing_last_name', 'Simpson' );
|
||||||
|
await page.fill( '#billing_address_1', '123 Evergreen Terrace' );
|
||||||
|
await page.fill( '#billing_city', 'Springfield' );
|
||||||
|
await page.selectOption( '#billing_state', 'OR' );
|
||||||
|
await page.fill( '#billing_postcode', '97403' );
|
||||||
|
await page.fill( '#billing_phone', '555 555-5555' );
|
||||||
|
await page.fill( '#billing_email', customerEmail );
|
||||||
|
|
||||||
|
await page.click( 'text=Cash on delivery' );
|
||||||
|
await expect( page.locator( 'div.payment_method_cod' ) ).toBeVisible();
|
||||||
|
|
||||||
|
await page.click( 'text=Place order' );
|
||||||
|
|
||||||
|
await expect( page.locator( 'h1.entry-title' ) ).toContainText(
|
||||||
|
'Order received'
|
||||||
|
);
|
||||||
|
|
||||||
|
// get order ID from the page
|
||||||
|
const orderReceivedHtmlElement = await page.$(
|
||||||
|
'.woocommerce-order-overview__order.order'
|
||||||
|
);
|
||||||
|
const orderReceivedText = await page.evaluate(
|
||||||
|
( element ) => element.textContent,
|
||||||
|
orderReceivedHtmlElement
|
||||||
|
);
|
||||||
|
customerOrderId = await orderReceivedText
|
||||||
|
.split( /(\s+)/ )[ 6 ]
|
||||||
|
.toString();
|
||||||
|
|
||||||
|
await page.goto( 'wp-login.php?loggedout=true' );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
|
await page.fill( 'input[name="log"]', 'admin' );
|
||||||
|
await page.fill( 'input[name="pwd"]', 'password' );
|
||||||
|
await page.click( 'text=Log In' );
|
||||||
|
|
||||||
|
// load the order placed as a customer
|
||||||
|
await page.goto(
|
||||||
|
`wp-admin/post.php?post=${ customerOrderId }&action=edit`
|
||||||
|
);
|
||||||
|
await expect(
|
||||||
|
page.locator( 'h2.woocommerce-order-data__heading' )
|
||||||
|
).toContainText( `Order #${ customerOrderId } details` );
|
||||||
|
await expect( page.locator( '.wc-order-item-name' ) ).toContainText(
|
||||||
|
simpleProductName
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'td.quantity >> nth=0' ) ).toContainText(
|
||||||
|
'2'
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'td.item_cost >> nth=0' ) ).toContainText(
|
||||||
|
singleProductPrice
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'td.line_cost >> nth=0' ) ).toContainText(
|
||||||
|
twoProductPrice
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,67 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
const customerEmailAddress = 'john.doe.test@example.com';
|
||||||
|
|
||||||
|
test.describe( 'Shopper My Account Create Account', () => {
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put(
|
||||||
|
'settings/account/woocommerce_enable_myaccount_registration',
|
||||||
|
{
|
||||||
|
value: 'yes',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// get a list of all customers
|
||||||
|
await api.get( 'customers' ).then( ( response ) => {
|
||||||
|
for ( let i = 0; i < response.data.length; i++ ) {
|
||||||
|
if ( response.data[ i ].email === customerEmailAddress ) {
|
||||||
|
api.delete( `customers/${ response.data[ i ].id }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
await api.put(
|
||||||
|
'settings/account/woocommerce_enable_myaccount_registration',
|
||||||
|
{
|
||||||
|
value: 'no',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'can create a new account via my account', async ( { page } ) => {
|
||||||
|
await page.goto( 'my-account/' );
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-form-register' )
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await page.fill( 'input#reg_email', customerEmailAddress );
|
||||||
|
await page.click( 'button[name="register"]' );
|
||||||
|
|
||||||
|
await expect( page.locator( 'h1.entry-title' ) ).toContainText(
|
||||||
|
'My account'
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'text=Logout' ) ).toBeVisible();
|
||||||
|
|
||||||
|
await page.goto( 'my-account/edit-account/' );
|
||||||
|
await expect( page.locator( '#account_email' ) ).toHaveValue(
|
||||||
|
customerEmailAddress
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,89 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
test.describe( 'Customer can pay for their order through My Account', () => {
|
||||||
|
let productId, orderId;
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add product
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: 'Pay Order My Account',
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: '15.77',
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
productId = response.data.id;
|
||||||
|
} );
|
||||||
|
// create an order
|
||||||
|
await api
|
||||||
|
.post( 'orders', {
|
||||||
|
set_paid: false,
|
||||||
|
billing: {
|
||||||
|
first_name: 'Jane',
|
||||||
|
last_name: 'Smith',
|
||||||
|
email: 'customer@woocommercecoree2etestsuite.com',
|
||||||
|
},
|
||||||
|
line_items: [
|
||||||
|
{
|
||||||
|
product_id: productId,
|
||||||
|
quantity: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
orderId = response.data.id;
|
||||||
|
} );
|
||||||
|
// once the order is created, assign it to our existing customer user
|
||||||
|
await api.put( `orders/${ orderId }`, {
|
||||||
|
customer_id: 2, // should be safe to use this ID. Saves an API call to retrieve.
|
||||||
|
} );
|
||||||
|
// enable COD payment
|
||||||
|
await api.put( 'payment_gateways/cod', {
|
||||||
|
enabled: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ productId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `orders/${ orderId }`, { force: true } );
|
||||||
|
await api.put( 'payment_gateways/cod', {
|
||||||
|
enabled: false,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'allows customer to pay for their order in My Account', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( 'my-account/orders/' );
|
||||||
|
// sign in as the "customer" user
|
||||||
|
await page.fill( '#username', 'customer' );
|
||||||
|
await page.fill( '#password', 'password' );
|
||||||
|
await page.click( 'text=Log in' );
|
||||||
|
|
||||||
|
await page.click( 'a.pay' );
|
||||||
|
|
||||||
|
await expect( page.locator( 'h1.entry-title' ) ).toContainText(
|
||||||
|
'Pay for order'
|
||||||
|
);
|
||||||
|
await page.click( '#place_order' );
|
||||||
|
|
||||||
|
await expect( page.locator( 'h1.entry-title' ) ).toContainText(
|
||||||
|
'Order received'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,54 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
|
||||||
|
const pages = [
|
||||||
|
[ 'Orders', 'my-account/orders' ],
|
||||||
|
[ 'Downloads', 'my-account/downloads' ],
|
||||||
|
[ 'Addresses', 'my-account/edit-address' ],
|
||||||
|
[ 'Account details', 'my-account/edit-account' ],
|
||||||
|
];
|
||||||
|
|
||||||
|
test.describe( 'My account page', () => {
|
||||||
|
test.use( { storageState: 'e2e/storage/customerState.json' } );
|
||||||
|
|
||||||
|
test( 'allows customer to login', async ( { page } ) => {
|
||||||
|
await page.goto( 'my-account/' );
|
||||||
|
|
||||||
|
await expect( page.locator( 'h1.entry-title' ) ).toContainText(
|
||||||
|
'My account'
|
||||||
|
);
|
||||||
|
await expect(
|
||||||
|
page.locator( 'div.woocommerce-MyAccount-content > p >> nth=0' )
|
||||||
|
).toContainText( 'Jane Smith' );
|
||||||
|
|
||||||
|
// assert that navigation is visible
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-MyAccount-navigation-link >> nth=0' )
|
||||||
|
).toContainText( 'Dashboard' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-MyAccount-navigation-link >> nth=1' )
|
||||||
|
).toContainText( 'Orders' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-MyAccount-navigation-link >> nth=2' )
|
||||||
|
).toContainText( 'Downloads' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-MyAccount-navigation-link >> nth=3' )
|
||||||
|
).toContainText( 'Addresses' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-MyAccount-navigation-link >> nth=4' )
|
||||||
|
).toContainText( 'Account details' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-MyAccount-navigation-link >> nth=5' )
|
||||||
|
).toContainText( 'Logout' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
for ( let i = 0; i < pages.length; i++ ) {
|
||||||
|
test( `allows customer to see ${ pages[ i ][ 0 ] } page`, async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( pages[ i ][ 1 ] );
|
||||||
|
await expect( page.locator( 'h1.entry-title' ) ).toContainText(
|
||||||
|
pages[ i ][ 0 ]
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
} );
|
|
@ -0,0 +1,109 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
let productId, orderId;
|
||||||
|
const productName = 'Order email product';
|
||||||
|
const customerEmail = 'order-email-test@example.com';
|
||||||
|
const storeName = 'WooCommerce Core E2E Test Suite';
|
||||||
|
|
||||||
|
test.describe( 'Shopper Order Email Receiving', () => {
|
||||||
|
test.use( { storageState: 'e2e/storage/adminState.json' } );
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add product
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: productName,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: '42.77',
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
productId = response.data.id;
|
||||||
|
} );
|
||||||
|
// enable COD payment
|
||||||
|
await api.put( 'payment_gateways/cod', {
|
||||||
|
enabled: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { page } ) => {
|
||||||
|
await page.goto(
|
||||||
|
`wp-admin/tools.php?page=wpml_plugin_log&s=${ encodeURIComponent(
|
||||||
|
customerEmail
|
||||||
|
) }`
|
||||||
|
);
|
||||||
|
// clear out the email logs before each test
|
||||||
|
while ( ( await page.$( '#bulk-action-selector-top' ) ) !== null ) {
|
||||||
|
await page.click( '#cb-select-all-1' );
|
||||||
|
await page.selectOption( '#bulk-action-selector-top', 'delete' );
|
||||||
|
await page.click( '#doaction' );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ productId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
if ( orderId ) {
|
||||||
|
await api.delete( `orders/${ orderId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
await api.put( 'payment_gateways/cod', {
|
||||||
|
enabled: false,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should receive order email after purchasing an item', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
|
||||||
|
await page.fill( '#billing_first_name', 'Maggie' );
|
||||||
|
await page.fill( '#billing_last_name', 'Simpson' );
|
||||||
|
await page.fill( '#billing_address_1', '123 Evergreen Terrace' );
|
||||||
|
await page.fill( '#billing_city', 'Springfield' );
|
||||||
|
await page.selectOption( '#billing_state', 'OR' );
|
||||||
|
await page.fill( '#billing_postcode', '97403' );
|
||||||
|
await page.fill( '#billing_phone', '555 555-5555' );
|
||||||
|
await page.fill( '#billing_email', customerEmail );
|
||||||
|
|
||||||
|
await page.click( 'text=Place order' );
|
||||||
|
|
||||||
|
await page.waitForSelector(
|
||||||
|
'li.woocommerce-order-overview__order > strong'
|
||||||
|
);
|
||||||
|
orderId = await page.textContent(
|
||||||
|
'li.woocommerce-order-overview__order > strong'
|
||||||
|
);
|
||||||
|
|
||||||
|
// search to narrow it down to just the messages we want
|
||||||
|
await page.goto(
|
||||||
|
`wp-admin/tools.php?page=wpml_plugin_log&s=${ encodeURIComponent(
|
||||||
|
customerEmail
|
||||||
|
) }`
|
||||||
|
);
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
await expect(
|
||||||
|
page.locator( 'td.column-receiver >> nth=0' )
|
||||||
|
).toContainText( customerEmail );
|
||||||
|
await expect(
|
||||||
|
page.locator( 'td.column-subject >> nth=1' )
|
||||||
|
).toContainText( `[${ storeName }]: New order #${ orderId }` );
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,161 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
const singleProductPrice1 = '979.99';
|
||||||
|
const singleProductPrice2 = '989.99';
|
||||||
|
const singleProductPrice3 = '999.99';
|
||||||
|
|
||||||
|
const simpleProductName = 'AAA Search and Browse Product';
|
||||||
|
|
||||||
|
const categoryA = 'Dogs';
|
||||||
|
const categoryB = 'Cats';
|
||||||
|
const categoryC = 'Fish';
|
||||||
|
|
||||||
|
let categoryAId, categoryBId, categoryCId, product1Id, product2Id, product3Id;
|
||||||
|
|
||||||
|
test.describe(
|
||||||
|
'Search, browse by categories and sort items in the shop',
|
||||||
|
() => {
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add product categories
|
||||||
|
await api
|
||||||
|
.post( 'products/categories', {
|
||||||
|
name: categoryA,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
categoryAId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api
|
||||||
|
.post( 'products/categories', {
|
||||||
|
name: categoryB,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
categoryBId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api
|
||||||
|
.post( 'products/categories', {
|
||||||
|
name: categoryC,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
categoryCId = response.data.id;
|
||||||
|
} );
|
||||||
|
|
||||||
|
// add products
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: simpleProductName + ' 1',
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: singleProductPrice1,
|
||||||
|
categories: [ { id: categoryAId } ],
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
product1Id = response.data.id;
|
||||||
|
} );
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: simpleProductName + ' 2',
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: singleProductPrice2,
|
||||||
|
categories: [ { id: categoryBId } ],
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
product2Id = response.data.id;
|
||||||
|
} );
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: simpleProductName + ' 3',
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: singleProductPrice3,
|
||||||
|
categories: [ { id: categoryCId } ],
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
product3Id = response.data.id;
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.post( 'products/batch', {
|
||||||
|
delete: [ product1Id, product2Id, product3Id ],
|
||||||
|
} );
|
||||||
|
await api.post( 'products/categories/batch', {
|
||||||
|
delete: [ categoryAId, categoryBId, categoryCId ],
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should let user search the store', async ( { page } ) => {
|
||||||
|
await page.goto( 'shop/' );
|
||||||
|
|
||||||
|
await page.fill(
|
||||||
|
'#wp-block-search__input-1',
|
||||||
|
simpleProductName + ' 1'
|
||||||
|
);
|
||||||
|
await page.click( 'button.wp-block-search__button' );
|
||||||
|
|
||||||
|
await expect( page.locator( 'h1.page-title' ) ).toContainText(
|
||||||
|
`${ simpleProductName } 1`
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'h2.entry-title' ) ).toContainText(
|
||||||
|
simpleProductName + ' 1'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should let user browse products by categories', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
// browse the Audio category
|
||||||
|
await page.goto( 'shop/' );
|
||||||
|
await page.click( `text=${ simpleProductName } 2` );
|
||||||
|
await page.click( 'span.posted_in > a', { hasText: categoryB } );
|
||||||
|
|
||||||
|
// verify the Audio category page
|
||||||
|
await expect( page.locator( 'h1.page-title' ) ).toContainText(
|
||||||
|
categoryB
|
||||||
|
);
|
||||||
|
await expect(
|
||||||
|
page.locator( 'h2.woocommerce-loop-product__title' )
|
||||||
|
).toContainText( simpleProductName + ' 2' );
|
||||||
|
await page.click( `text=${ simpleProductName } 2` );
|
||||||
|
await expect( page.locator( 'h1.entry-title' ) ).toContainText(
|
||||||
|
simpleProductName + ' 2'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should let user sort the products in the shop', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( 'shop/' );
|
||||||
|
|
||||||
|
// sort by price high to low
|
||||||
|
await page.selectOption( '.orderby', 'price-desc' );
|
||||||
|
// last product is most expensive
|
||||||
|
await expect(
|
||||||
|
page.locator( 'ul.products > li:nth-child(1)' )
|
||||||
|
).toContainText( `${ simpleProductName } 3` );
|
||||||
|
await expect(
|
||||||
|
page.locator( 'ul.products > li:nth-child(3)' )
|
||||||
|
).toContainText( `${ simpleProductName } 1` );
|
||||||
|
|
||||||
|
// sort by price low to high
|
||||||
|
await page.selectOption( '.orderby', 'price' );
|
||||||
|
// last product is most expensive
|
||||||
|
await expect(
|
||||||
|
page.locator( 'ul.products > li:nth-last-child(3)' )
|
||||||
|
).toContainText( `${ simpleProductName } 1` );
|
||||||
|
await expect(
|
||||||
|
page.locator( 'ul.products > li:nth-last-child(1)' )
|
||||||
|
).toContainText( `${ simpleProductName } 3` );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
);
|
|
@ -0,0 +1,324 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
const productPrice = '18.16';
|
||||||
|
const simpleProductName = 'Simple single product';
|
||||||
|
const variableProductName = 'Variable single product';
|
||||||
|
const variations = [
|
||||||
|
{
|
||||||
|
regular_price: productPrice,
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
name: 'Size',
|
||||||
|
option: 'Small',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
regular_price: ( +productPrice * 2 ).toString(),
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
name: 'Size',
|
||||||
|
option: 'Medium',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
regular_price: ( +productPrice * 3 ).toString(),
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
name: 'Size',
|
||||||
|
option: 'Large',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
regular_price: ( +productPrice * 4 ).toString(),
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
name: 'Size',
|
||||||
|
option: 'XLarge',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const groupedProductName = 'Grouped single product';
|
||||||
|
|
||||||
|
let simpleProductId, simpleProduct2Id, variableProductId, groupedProductId;
|
||||||
|
|
||||||
|
test.describe( 'Single Product Page', () => {
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add product
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: simpleProductName,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: productPrice,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
simpleProductId = response.data.id;
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
context.clearCookies();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ simpleProductId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should be able to add simple products to the cart', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
const slug = simpleProductName.replace( / /gi, '-' ).toLowerCase();
|
||||||
|
await page.goto( `product/${ slug }` );
|
||||||
|
|
||||||
|
await page.fill( 'input.qty', '5' );
|
||||||
|
await page.click( 'text=Add to cart' );
|
||||||
|
|
||||||
|
await expect( page.locator( '.woocommerce-message' ) ).toContainText(
|
||||||
|
'have been added to your cart.'
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.goto( 'cart/' );
|
||||||
|
await expect( page.locator( 'td.product-name' ) ).toContainText(
|
||||||
|
simpleProductName
|
||||||
|
);
|
||||||
|
await expect( page.locator( 'input.qty' ) ).toHaveValue( '5' );
|
||||||
|
await expect( page.locator( 'td.product-subtotal' ) ).toContainText(
|
||||||
|
( 5 * +productPrice ).toString()
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should be able to remove simple products from the cart', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ simpleProductId }` );
|
||||||
|
await page.waitForLoadState( 'networkidle' );
|
||||||
|
|
||||||
|
await page.goto( 'cart/' );
|
||||||
|
await page.click( 'a.remove' );
|
||||||
|
|
||||||
|
await expect( page.locator( 'p.cart-empty' ) ).toContainText(
|
||||||
|
'Your cart is currently empty.'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.describe( 'Variable Product Page', () => {
|
||||||
|
const slug = variableProductName.replace( / /gi, '-' ).toLowerCase();
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add product
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: variableProductName,
|
||||||
|
type: 'variable',
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
name: 'Size',
|
||||||
|
options: [ 'Small', 'Medium', 'Large', 'XLarge' ],
|
||||||
|
visible: true,
|
||||||
|
variation: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
variableProductId = response.data.id;
|
||||||
|
for ( const key in variations ) {
|
||||||
|
api.post(
|
||||||
|
`products/${ variableProductId }/variations`,
|
||||||
|
variations[ key ]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
context.clearCookies();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ variableProductId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should be able to add variation products to the cart', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( `product/${ slug }` );
|
||||||
|
|
||||||
|
for ( const attr of variations ) {
|
||||||
|
await page.selectOption( '#size', attr.attributes[ 0 ].option );
|
||||||
|
await page.click( 'text=Add to cart' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-message' )
|
||||||
|
).toContainText( 'has been added to your cart.' );
|
||||||
|
}
|
||||||
|
|
||||||
|
await page.goto( 'cart/' );
|
||||||
|
await expect(
|
||||||
|
page.locator( 'td.product-name >> nth=0' )
|
||||||
|
).toContainText( variableProductName );
|
||||||
|
await expect( page.locator( 'tr.order-total > td' ) ).toContainText(
|
||||||
|
( +productPrice * 10 ).toString()
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should be able to remove variation products from the cart', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( `product/${ slug }` );
|
||||||
|
await page.selectOption( '#size', 'Large' );
|
||||||
|
await page.click( 'text=Add to cart' );
|
||||||
|
|
||||||
|
await page.goto( 'cart/' );
|
||||||
|
await page.click( 'a.remove' );
|
||||||
|
|
||||||
|
await expect( page.locator( 'p.cart-empty' ) ).toContainText(
|
||||||
|
'Your cart is currently empty.'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.describe( 'Grouped Product Page', () => {
|
||||||
|
const slug = groupedProductName.replace( / /gi, '-' ).toLowerCase();
|
||||||
|
const simpleProduct1 = simpleProductName + ' 1';
|
||||||
|
const simpleProduct2 = simpleProductName + ' 2';
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add products
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: simpleProduct1,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: productPrice,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
simpleProductId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: simpleProduct2,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: productPrice,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
simpleProduct2Id = response.data.id;
|
||||||
|
} );
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: groupedProductName,
|
||||||
|
type: 'grouped',
|
||||||
|
grouped_products: [ simpleProductId, simpleProduct2Id ],
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
groupedProductId = response.data.id;
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
context.clearCookies();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ simpleProductId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ simpleProduct2Id }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ groupedProductId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should be able to add grouped products to the cart', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( `product/${ slug }` );
|
||||||
|
|
||||||
|
await page.click( 'text=Add to cart' );
|
||||||
|
await expect( page.locator( '.woocommerce-error' ) ).toContainText(
|
||||||
|
'Please choose the quantity of items you wish to add to your cart…'
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.fill( 'div.quantity input.qty >> nth=0', '5' );
|
||||||
|
await page.fill( 'div.quantity input.qty >> nth=1', '5' );
|
||||||
|
await page.click( 'text=Add to cart' );
|
||||||
|
await expect( page.locator( '.woocommerce-message' ) ).toContainText(
|
||||||
|
`“${ simpleProduct1 }” and “${ simpleProduct2 }” have been added to your cart.`
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.goto( 'cart/' );
|
||||||
|
await expect(
|
||||||
|
page.locator( 'td.product-name >> nth=0' )
|
||||||
|
).toContainText( simpleProduct1 );
|
||||||
|
await expect(
|
||||||
|
page.locator( 'td.product-name >> nth=1' )
|
||||||
|
).toContainText( simpleProduct2 );
|
||||||
|
await expect( page.locator( 'tr.order-total > td' ) ).toContainText(
|
||||||
|
( +productPrice * 10 ).toString()
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should be able to remove grouped products from the cart', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( `product/${ slug }` );
|
||||||
|
await page.fill( 'div.quantity input.qty >> nth=0', '1' );
|
||||||
|
await page.fill( 'div.quantity input.qty >> nth=1', '1' );
|
||||||
|
await page.click( 'text=Add to cart' );
|
||||||
|
|
||||||
|
await page.goto( 'cart/' );
|
||||||
|
await page.click( 'a.remove >> nth=1' );
|
||||||
|
await page.click( 'a.remove >> nth=0' );
|
||||||
|
|
||||||
|
await expect( page.locator( 'p.cart-empty' ) ).toContainText(
|
||||||
|
'Your cart is currently empty.'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,254 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
|
||||||
|
const variableProductName = 'Variable Product Updates';
|
||||||
|
const productPrice = '11.16';
|
||||||
|
const variations = [
|
||||||
|
{
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
name: 'Colour',
|
||||||
|
option: 'Red',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
name: 'Colour',
|
||||||
|
option: 'Blue',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
name: 'Colour',
|
||||||
|
option: 'Green',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
regular_price: productPrice,
|
||||||
|
weight: '100',
|
||||||
|
dimensions: {
|
||||||
|
length: '5',
|
||||||
|
width: '10',
|
||||||
|
height: '10',
|
||||||
|
},
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
name: 'Size',
|
||||||
|
option: 'Small',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
regular_price: productPrice,
|
||||||
|
weight: '100',
|
||||||
|
dimensions: {
|
||||||
|
length: '5',
|
||||||
|
width: '10',
|
||||||
|
height: '10',
|
||||||
|
},
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
name: 'Size',
|
||||||
|
option: 'Medium',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
regular_price: ( +productPrice * 2 ).toString(),
|
||||||
|
weight: '200',
|
||||||
|
dimensions: {
|
||||||
|
length: '10',
|
||||||
|
width: '20',
|
||||||
|
height: '15',
|
||||||
|
},
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
name: 'Size',
|
||||||
|
option: 'Large',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
regular_price: ( +productPrice * 2 ).toString(),
|
||||||
|
weight: '400',
|
||||||
|
dimensions: {
|
||||||
|
length: '20',
|
||||||
|
width: '40',
|
||||||
|
height: '30',
|
||||||
|
},
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
name: 'Size',
|
||||||
|
option: 'XLarge',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const cartDialogMessage =
|
||||||
|
'Please select some product options before adding this product to your cart.';
|
||||||
|
|
||||||
|
test.describe( 'Shopper > Update variable product', () => {
|
||||||
|
let variableProductId;
|
||||||
|
const slug = variableProductName.replace( / /gi, '-' ).toLowerCase();
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
// add product
|
||||||
|
await api
|
||||||
|
.post( 'products', {
|
||||||
|
name: variableProductName,
|
||||||
|
type: 'variable',
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
name: 'Size',
|
||||||
|
options: [ 'Small', 'Medium', 'Large', 'XLarge' ],
|
||||||
|
visible: true,
|
||||||
|
variation: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Colour',
|
||||||
|
options: [ 'Red', 'Green', 'Blue' ],
|
||||||
|
visible: true,
|
||||||
|
variation: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
variableProductId = response.data.id;
|
||||||
|
for ( const key in variations ) {
|
||||||
|
api.post(
|
||||||
|
`products/${ variableProductId }/variations`,
|
||||||
|
variations[ key ]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
context.clearCookies();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ variableProductId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'Shopper can change variable attributes to the same value', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( `product/${ slug }` );
|
||||||
|
|
||||||
|
await page.selectOption( '#size', 'Small' );
|
||||||
|
|
||||||
|
await page.selectOption( '#colour', 'Red' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-variation-price' )
|
||||||
|
).toContainText( productPrice );
|
||||||
|
|
||||||
|
await page.selectOption( '#colour', 'Green' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-variation-price' )
|
||||||
|
).toContainText( productPrice );
|
||||||
|
|
||||||
|
await page.selectOption( '#colour', 'Blue' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-variation-price' )
|
||||||
|
).toContainText( productPrice );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'Shopper can change attributes to combination with dimentions and weight', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( `product/${ slug }` );
|
||||||
|
|
||||||
|
await page.selectOption( '#colour', 'Red' );
|
||||||
|
|
||||||
|
await page.selectOption( '#size', 'Small' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-variation-price' )
|
||||||
|
).toContainText( productPrice );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-product-attributes-item--weight' )
|
||||||
|
).toContainText( '100 kg' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-product-attributes-item--dimensions' )
|
||||||
|
).toContainText( '5 × 10 × 10 cm' );
|
||||||
|
|
||||||
|
await page.selectOption( '#size', 'XLarge' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-variation-price' )
|
||||||
|
).toContainText( ( +productPrice * 2 ).toString() );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-product-attributes-item--weight' )
|
||||||
|
).toContainText( '400 kg' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-product-attributes-item--dimensions' )
|
||||||
|
).toContainText( '20 × 40 × 30 cm' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'Shopper can change variable product attributes to variation with a different price', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( `product/${ slug }` );
|
||||||
|
|
||||||
|
await page.selectOption( '#colour', 'Red' );
|
||||||
|
|
||||||
|
await page.selectOption( '#size', 'Small' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-variation-price' )
|
||||||
|
).toContainText( productPrice );
|
||||||
|
|
||||||
|
await page.selectOption( '#size', 'Medium' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-variation-price' )
|
||||||
|
).toContainText( productPrice );
|
||||||
|
|
||||||
|
await page.selectOption( '#size', 'Large' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-variation-price' )
|
||||||
|
).toContainText( ( +productPrice * 2 ).toString() );
|
||||||
|
|
||||||
|
await page.selectOption( '#size', 'XLarge' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-variation-price' )
|
||||||
|
).toContainText( ( +productPrice * 2 ).toString() );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'Shopper can reset variations', async ( { page } ) => {
|
||||||
|
await page.goto( `product/${ slug }` );
|
||||||
|
|
||||||
|
await page.selectOption( '#colour', 'Red' );
|
||||||
|
|
||||||
|
await page.selectOption( '#size', 'Small' );
|
||||||
|
await expect(
|
||||||
|
page.locator( '.woocommerce-variation-price' )
|
||||||
|
).toContainText( productPrice );
|
||||||
|
|
||||||
|
await page.click( 'a.reset_variations' );
|
||||||
|
|
||||||
|
// Verify the reset by attempting to add the product to the cart
|
||||||
|
page.on( 'dialog', async ( dialog ) => {
|
||||||
|
expect( dialog.message() ).toContain( cartDialogMessage );
|
||||||
|
await dialog.dismiss();
|
||||||
|
} );
|
||||||
|
await page.click( '.single_add_to_cart_button' );
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -78,6 +78,7 @@
|
||||||
"require-turbo": "workspace:*",
|
"require-turbo": "workspace:*",
|
||||||
"stylelint": "^13.8.0",
|
"stylelint": "^13.8.0",
|
||||||
"typescript": "3.9.7",
|
"typescript": "3.9.7",
|
||||||
|
"uuid": "^8.3.2",
|
||||||
"webpack": "5.70.0",
|
"webpack": "5.70.0",
|
||||||
"webpack-cli": "3.3.12",
|
"webpack-cli": "3.3.12",
|
||||||
"wp-textdomain": "1.0.1"
|
"wp-textdomain": "1.0.1"
|
||||||
|
|
|
@ -1270,6 +1270,7 @@ importers:
|
||||||
require-turbo: workspace:*
|
require-turbo: workspace:*
|
||||||
stylelint: ^13.8.0
|
stylelint: ^13.8.0
|
||||||
typescript: 3.9.7
|
typescript: 3.9.7
|
||||||
|
uuid: ^8.3.2
|
||||||
webpack: 5.70.0
|
webpack: 5.70.0
|
||||||
webpack-cli: 3.3.12
|
webpack-cli: 3.3.12
|
||||||
wp-textdomain: 1.0.1
|
wp-textdomain: 1.0.1
|
||||||
|
@ -1313,6 +1314,7 @@ importers:
|
||||||
require-turbo: link:../../tools/require-turbo
|
require-turbo: link:../../tools/require-turbo
|
||||||
stylelint: 13.13.1
|
stylelint: 13.13.1
|
||||||
typescript: 3.9.7
|
typescript: 3.9.7
|
||||||
|
uuid: 8.3.2
|
||||||
webpack: 5.70.0_webpack-cli@3.3.12
|
webpack: 5.70.0_webpack-cli@3.3.12
|
||||||
webpack-cli: 3.3.12_webpack@5.70.0
|
webpack-cli: 3.3.12_webpack@5.70.0
|
||||||
wp-textdomain: 1.0.1
|
wp-textdomain: 1.0.1
|
||||||
|
@ -17027,7 +17029,7 @@ packages:
|
||||||
loader-utils: 1.4.0
|
loader-utils: 1.4.0
|
||||||
make-dir: 3.1.0
|
make-dir: 3.1.0
|
||||||
schema-utils: 2.7.1
|
schema-utils: 2.7.1
|
||||||
webpack: 4.46.0_webpack-cli@3.3.12
|
webpack: 4.46.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/babel-loader/8.2.3_d3f6fe5812216e437b67a6bf164a056c:
|
/babel-loader/8.2.3_d3f6fe5812216e437b67a6bf164a056c:
|
||||||
|
@ -17057,7 +17059,7 @@ packages:
|
||||||
loader-utils: 1.4.0
|
loader-utils: 1.4.0
|
||||||
make-dir: 3.1.0
|
make-dir: 3.1.0
|
||||||
schema-utils: 2.7.1
|
schema-utils: 2.7.1
|
||||||
webpack: 5.70.0_webpack-cli@4.9.2
|
webpack: 5.70.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/babel-messages/6.23.0:
|
/babel-messages/6.23.0:
|
||||||
|
@ -19517,7 +19519,7 @@ packages:
|
||||||
postcss-value-parser: 4.2.0
|
postcss-value-parser: 4.2.0
|
||||||
schema-utils: 2.7.1
|
schema-utils: 2.7.1
|
||||||
semver: 6.3.0
|
semver: 6.3.0
|
||||||
webpack: 4.46.0_webpack-cli@3.3.12
|
webpack: 4.46.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/css-loader/3.6.0_webpack@5.70.0:
|
/css-loader/3.6.0_webpack@5.70.0:
|
||||||
|
@ -36552,7 +36554,7 @@ packages:
|
||||||
serialize-javascript: 4.0.0
|
serialize-javascript: 4.0.0
|
||||||
source-map: 0.6.1
|
source-map: 0.6.1
|
||||||
terser: 4.8.0
|
terser: 4.8.0
|
||||||
webpack: 4.46.0_webpack-cli@3.3.12
|
webpack: 4.46.0
|
||||||
webpack-sources: 1.4.3
|
webpack-sources: 1.4.3
|
||||||
worker-farm: 1.7.0
|
worker-farm: 1.7.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
Loading…
Reference in New Issue