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:
Jonathan Lane 2022-07-06 13:28:00 -07:00 committed by GitHub
parent aed4763414
commit 0cebdf5277
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 3437 additions and 721 deletions

View File

@ -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:

View File

@ -0,0 +1 @@
Significance: patch

View File

@ -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&section=keys&create-key=1` `${ baseURL }/wp-admin/admin.php?page=wc-settings&tab=advanced&section=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();
}; };

View File

@ -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'] },
// },
], ],
}; };

View File

@ -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 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
2 44 variable woo-vneck-tee V-Neck T-Shirt 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
3 45 variable woo-hoodie 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
4 46 simple woo-hoodie-with-logo 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
5 47 simple woo-tshirt T-Shirt 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
6 48 simple woo-beanie 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
7 58 simple woo-belt 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
8 60 simple woo-cap 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
9 62 simple woo-sunglasses 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
10 64 simple woo-hoodie-with-pocket 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
11 66 simple woo-hoodie-with-zipper 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
12 68 simple woo-long-sleeve-tee 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
13 70 simple woo-polo 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
14 73 simple, downloadable, virtual woo-album 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
15 75 simple, downloadable, virtual woo-single 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
16 76 variation woo-vneck-tee-red V-Neck T-Shirt - 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
17 77 variation woo-vneck-tee-green V-Neck T-Shirt - 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
18 78 variation woo-vneck-tee-blue V-Neck T-Shirt - 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
19 79 variation woo-hoodie-red Hoodie - Red, No 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
20 80 variation woo-hoodie-green Hoodie - Green, No 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
21 81 variation woo-hoodie-blue Hoodie - Blue, No 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
22 83 simple Woo-tshirt-logo T-Shirt with 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
23 85 simple Woo-beanie-logo Beanie with 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
24 87 grouped logo-collection 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
25 89 external wp-pennant WordPress 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
26 90 variation woo-hoodie-blue-logo Hoodie - Blue, Yes 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

View File

@ -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",,,,,

1 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
2 variable woo-vneck-tee V-Neck T-Shirt Override 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
3 variable woo-hoodie Hoodie Override 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
4 simple woo-hoodie-with-logo Hoodie with Logo Override 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
5 simple woo-tshirt T-Shirt Override 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
6 simple woo-beanie Beanie Override 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
7 simple woo-belt Belt Override 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
8 simple woo-cap Cap Override 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
9 simple woo-sunglasses Sunglasses Override 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
10 simple woo-hoodie-with-pocket Hoodie with Pocket Override 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
11 simple woo-hoodie-with-zipper Hoodie with Zipper Override 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
12 simple woo-long-sleeve-tee Long Sleeve Tee Override 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
13 simple woo-polo Polo Override 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
14 simple, downloadable, virtual woo-album Album Override 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
15 simple, downloadable, virtual woo-single Single Override 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
16 variation woo-vneck-tee-red V-Neck T-Shirt - Red Override 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
17 variation woo-vneck-tee-green V-Neck T-Shirt - Green Override 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
18 variation woo-vneck-tee-blue V-Neck T-Shirt - Blue Override 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
19 variation woo-hoodie-red Hoodie - Red, No Override 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
20 variation woo-hoodie-green Hoodie - Green, No Override 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
21 variation woo-hoodie-blue Hoodie - Blue, No Override 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
22 simple Woo-tshirt-logo T-Shirt with Logo Override 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
23 simple Woo-beanie-logo Beanie with Logo Override 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
24 grouped logo-collection Logo Collection Override 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
25 external wp-pennant WordPress Pennant Override 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
26 variation woo-hoodie-blue-logo Hoodie - Blue, Yes Override 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

View File

@ -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/' );
} ); } );
} ); } );

View File

@ -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();
} }

View File

@ -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' );
) await page.click( 'text=Move down' );
.click();
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' );
) await page.click( 'text=Move up' );
.click();
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' );
} );
} ); } );

View File

@ -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();

View File

@ -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&section=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&section=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' );
} ); } );
} ); } );

View File

@ -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(
await page.goto( '/' ); 'A basic set of tests to ensure WP, wp-admin and my-account load',
const title = page.locator( 'h1.site-title' ); () => {
await expect( title ).toHaveText( 'WooCommerce Core E2E Test Suite' ); test( 'Load the home page', async ( { page } ) => {
} ); await page.goto( '/' );
const title = page.locator( 'h1.site-title' );
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' );
} ); } );
} ); } );
}
);

View File

@ -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' );
} ); } );
} ); } );

View File

@ -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 ) { // attach rates to the classes
api.post( 'taxes', taxRates[ rate ] ); for ( let i = 0; i < taxRates.length; i++ ) {
} await api.post( 'taxes', taxRates[ i ] );
}
);
} }
// make sure the taxes are all created before creating products
api.get( 'taxes/classes' ).then( ( response ) => {
while ( true ) {
if ( Object.keys( response.data ).length === 3 ) {
api.post( 'products', {
name: 'Simple Product 273722',
type: 'simple',
regular_price: '100',
tax_class: 'Tax Class Simple',
} ).then( ( resp ) => {
simpleProductId = resp.data.id;
} );
break;
}
}
} );
// create simple product // create simple product
await api
.post( 'products', {
name: simpleProductName,
type: 'simple',
regular_price: '100',
tax_class: 'Tax Class Simple',
} )
.then( ( resp ) => {
simpleProductId = resp.data.id;
} );
// 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

View File

@ -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&section=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&section=classes' 'wp-admin/admin.php?page=wc-settings&tab=shipping&section=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' );
} ); } );
} ); } );

View File

@ -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
name: 'Shipping options are the best', .post( 'products', {
type: 'simple', name: 'Shipping options are the best',
regular_price: '25.99', type: 'simple',
} ).then( ( response ) => { regular_price: '25.99',
productId = response.data.id; } )
.then( ( response ) => {
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' );
} ); } );
} ); } );

View File

@ -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',
} ); } );

View File

@ -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
); );

View File

@ -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 );
} ); } );
} ); } );

View File

@ -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,279 +86,256 @@ 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';
const product2Name = 'TDP 002'; const product2Name = 'TDP 002';
const customerBilling = { const customerBilling = {
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( {
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
.post( 'products', {
name: productName,
downloadable: true,
download_limit: -1,
downloads: [
{
id: uuid.v4(),
name: 'Single',
file:
'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg',
},
],
} )
.then( ( response ) => {
productId = response.data.id;
} ); } );
await api await api
.post( 'products', { .post( 'products', {
name: productName, name: product2Name,
downloadable: true, downloadable: true,
download_limit: -1, download_limit: -1,
downloads: [ downloads: [
{ {
id: uuid.v4(), id: uuid.v4(),
name: 'Single', name: 'Single',
file: file:
'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg', 'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg',
}, },
], ],
} ) } )
.then( ( response ) => { .then( ( response ) => {
productId = response.data.id; product2Id = response.data.id;
} );
await api
.post( 'products', {
name: product2Name,
downloadable: true,
download_limit: -1,
downloads: [
{
id: uuid.v4(),
name: 'Single',
file:
'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg',
},
],
} )
.then( ( response ) => {
product2Id = response.data.id;
} );
await api
.post( 'orders', {
status: 'processing',
line_items: [
{
product_id: productId,
quantity: 1,
},
],
billing: customerBilling,
} )
.then( ( response ) => {
orderId = response.data.id;
} );
await api
.post( 'orders', {
status: 'processing',
billing: customerBilling,
} )
.then( ( response ) => {
noProductOrderId = response.data.id;
} );
} );
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.delete( `products/${ productId }`, { force: true } ); await api
await api.delete( `products/${ product2Id }`, { force: true } ); .post( 'orders', {
await api.delete( `orders/${ orderId }`, { force: true } ); status: 'processing',
await api.delete( `orders/${ noProductOrderId }`, { force: true } ); line_items: [
{
product_id: productId,
quantity: 1,
},
],
billing: customerBilling,
} )
.then( ( response ) => {
orderId = response.data.id;
} );
await api
.post( 'orders', {
status: 'processing',
billing: customerBilling,
} )
.then( ( response ) => {
noProductOrderId = response.data.id;
} );
} );
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.delete( `products/${ productId }`, { force: true } );
await api.delete( `products/${ product2Id }`, { force: true } );
await api.delete( `orders/${ orderId }`, { force: true } );
await api.delete( `orders/${ noProductOrderId }`, { force: true } );
} );
test( 'can add downloadable product permissions to order without product', async ( { test( 'can add downloadable product permissions to order without product', async ( {
page, page,
} ) => { } ) => {
// go to the order with no products // go to the order with no products
await page.goto( await page.goto(
`wp-admin/post.php?post=${ noProductOrderId }&action=edit` `wp-admin/post.php?post=${ noProductOrderId }&action=edit`
); );
// add downloadable product permissions // add downloadable product permissions
await page.type( 'input.select2-search__field', productName ); await page.type( 'input.select2-search__field', productName );
await page.click( await page.click(
'li.select2-results__option.select2-results__option--highlighted' 'li.select2-results__option.select2-results__option--highlighted'
); );
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(
); page.locator( 'input[name="downloads_remaining[1]"]' )
await expect( ).toHaveAttribute( 'placeholder', 'Unlimited' );
page.locator( 'input[name="downloads_remaining[1]"]' ) await expect(
).toHaveAttribute( 'placeholder', 'Unlimited' ); page.locator( 'input[name="access_expires[1]"]' )
await expect( ).toHaveAttribute( 'placeholder', 'Never' );
page.locator( 'input[name="access_expires[1]"]' ) await expect( page.locator( 'button.revoke_access' ) ).toBeVisible();
).toHaveAttribute( 'placeholder', 'Never' ); await expect( page.locator( 'a:has-text("Copy link")' ) ).toBeVisible();
await expect( await expect(
page.locator( 'button.revoke_access' ) page.locator( 'a:has-text("View report")' )
).toBeVisible(); ).toBeVisible();
await expect( } );
page.locator( 'a:has-text("Copy link")' )
).toBeVisible();
await expect(
page.locator( 'a:has-text("View report")' )
).toBeVisible();
} );
test( 'can add downloadable product permissions to order with product', async ( { test( 'can add downloadable product permissions to order with product', 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`
);
// add downloadable product permissions // add downloadable product permissions
await page.type( 'input.select2-search__field', product2Name ); await page.type( 'input.select2-search__field', product2Name );
await page.click( await page.click(
'li.select2-results__option.select2-results__option--highlighted' 'li.select2-results__option.select2-results__option--highlighted'
); );
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 >> nth=1' ) ).toContainText( await expect( page.locator( 'h3.fixed >> nth=1' ) ).toContainText(
product2Name product2Name
); );
await expect( await expect(
page.locator( 'input[name="downloads_remaining[2]"]' ) page.locator( 'input[name="downloads_remaining[2]"]' )
).toHaveAttribute( 'placeholder', 'Unlimited' ); ).toHaveAttribute( 'placeholder', 'Unlimited' );
await expect( await expect(
page.locator( 'input[name="access_expires[2]"]' ) page.locator( 'input[name="access_expires[2]"]' )
).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 expectedDownloadsExpirationDate = '2050-01-01';
const expectedDownloadsRemaining = '10';
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' );
// edit download permissions // edit download permissions
await page.fill( await page.fill(
'input[name="downloads_remaining[0]"]', 'input[name="downloads_remaining[0]"]',
expectedDownloadsRemaining expectedDownloadsRemaining
); );
await page.fill( await page.fill(
'input[name="access_expires[0]"]', 'input[name="access_expires[0]"]',
expectedDownloadsExpirationDate expectedDownloadsExpirationDate
); );
await page.click( 'button.save_order' ); await page.click( 'button.save_order' );
// verify new downloadable product permissions // verify new downloadable product permissions
await page.click( 'h3.fixed' ); await page.click( 'h3.fixed' );
await expect( await expect(
page.locator( 'input[name="downloads_remaining[0]"]' ) page.locator( 'input[name="downloads_remaining[0]"]' )
).toHaveValue( expectedDownloadsRemaining ); ).toHaveValue( expectedDownloadsRemaining );
await expect( await expect(
page.locator( 'input[name="access_expires[0]"]' ) page.locator( 'input[name="access_expires[0]"]' )
).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
} ) => { await page.goto( `wp-admin/post.php?post=${ orderId }&action=edit` );
// open the order that already has a product assigned
await page.goto(
`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' );
// verify prior state before revoking // verify prior state before revoking
await expect( page.locator( 'h3.fixed' ) ).toHaveCount( 1 ); await expect( page.locator( 'h3.fixed' ) ).toHaveCount( 1 );
// click revoke access // click revoke access
page.on( 'dialog', ( dialog ) => dialog.accept() ); page.on( 'dialog', ( dialog ) => dialog.accept() );
await page.click( 'button.revoke_access' ); await page.click( 'button.revoke_access' );
await page.waitForLoadState( 'networkidle' ); await page.waitForLoadState( 'networkidle' );
// verify permissions gone // verify permissions gone
await expect( page.locator( 'h3.fixed' ) ).toHaveCount( 0 ); await expect( page.locator( 'h3.fixed' ) ).toHaveCount( 0 );
} ); } );
test( 'should not allow downloading a product if download attempts are exceeded', async ( { test( 'should not allow downloading a product if download attempts are exceeded', async ( {
page, page,
} ) => { } ) => {
const expectedReason = const expectedReason =
'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
await page.click( 'h3.fixed' ); await page.click( 'h3.fixed' );
// edit download permissions // edit download permissions
await page.fill( 'input[name="downloads_remaining[0]"]', '0' ); await page.fill( 'input[name="downloads_remaining[0]"]', '0' );
await page.click( 'button.save_order' ); await page.click( 'button.save_order' );
// get the download link // get the download link
await page.click( 'h3.fixed' ); await page.click( 'h3.fixed' );
const downloadPage = await page const downloadPage = await page
.locator( 'a#copy-download-link' ) .locator( 'a#copy-download-link' )
.getAttribute( 'href' ); .getAttribute( 'href' );
// open download page // open download page
await page.goto( downloadPage ); await page.goto( downloadPage );
await expect( page.locator( 'div.wp-die-message' ) ).toContainText( await expect( page.locator( 'div.wp-die-message' ) ).toContainText(
expectedReason expectedReason
); );
} ); } );
test( 'should not allow downloading a product if expiration date has passed', async ( { test( 'should not allow downloading a product if expiration date has passed', async ( {
page, page,
} ) => { } ) => {
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
await page.click( 'h3.fixed' ); await page.click( 'h3.fixed' );
// edit download permissions // edit download permissions
await page.fill( 'input[name="access_expires[0]"]', '2018-12-14' ); await page.fill( 'input[name="access_expires[0]"]', '2018-12-14' );
await page.click( 'button.save_order' ); await page.click( 'button.save_order' );
// get the download link // get the download link
await page.click( 'h3.fixed' ); await page.click( 'h3.fixed' );
const downloadPage = await page const downloadPage = await page
.locator( 'a#copy-download-link' ) .locator( 'a#copy-download-link' )
.getAttribute( 'href' ); .getAttribute( 'href' );
// open download page // open download page
await page.goto( downloadPage ); await page.goto( downloadPage );
await expect( page.locator( 'div.wp-die-message' ) ).toContainText( await expect( page.locator( 'div.wp-die-message' ) ).toContainText(
expectedReason expectedReason
); );
} ); } );
} } );
);

View File

@ -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
); );

View File

@ -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.'
); );

View File

@ -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 }` );
} ); } );
} }

View File

@ -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 );
} ); } );
} }
} ); } );

View File

@ -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 ) =>

View File

@ -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

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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 }`
);
} );
} );

View File

@ -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'
);
} );
} );

View File

@ -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
);
} );
} );

View File

@ -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();
} );
} );

View File

@ -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'
);
} );
} );

View File

@ -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
);
} );
} );

View File

@ -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'
);
} );
} );

View File

@ -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
);
} );
} );

View File

@ -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
);
} );
} );

View File

@ -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'
);
} );
} );

View File

@ -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 ]
);
} );
}
} );

View File

@ -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 }` );
} );
} );

View File

@ -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` );
} );
}
);

View File

@ -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.'
);
} );
} );

View File

@ -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' );
} );
} );

View File

@ -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"

View File

@ -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