diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/checkout/checkout-block.shopper.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/checkout/checkout-block.shopper.block_theme.spec.ts
index de86eff5685..d3b78538f47 100644
--- a/plugins/woocommerce-blocks/tests/e2e/tests/checkout/checkout-block.shopper.block_theme.spec.ts
+++ b/plugins/woocommerce-blocks/tests/e2e/tests/checkout/checkout-block.shopper.block_theme.spec.ts
@@ -482,6 +482,8 @@ test.describe( 'Shopper → Checkout Form Errors (guest user)', () => {
await frontendUtils.goToCheckout();
await page.getByLabel( 'Email address' ).clear();
+ // Notices on the email field will move content when the field loses focus. This can cause the click to "miss".
+ await page.getByRole( 'button', { name: 'Place order' } ).focus();
await page.getByRole( 'button', { name: 'Place order' } ).click();
// Verify that all required fields show the correct warning.
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/active-filters.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/active-filters.block_theme.spec.ts
deleted file mode 100644
index b4c78fd0ab1..00000000000
--- a/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/active-filters.block_theme.spec.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * External dependencies
- */
-import { TemplateCompiler, test as base, expect } from '@woocommerce/e2e-utils';
-
-const test = base.extend< { templateCompiler: TemplateCompiler } >( {
- templateCompiler: async ( { requestUtils }, use ) => {
- const compiler = await requestUtils.createTemplateFromFile(
- 'archive-product_active-filters'
- );
- await use( compiler );
- },
-} );
-
-test.describe( 'Product Filter: Active Filters Block', () => {
- test.describe( 'frontend', () => {
- test.beforeEach( async ( { requestUtils } ) => {
- await requestUtils.activatePlugin(
- 'woocommerce-blocks-test-enable-experimental-features'
- );
- } );
-
- test( 'Without any filters selected, only a wrapper block is rendered', async ( {
- page,
- templateCompiler,
- } ) => {
- await templateCompiler.compile();
-
- await page.goto( '/shop' );
-
- const locator = page.locator(
- '.wp-block-woocommerce-product-filter'
- );
-
- await expect( locator ).toHaveCount( 1 );
-
- const html = await locator.innerHTML();
- expect( html.trim() ).toBe( '' );
- } );
-
- test( 'With rating filters applied it shows the correct active filters', async ( {
- page,
- templateCompiler,
- } ) => {
- await templateCompiler.compile();
-
- await page.goto( `${ '/shop' }?rating_filter=1,2,5` );
-
- await expect( page.getByText( 'Rating:' ) ).toBeVisible();
- await expect( page.getByText( 'Rated 1 out of 5' ) ).toBeVisible();
- await expect( page.getByText( 'Rated 2 out of 5' ) ).toBeVisible();
- await expect( page.getByText( 'Rated 5 out of 5' ) ).toBeVisible();
- } );
-
- test( 'With stock filters applied it shows the correct active filters', async ( {
- page,
- templateCompiler,
- } ) => {
- await templateCompiler.compile();
-
- await page.goto(
- `${ '/shop' }?filter_stock_status=instock,onbackorder`
- );
-
- await expect( page.getByText( 'Stock Status:' ) ).toBeVisible();
- await expect( page.getByText( 'In stock' ) ).toBeVisible();
- await expect( page.getByText( 'On backorder' ) ).toBeVisible();
- } );
-
- test( 'With attribute filters applied it shows the correct active filters', async ( {
- page,
- templateCompiler,
- } ) => {
- await templateCompiler.compile();
-
- await page.goto(
- `${ '/shop' }?filter_color=blue,gray&query_type_color=or`
- );
-
- await expect( page.getByText( 'Color:' ) ).toBeVisible();
- await expect( page.getByText( 'Blue' ) ).toBeVisible();
- await expect( page.getByText( 'Gray' ) ).toBeVisible();
- } );
-
- test( 'With price filters applied it shows the correct active filters', async ( {
- page,
- templateCompiler,
- } ) => {
- await templateCompiler.compile();
-
- await page.goto( `${ '/shop' }?min_price=17&max_price=71` );
-
- await expect( page.getByText( 'Price:' ) ).toBeVisible();
- await expect(
- page.getByText( 'Between $17 and $71' )
- ).toBeVisible();
- } );
- } );
-} );
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/attribute-filter.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/attribute-filter.block_theme.spec.ts
deleted file mode 100644
index d39c14ff018..00000000000
--- a/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/attribute-filter.block_theme.spec.ts
+++ /dev/null
@@ -1,316 +0,0 @@
-/**
- * External dependencies
- */
-import { TemplateCompiler, test as base, expect } from '@woocommerce/e2e-utils';
-
-const COLOR_ATTRIBUTE_VALUES = [ 'Blue', 'Gray', 'Green', 'Red', 'Yellow' ];
-const COLOR_ATTRIBUTES_WITH_COUNTS = [
- 'Blue (4)',
- 'Gray (2)',
- 'Green (3)',
- 'Red (4)',
- 'Yellow (1)',
-];
-
-const test = base.extend< { templateCompiler: TemplateCompiler } >( {
- templateCompiler: async ( { requestUtils }, use ) => {
- const compiler = await requestUtils.createTemplateFromFile(
- 'archive-product_attribute-filter'
- );
- await use( compiler );
- },
-} );
-
-test.describe( 'Product Filter: Attribute Block', () => {
- test.describe( 'With default display style', () => {
- test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
- await requestUtils.activatePlugin(
- 'woocommerce-blocks-test-enable-experimental-features'
- );
- await templateCompiler.compile( {
- attributes: {
- attributeId: 1,
- },
- } );
- } );
-
- test( 'clear button is not shown on initial page load', async ( {
- page,
- } ) => {
- await page.goto( '/shop' );
-
- const button = page.getByRole( 'button', { name: 'Clear' } );
-
- await expect( button ).toBeHidden();
- } );
-
- test( 'renders a checkbox list with the available attribute filters', async ( {
- page,
- } ) => {
- await page.goto( '/shop' );
-
- const attributes = page.locator(
- '.wc-block-interactivity-components-checkbox-list__label'
- );
-
- await expect( attributes ).toHaveCount( 5 );
-
- for ( let i = 0; i < COLOR_ATTRIBUTE_VALUES.length; i++ ) {
- await expect( attributes.nth( i ) ).toHaveText(
- COLOR_ATTRIBUTE_VALUES[ i ]
- );
- }
- } );
-
- test( 'filters the list of products by selecting an attribute', async ( {
- page,
- } ) => {
- await page.goto( '/shop' );
-
- const grayCheckbox = page.getByText( 'Gray' );
- await grayCheckbox.click();
-
- // wait for navigation
- await page.waitForURL( /.*filter_color=gray.*/ );
-
- const products = page.locator( '.wc-block-product' );
-
- await expect( products ).toHaveCount( 2 );
- } );
-
- test( 'clear button appears after a filter is applied', async ( {
- page,
- } ) => {
- await page.goto( '/shop' );
-
- const grayCheckbox = page.getByText( 'Gray' );
- await grayCheckbox.click();
-
- // wait for navigation
- await page.waitForURL( /.*filter_color=gray.*/ );
-
- const button = page.getByRole( 'button', { name: 'Clear' } );
-
- await expect( button ).toBeVisible();
- } );
-
- test( 'clear button hides after deselecting all filters', async ( {
- page,
- } ) => {
- await page.goto( '/shop' );
-
- const grayCheckbox = page.getByText( 'Gray' );
- await grayCheckbox.click();
-
- // wait for navigation
- await page.waitForURL( /.*filter_color=gray.*/ );
-
- await grayCheckbox.click();
-
- const button = page.getByRole( 'button', { name: 'Clear' } );
-
- await expect( button ).toBeHidden();
- } );
-
- test( 'filters are cleared after clear button is clicked', async ( {
- page,
- } ) => {
- await page.goto( '/shop' );
-
- const grayCheckbox = page.getByText( 'Gray' );
- await grayCheckbox.click();
-
- // wait for navigation
- await page.waitForURL( /.*filter_color=gray.*/ );
-
- const button = page.getByRole( 'button', { name: 'Clear' } );
-
- await button.click();
-
- COLOR_ATTRIBUTE_VALUES.map( async ( color ) => {
- const element = page.locator(
- `input[value="${ color.toLowerCase() }"]`
- );
-
- await expect( element ).not.toBeChecked();
- } );
- } );
- } );
-
- test.describe( 'With show counts enabled', () => {
- test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
- await requestUtils.activatePlugin(
- 'woocommerce-blocks-test-enable-experimental-features'
- );
- await templateCompiler.compile( {
- attributes: {
- attributeId: 1,
- showCounts: true,
- },
- } );
- } );
-
- test( 'Renders checkboxes with associated product counts', async ( {
- page,
- } ) => {
- await page.goto( '/shop' );
-
- const attributes = page.locator(
- '.wc-block-interactivity-components-checkbox-list__label'
- );
-
- await expect( attributes ).toHaveCount( 5 );
-
- for ( let i = 0; i < COLOR_ATTRIBUTES_WITH_COUNTS.length; i++ ) {
- await expect( attributes.nth( i ) ).toHaveText(
- COLOR_ATTRIBUTES_WITH_COUNTS[ i ]
- );
- }
- } );
- } );
-
- test.describe( "With display style 'dropdown'", () => {
- test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
- await requestUtils.activatePlugin(
- 'woocommerce-blocks-test-enable-experimental-features'
- );
- await templateCompiler.compile( {
- attributes: {
- attributeId: 1,
- displayStyle: 'dropdown',
- },
- } );
- } );
-
- test( 'clear button is not shown on initial page load', async ( {
- page,
- } ) => {
- await page.goto( '/shop' );
-
- const button = page.getByRole( 'button', { name: 'Clear' } );
-
- await expect( button ).toBeHidden();
- } );
-
- test( 'renders a dropdown list with the available attribute filters', async ( {
- page,
- } ) => {
- await page.goto( '/shop' );
-
- const dropdownLocator = page.locator(
- '.wc-interactivity-dropdown'
- );
-
- await expect( dropdownLocator ).toBeVisible();
- await dropdownLocator.click();
-
- for ( let i = 0; i < COLOR_ATTRIBUTE_VALUES.length; i++ ) {
- await expect(
- dropdownLocator.getByText( COLOR_ATTRIBUTE_VALUES[ i ] )
- ).toBeVisible();
- }
- } );
-
- test( 'Clicking a dropdown option should filter the displayed products', async ( {
- page,
- } ) => {
- await page.goto( '/shop' );
-
- const dropdownLocator = page.locator(
- '.wc-interactivity-dropdown'
- );
-
- await expect( dropdownLocator ).toBeVisible();
- await dropdownLocator.click();
-
- const yellowOption = page.getByText( 'Yellow' );
- await yellowOption.click();
-
- // wait for navigation
- await page.waitForURL( /.*filter_color=yellow.*/ );
-
- const products = page.locator( '.wc-block-product' );
-
- await expect( products ).toHaveCount( 1 );
- } );
-
- test( 'clear button appears after a filter is applied', async ( {
- page,
- } ) => {
- await page.goto( '/shop' );
-
- const dropdownLocator = page.locator(
- '.wc-interactivity-dropdown'
- );
-
- await expect( dropdownLocator ).toBeVisible();
- await dropdownLocator.click();
-
- const yellowOption = page.getByText( 'Yellow' );
- await yellowOption.click();
-
- // wait for navigation
- await page.waitForURL( /.*filter_color=yellow.*/ );
-
- const button = page.getByRole( 'button', { name: 'Clear' } );
-
- await expect( button ).toBeVisible();
- } );
-
- test( 'clear button hides after deselecting all filters', async ( {
- page,
- } ) => {
- await page.goto( '/shop' );
-
- const dropdownLocator = page.locator(
- '.wc-interactivity-dropdown'
- );
-
- await dropdownLocator.click();
-
- const yellowOption = page.getByText( 'Yellow' );
- await yellowOption.click();
-
- // wait for navigation
- await page.waitForURL( /.*filter_color=yellow.*/ );
-
- await dropdownLocator.click();
-
- const button = page.getByRole( 'button', { name: 'Clear' } );
-
- const removeFilter = page.locator(
- '.wc-interactivity-dropdown__badge-remove'
- );
-
- await removeFilter.click();
-
- await expect( button ).toBeHidden();
- } );
-
- test( 'filters are cleared after clear button is clicked', async ( {
- page,
- } ) => {
- await page.goto( '/shop' );
-
- const dropdownLocator = page.locator(
- '.wc-interactivity-dropdown'
- );
-
- await dropdownLocator.click();
-
- const yellowOption = page.getByText( 'Yellow' );
- await yellowOption.click();
-
- // wait for navigation
- await page.waitForURL( /.*filter_color=yellow.*/ );
-
- const button = page.getByRole( 'button', { name: 'Clear' } );
-
- await button.click();
-
- const placeholder = page.getByText( 'Select Color' );
-
- await expect( placeholder ).toBeVisible();
- } );
- } );
-} );
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/basic.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/basic.block_theme.spec.ts
deleted file mode 100644
index db9f8dd5b10..00000000000
--- a/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/basic.block_theme.spec.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * External dependencies
- */
-import { test, expect } from '@woocommerce/e2e-utils';
-
-const filterBlocks = [
- {
- name: 'woocommerce/product-filter-price',
- title: 'Product Filter: Price (Experimental)',
- heading: 'Filter by Price',
- },
- {
- name: 'woocommerce/product-filter-stock-status',
- title: 'Product Filter: Stock Status (Experimental)',
- heading: 'Filter by Stock Status',
- },
- {
- name: 'woocommerce/product-filter-rating',
- title: 'Product Filter: Rating (Experimental)',
- heading: 'Filter by Rating',
- },
- {
- name: 'woocommerce/product-filter-attribute',
- title: 'Product Filter: Attribute (Experimental)',
- heading: 'Filter by Attribute',
- },
- {
- name: 'woocommerce/product-filter-active',
- title: 'Product Filter: Active Filters (Experimental)',
- heading: 'Active Filters',
- },
-];
-
-test.describe( 'Filter blocks registration', () => {
- test.beforeEach( async ( { admin } ) => {
- await admin.createNewPost();
- } );
-
- test( 'Variations cannot be inserted through the inserter.', async ( {
- page,
- editor,
- } ) => {
- for ( const block of filterBlocks ) {
- await editor.openGlobalBlockInserter();
- await page.getByPlaceholder( 'Search' ).fill( block.title );
- const filterBlock = page.getByRole( 'option', {
- name: block.title,
- exact: true,
- } );
-
- await expect( filterBlock ).toBeHidden();
- }
- } );
-} );
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-filters-overlay/product-filters-overlay-template-part.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters-overlay/product-filters-overlay-template-part.block_theme.spec.ts
index a5e02ea94fa..97ae2631985 100644
--- a/plugins/woocommerce-blocks/tests/e2e/tests/product-filters-overlay/product-filters-overlay-template-part.block_theme.spec.ts
+++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters-overlay/product-filters-overlay-template-part.block_theme.spec.ts
@@ -105,10 +105,6 @@ test.describe( 'Filters Overlay Template Part', () => {
templatePartData.selectors.editor.blocks.activeFilters
.blockLabel
)
- .getByLabel(
- templatePartData.selectors.editor.blocks.filterOptions
- .blockLabel
- )
.click();
await editor.openDocumentSettingsSidebar();
@@ -174,7 +170,9 @@ test.describe( 'Filters Overlay Template Part', () => {
await expect( productFiltersDialog ).toBeHidden();
} );
- test( 'should hide Product Filters Overlay Navigation block when the Overlay mode is set to `Never`', async ( {
+ // Since we need to overhaul the overlay area, we can skip this test for now.
+ // eslint-disable-next-line playwright/no-skipped-test
+ test.skip( 'should hide Product Filters Overlay Navigation block when the Overlay mode is set to `Never`', async ( {
editor,
page,
frontendUtils,
@@ -199,10 +197,6 @@ test.describe( 'Filters Overlay Template Part', () => {
templatePartData.selectors.editor.blocks.activeFilters
.blockLabel
)
- .getByLabel(
- templatePartData.selectors.editor.blocks.filterOptions
- .blockLabel
- )
.click();
await editor.openDocumentSettingsSidebar();
@@ -219,12 +213,6 @@ test.describe( 'Filters Overlay Template Part', () => {
'OverlayNeverMobileAlways'
);
await layoutSettings.getByLabel( 'Never' ).click();
- await editor.page
- .getByRole( 'link', {
- name: templatePartData.selectors.editor.blocks
- .productFiltersOverlayNavigation.title,
- } )
- .click();
await editor.saveSiteEditorEntities( {
isOnlyCurrentEntityDirty: true,
@@ -269,10 +257,6 @@ test.describe( 'Filters Overlay Template Part', () => {
templatePartData.selectors.editor.blocks.activeFilters
.blockLabel
)
- .getByLabel(
- templatePartData.selectors.editor.blocks.filterOptions
- .blockLabel
- )
.click();
await editor.openDocumentSettingsSidebar();
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/active-filter-frontend.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/active-filter-frontend.block_theme.spec.ts
new file mode 100644
index 00000000000..341a57ee21e
--- /dev/null
+++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/active-filter-frontend.block_theme.spec.ts
@@ -0,0 +1,115 @@
+/**
+ * External dependencies
+ */
+import { TemplateCompiler, test as base, expect } from '@woocommerce/e2e-utils';
+
+const test = base.extend< { templateCompiler: TemplateCompiler } >( {
+ templateCompiler: async ( { requestUtils }, use ) => {
+ const compiler = await requestUtils.createTemplateFromFile(
+ 'archive-product_active-filters'
+ );
+ await use( compiler );
+ },
+} );
+
+test.describe( 'woocommerce/product-filter-active - Frontend', () => {
+ test.beforeEach( async ( { requestUtils } ) => {
+ await requestUtils.activatePlugin(
+ 'woocommerce-blocks-test-enable-experimental-features'
+ );
+ } );
+
+ test( 'Without any filters selected, only a wrapper block is rendered', async ( {
+ page,
+ templateCompiler,
+ } ) => {
+ await templateCompiler.compile( {
+ attributes: {
+ displayStyle: 'list',
+ },
+ } );
+
+ await page.goto( '/shop' );
+
+ const locator = page.locator(
+ '.wp-block-woocommerce-product-filter-active'
+ );
+
+ await expect( locator ).toHaveCount( 1 );
+
+ const html = await locator.innerHTML();
+ expect( html.trim() ).toBe( '' );
+ } );
+
+ test( 'With rating filters applied it shows the correct active filters', async ( {
+ page,
+ templateCompiler,
+ } ) => {
+ await templateCompiler.compile( {
+ attributes: {
+ displayStyle: 'list',
+ },
+ } );
+
+ await page.goto( `${ '/shop' }?rating_filter=1,2,5` );
+
+ await expect( page.getByText( 'Rating:' ) ).toBeVisible();
+ await expect( page.getByText( 'Rated 1 out of 5' ) ).toBeVisible();
+ await expect( page.getByText( 'Rated 2 out of 5' ) ).toBeVisible();
+ await expect( page.getByText( 'Rated 5 out of 5' ) ).toBeVisible();
+ } );
+
+ test( 'With stock filters applied it shows the correct active filters', async ( {
+ page,
+ templateCompiler,
+ } ) => {
+ await templateCompiler.compile( {
+ attributes: {
+ displayStyle: 'list',
+ },
+ } );
+
+ await page.goto(
+ `${ '/shop' }?filter_stock_status=instock,onbackorder`
+ );
+
+ await expect( page.getByText( 'Stock Status:' ) ).toBeVisible();
+ await expect( page.getByText( 'In stock' ) ).toBeVisible();
+ await expect( page.getByText( 'On backorder' ) ).toBeVisible();
+ } );
+
+ test( 'With attribute filters applied it shows the correct active filters', async ( {
+ page,
+ templateCompiler,
+ } ) => {
+ await templateCompiler.compile( {
+ attributes: {
+ displayStyle: 'list',
+ },
+ } );
+
+ await page.goto(
+ `${ '/shop' }?filter_color=blue,gray&query_type_color=or`
+ );
+
+ await expect( page.getByText( 'Color:' ) ).toBeVisible();
+ await expect( page.getByText( 'Blue' ) ).toBeVisible();
+ await expect( page.getByText( 'Gray' ) ).toBeVisible();
+ } );
+
+ test( 'With price filters applied it shows the correct active filters', async ( {
+ page,
+ templateCompiler,
+ } ) => {
+ await templateCompiler.compile( {
+ attributes: {
+ displayStyle: 'list',
+ },
+ } );
+
+ await page.goto( `${ '/shop' }?min_price=17&max_price=71` );
+
+ await expect( page.getByText( 'Price:' ) ).toBeVisible();
+ await expect( page.getByText( 'Between $17 and $71' ) ).toBeVisible();
+ } );
+} );
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/attribute-filter.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/attribute-filter-editor.block_theme.spec.ts
similarity index 91%
rename from plugins/woocommerce-blocks/tests/e2e/tests/product-filters/attribute-filter.block_theme.spec.ts
rename to plugins/woocommerce-blocks/tests/e2e/tests/product-filters/attribute-filter-editor.block_theme.spec.ts
index 54220f04b92..77f9b13f090 100644
--- a/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/attribute-filter.block_theme.spec.ts
+++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/attribute-filter-editor.block_theme.spec.ts
@@ -48,9 +48,7 @@ test.describe( `${ blockData.name }`, () => {
} ) => {
await pageObject.addProductFiltersBlock( { cleanContent: true } );
- const block = editor.canvas
- .getByLabel( 'Block: Color (Experimental)' )
- .getByLabel( 'Block: Filter Options' );
+ const block = editor.canvas.getByLabel( 'Block: Color (Experimental)' );
await expect( block ).toBeVisible();
@@ -82,9 +80,7 @@ test.describe( `${ blockData.name }`, () => {
} ) => {
await pageObject.addProductFiltersBlock( { cleanContent: true } );
- const block = editor.canvas
- .getByLabel( 'Block: Color (Experimental)' )
- .getByLabel( 'Block: Filter Options' );
+ const block = editor.canvas.getByLabel( 'Block: Color (Experimental)' );
await expect( block ).toBeVisible();
@@ -112,9 +108,7 @@ test.describe( `${ blockData.name }`, () => {
} ) => {
await pageObject.addProductFiltersBlock( { cleanContent: true } );
- const block = editor.canvas
- .getByLabel( 'Block: Color (Experimental)' )
- .getByLabel( 'Block: Filter Options' );
+ const block = editor.canvas.getByLabel( 'Block: Color (Experimental)' );
await editor.openDocumentSettingsSidebar();
await block.click();
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/attribute-filter-frontend.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/attribute-filter-frontend.block_theme.spec.ts
new file mode 100644
index 00000000000..8f79924b291
--- /dev/null
+++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/attribute-filter-frontend.block_theme.spec.ts
@@ -0,0 +1,171 @@
+/**
+ * External dependencies
+ */
+import { TemplateCompiler, test as base, expect } from '@woocommerce/e2e-utils';
+
+const COLOR_ATTRIBUTE_VALUES = [ 'Blue', 'Gray', 'Green', 'Red', 'Yellow' ];
+const COLOR_ATTRIBUTES_WITH_COUNTS = [
+ 'Blue (4)',
+ 'Gray (2)',
+ 'Green (3)',
+ 'Red (4)',
+ 'Yellow (1)',
+];
+
+const test = base.extend< { templateCompiler: TemplateCompiler } >( {
+ templateCompiler: async ( { requestUtils }, use ) => {
+ const compiler = await requestUtils.createTemplateFromFile(
+ 'archive-product_attribute-filter'
+ );
+ await use( compiler );
+ },
+} );
+
+test.describe( 'woocommerce/product-filter-attribute - Frontend', () => {
+ test.describe( 'With default display style', () => {
+ test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
+ await requestUtils.activatePlugin(
+ 'woocommerce-blocks-test-enable-experimental-features'
+ );
+ await templateCompiler.compile( {
+ attributes: {
+ attributeId: 1,
+ },
+ } );
+ } );
+
+ test( 'clear button is not shown on initial page load', async ( {
+ page,
+ } ) => {
+ await page.goto( '/shop' );
+
+ const button = page.getByRole( 'button', { name: 'Clear' } );
+
+ await expect( button ).toBeHidden();
+ } );
+
+ test( 'renders a checkbox list with the available attribute filters', async ( {
+ page,
+ } ) => {
+ await page.goto( '/shop' );
+
+ const listItems = page
+ .getByLabel( 'Filter Options' )
+ .getByRole( 'listitem' );
+
+ await expect( listItems ).toHaveCount( 5 );
+
+ for ( let i = 0; i < COLOR_ATTRIBUTE_VALUES.length; i++ ) {
+ await expect( listItems.nth( i ) ).toHaveText(
+ COLOR_ATTRIBUTE_VALUES[ i ]
+ );
+ }
+ } );
+
+ test( 'filters the list of products by selecting an attribute', async ( {
+ page,
+ } ) => {
+ await page.goto( '/shop' );
+
+ const grayCheckbox = page.getByText( 'Gray' );
+ await grayCheckbox.click();
+
+ // wait for navigation
+ await page.waitForURL( /.*filter_color=gray.*/ );
+
+ const products = page.locator( '.wc-block-product' );
+
+ await expect( products ).toHaveCount( 2 );
+ } );
+
+ test( 'clear button appears after a filter is applied', async ( {
+ page,
+ } ) => {
+ await page.goto( '/shop' );
+
+ const grayCheckbox = page.getByText( 'Gray' );
+ await grayCheckbox.click();
+
+ // wait for navigation
+ await page.waitForURL( /.*filter_color=gray.*/ );
+
+ const button = page.getByRole( 'button', { name: 'Clear' } );
+
+ await expect( button ).toBeVisible();
+ } );
+
+ test( 'clear button hides after deselecting all filters', async ( {
+ page,
+ } ) => {
+ await page.goto( '/shop' );
+
+ const grayCheckbox = page.getByText( 'Gray' );
+ await grayCheckbox.click();
+
+ // wait for navigation
+ await page.waitForURL( /.*filter_color=gray.*/ );
+
+ await grayCheckbox.click();
+
+ const button = page.getByRole( 'button', { name: 'Clear' } );
+
+ await expect( button ).toBeHidden();
+ } );
+
+ test( 'filters are cleared after clear button is clicked', async ( {
+ page,
+ } ) => {
+ await page.goto( '/shop' );
+
+ const grayCheckbox = page.getByText( 'Gray' );
+ await grayCheckbox.click();
+
+ // wait for navigation
+ await page.waitForURL( /.*filter_color=gray.*/ );
+
+ const button = page.getByRole( 'button', { name: 'Clear' } );
+
+ await button.click();
+
+ COLOR_ATTRIBUTE_VALUES.map( async ( color ) => {
+ const element = page.locator(
+ `input[value="${ color.toLowerCase() }"]`
+ );
+
+ await expect( element ).not.toBeChecked();
+ } );
+ } );
+ } );
+
+ test.describe( 'With show counts enabled', () => {
+ test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
+ await requestUtils.activatePlugin(
+ 'woocommerce-blocks-test-enable-experimental-features'
+ );
+ await templateCompiler.compile( {
+ attributes: {
+ attributeId: 1,
+ showCounts: true,
+ },
+ } );
+ } );
+
+ test( 'Renders checkboxes with associated product counts', async ( {
+ page,
+ } ) => {
+ await page.goto( '/shop' );
+
+ const listItems = page
+ .getByLabel( 'Filter Options' )
+ .getByRole( 'listitem' );
+
+ await expect( listItems ).toHaveCount( 5 );
+
+ for ( let i = 0; i < COLOR_ATTRIBUTES_WITH_COUNTS.length; i++ ) {
+ await expect( listItems.nth( i ) ).toHaveText(
+ COLOR_ATTRIBUTES_WITH_COUNTS[ i ]
+ );
+ }
+ } );
+ } );
+} );
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/price-filter.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/price-filter-frontend.block_theme.spec.ts
similarity index 99%
rename from plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/price-filter.block_theme.spec.ts
rename to plugins/woocommerce-blocks/tests/e2e/tests/product-filters/price-filter-frontend.block_theme.spec.ts
index 796fd4af488..191c16f53f4 100644
--- a/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/price-filter.block_theme.spec.ts
+++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/price-filter-frontend.block_theme.spec.ts
@@ -12,7 +12,7 @@ const test = base.extend< { templateCompiler: TemplateCompiler } >( {
},
} );
-test.describe( 'Product Filter: Price Filter Block', () => {
+test.describe.skip( 'Product Filter: Price Filter Block', () => {
test.describe( 'frontend', () => {
test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
await requestUtils.activatePlugin(
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/product-filters-template-part.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/product-filters-template-part.block_theme.spec.ts
index d065baf73dc..3d16f0c9e89 100644
--- a/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/product-filters-template-part.block_theme.spec.ts
+++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/product-filters-template-part.block_theme.spec.ts
@@ -52,13 +52,7 @@ test.describe( 'Product Filters Template Part', () => {
const block = editor.canvas.getByLabel( `Block: ${ blockData.name }` );
await expect( block ).toBeVisible();
- const searchTerms = [
- 'Status (Experimental)',
- 'Price (Experimental)',
- 'Rating (Experimental)',
- 'Attribute (Experimental)',
- 'Active (Experimental)',
- ];
+ const searchTerms = [ 'Color (Experimental)', 'Active (Experimental)' ];
for ( const filter of searchTerms ) {
await editor.selectBlocks( blockData.selectors.editor.block );
@@ -78,13 +72,7 @@ test.describe( 'Product Filters Template Part', () => {
await searchResult.click();
- let _locator = `[aria-label="Block: ${ filter }"]`;
-
- // We need to treat the attributes filter different because
- // the variation of the block label depends on the product attribute.
- if ( filter === 'Attribute (Experimental)' ) {
- _locator = '.wp-block-woocommerce-product-filter-attribute';
- }
+ const _locator = `[aria-label="Block: ${ filter }"]`;
await expect( editor.canvas.locator( _locator ) ).toHaveCount( 2 );
}
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/product-filters.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/product-filters.block_theme.spec.ts
index 887dcf60e20..e6838d7c37d 100644
--- a/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/product-filters.block_theme.spec.ts
+++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/product-filters.block_theme.spec.ts
@@ -68,53 +68,17 @@ test.describe( `${ blockData.name }`, () => {
);
await expect( block ).toBeVisible();
- const activeHeading = block.getByText( 'Active', { exact: true } );
- const activeFilterBlock = block
- .getByLabel( 'Block: Filter Options' )
- .and(
- editor.canvas.locator(
- '[data-type="woocommerce/product-filter-active"]'
- )
- );
- await expect( activeHeading ).toBeVisible();
+ const activeFilterBlock = block.getByLabel(
+ 'Block: Active (Experimental)'
+ );
await expect( activeFilterBlock ).toBeVisible();
- const priceHeading = block.getByText( 'Price', {
- exact: true,
- } );
- const priceFilterBlock = block
- .getByLabel( 'Block: Filter Options' )
- .and(
- editor.canvas.locator(
- '[data-type="woocommerce/product-filter-price"]'
- )
- );
- await expect( priceHeading ).toBeVisible();
- await expect( priceFilterBlock ).toBeVisible();
-
- const statusHeading = block.getByText( 'Status', {
- exact: true,
- } );
- const statusFilterBlock = block
- .getByLabel( 'Block: Filter Options' )
- .and(
- editor.canvas.locator(
- '[data-type="woocommerce/product-filter-stock-status"]'
- )
- );
- await expect( statusHeading ).toBeVisible();
- await expect( statusFilterBlock ).toBeVisible();
-
const colorHeading = block.getByText( 'Color', {
exact: true,
} );
- const colorFilterBlock = block
- .getByLabel( 'Block: Filter Options' )
- .and(
- editor.canvas.locator(
- '[data-type="woocommerce/product-filter-attribute"]'
- )
- );
+ const colorFilterBlock = block.getByLabel(
+ 'Block: Color (Experimental)'
+ );
const expectedColorFilterOptions = [
'Blue',
'Green',
@@ -122,27 +86,11 @@ test.describe( `${ blockData.name }`, () => {
'Red',
'Yellow',
];
- const colorFilterOptions = (
- await colorFilterBlock.allInnerTexts()
- )[ 0 ].split( '\n' );
await expect( colorHeading ).toBeVisible();
await expect( colorFilterBlock ).toBeVisible();
- expect( colorFilterOptions ).toEqual(
- expect.arrayContaining( expectedColorFilterOptions )
- );
-
- const ratingHeading = block.getByText( 'Rating', {
- exact: true,
- } );
- const ratingFilterBlock = block
- .getByLabel( 'Block: Filter Options' )
- .and(
- editor.canvas.locator(
- '[data-type="woocommerce/product-filter-rating"]'
- )
- );
- await expect( ratingHeading ).toBeVisible();
- await expect( ratingFilterBlock ).toBeVisible();
+ for ( const option of expectedColorFilterOptions ) {
+ await expect( colorFilterBlock ).toContainText( option );
+ }
} );
test( 'should contain the correct inner block names in the list view', async ( {
@@ -181,25 +129,10 @@ test.describe( `${ blockData.name }`, () => {
);
await expect( productFilterActiveBlocksListItem ).toBeVisible();
- const productFilterPriceBlockListItem = listView.getByText(
- 'Price (Experimental)'
- );
- await expect( productFilterPriceBlockListItem ).toBeVisible();
-
- const productFilterStatusBlockListItem = listView.getByText(
- 'Status (Experimental)'
- );
- await expect( productFilterStatusBlockListItem ).toBeVisible();
-
const productFilterAttributeBlockListItem = listView.getByText(
'Color (Experimental)' // it must select the attribute with the highest product count
);
await expect( productFilterAttributeBlockListItem ).toBeVisible();
-
- const productFilterRatingBlockListItem = listView.getByText(
- 'Rating (Experimental)'
- );
- await expect( productFilterRatingBlockListItem ).toBeVisible();
} );
test( 'should display the correct inspector style controls', async ( {
@@ -370,7 +303,7 @@ test.describe( `${ blockData.name }`, () => {
).toHaveCSS( 'align-items', 'center' );
} );
- test( 'Layout > Orientation: changing option should update the preview', async ( {
+ test.skip( 'Layout > Orientation: changing option should update the preview', async ( {
editor,
pageObject,
} ) => {
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/rating-filter.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/rating-filter-frontend.block_theme.spec.ts
similarity index 97%
rename from plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/rating-filter.block_theme.spec.ts
rename to plugins/woocommerce-blocks/tests/e2e/tests/product-filters/rating-filter-frontend.block_theme.spec.ts
index 279fd391567..272aeb4966f 100644
--- a/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/rating-filter.block_theme.spec.ts
+++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/rating-filter-frontend.block_theme.spec.ts
@@ -12,7 +12,7 @@ const test = base.extend< { templateCompiler: TemplateCompiler } >( {
},
} );
-test.describe( 'Product Filter: Rating Filter Block', () => {
+test.describe.skip( 'Product Filter: Rating Filter Block', () => {
test.describe( 'frontend', () => {
test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
await requestUtils.activatePlugin(
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/stock-status.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/stock-status-frontend.block_theme.spec.ts
similarity index 98%
rename from plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/stock-status.block_theme.spec.ts
rename to plugins/woocommerce-blocks/tests/e2e/tests/product-filters/stock-status-frontend.block_theme.spec.ts
index c465257eea2..4012ea324af 100644
--- a/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/stock-status.block_theme.spec.ts
+++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-filters/stock-status-frontend.block_theme.spec.ts
@@ -12,7 +12,7 @@ const test = base.extend< { templateCompiler: TemplateCompiler } >( {
},
} );
-test.describe( 'Product Filter: Stock Status Block', () => {
+test.describe.skip( 'Product Filter: Stock Status Block', () => {
test.describe( 'With default display style', () => {
test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
await requestUtils.activatePlugin(
diff --git a/plugins/woocommerce/bin/composer/phpcs/composer.lock b/plugins/woocommerce/bin/composer/phpcs/composer.lock
index a42b55c51d6..d1c2a664f30 100644
--- a/plugins/woocommerce/bin/composer/phpcs/composer.lock
+++ b/plugins/woocommerce/bin/composer/phpcs/composer.lock
@@ -874,5 +874,5 @@
"platform-overrides": {
"php": "7.2"
},
- "plugin-api-version": "2.3.0"
+ "plugin-api-version": "2.6.0"
}
diff --git a/plugins/woocommerce/bin/composer/phpunit/composer.lock b/plugins/woocommerce/bin/composer/phpunit/composer.lock
index f0b64b9cbe4..89456bd9d80 100644
--- a/plugins/woocommerce/bin/composer/phpunit/composer.lock
+++ b/plugins/woocommerce/bin/composer/phpunit/composer.lock
@@ -315,35 +315,35 @@
},
{
"name": "phpunit/php-code-coverage",
- "version": "9.2.31",
+ "version": "9.2.32",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965"
+ "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965",
- "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5",
+ "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
- "nikic/php-parser": "^4.18 || ^5.0",
+ "nikic/php-parser": "^4.19.1 || ^5.1.0",
"php": ">=7.3",
- "phpunit/php-file-iterator": "^3.0.3",
- "phpunit/php-text-template": "^2.0.2",
- "sebastian/code-unit-reverse-lookup": "^2.0.2",
- "sebastian/complexity": "^2.0",
- "sebastian/environment": "^5.1.2",
- "sebastian/lines-of-code": "^1.0.3",
- "sebastian/version": "^3.0.1",
- "theseer/tokenizer": "^1.2.0"
+ "phpunit/php-file-iterator": "^3.0.6",
+ "phpunit/php-text-template": "^2.0.4",
+ "sebastian/code-unit-reverse-lookup": "^2.0.3",
+ "sebastian/complexity": "^2.0.3",
+ "sebastian/environment": "^5.1.5",
+ "sebastian/lines-of-code": "^1.0.4",
+ "sebastian/version": "^3.0.2",
+ "theseer/tokenizer": "^1.2.3"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^9.6"
},
"suggest": {
"ext-pcov": "PHP extension that provides line coverage",
@@ -352,7 +352,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.2-dev"
+ "dev-main": "9.2.x-dev"
}
},
"autoload": {
@@ -381,7 +381,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31"
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32"
},
"funding": [
{
@@ -389,7 +389,7 @@
"type": "github"
}
],
- "time": "2024-03-02T06:37:42+00:00"
+ "time": "2024-08-22T04:23:01+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -1759,5 +1759,5 @@
"platform-overrides": {
"php": "7.4"
},
- "plugin-api-version": "2.3.0"
+ "plugin-api-version": "2.6.0"
}
diff --git a/plugins/woocommerce/bin/composer/wp/composer.lock b/plugins/woocommerce/bin/composer/wp/composer.lock
index aadb4231f84..64558c071e9 100644
--- a/plugins/woocommerce/bin/composer/wp/composer.lock
+++ b/plugins/woocommerce/bin/composer/wp/composer.lock
@@ -635,5 +635,5 @@
"platform-overrides": {
"php": "7.0"
},
- "plugin-api-version": "2.3.0"
+ "plugin-api-version": "2.6.0"
}
diff --git a/plugins/woocommerce/changelog/51060-fix-21455-notice-plugin-install-products-without-subscription b/plugins/woocommerce/changelog/51060-fix-21455-notice-plugin-install-products-without-subscription
new file mode 100644
index 00000000000..8e432f67f7a
--- /dev/null
+++ b/plugins/woocommerce/changelog/51060-fix-21455-notice-plugin-install-products-without-subscription
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Add a new notice to the plugins list for products used without subscriptions reminding them to purchase.
\ No newline at end of file
diff --git a/plugins/woocommerce/changelog/51163-fix-21486-iam-discover-tracks b/plugins/woocommerce/changelog/51163-fix-21486-iam-discover-tracks
new file mode 100644
index 00000000000..f2459934217
--- /dev/null
+++ b/plugins/woocommerce/changelog/51163-fix-21486-iam-discover-tracks
@@ -0,0 +1,4 @@
+Significance: patch
+Type: tweak
+Comment: Fix missing Tracks event from the Extensions > Discover page
+
diff --git a/plugins/woocommerce/changelog/51164-fix-extra-search-request-in-my-subscriptions b/plugins/woocommerce/changelog/51164-fix-extra-search-request-in-my-subscriptions
new file mode 100644
index 00000000000..85c7d2e021f
--- /dev/null
+++ b/plugins/woocommerce/changelog/51164-fix-extra-search-request-in-my-subscriptions
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Prevent search request in the Extensions > My Subscriptions page
\ No newline at end of file
diff --git a/plugins/woocommerce/changelog/51187-update-21566-in-app-marketaplace-header-sticky b/plugins/woocommerce/changelog/51187-update-21566-in-app-marketaplace-header-sticky
new file mode 100644
index 00000000000..844123a8234
--- /dev/null
+++ b/plugins/woocommerce/changelog/51187-update-21566-in-app-marketaplace-header-sticky
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Make In-App Marketplace header sticky to improve discoverability.
\ No newline at end of file
diff --git a/plugins/woocommerce/changelog/51277-bugfix-46283 b/plugins/woocommerce/changelog/51277-bugfix-46283
new file mode 100644
index 00000000000..cc81d2fcd5b
--- /dev/null
+++ b/plugins/woocommerce/changelog/51277-bugfix-46283
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix a styling bug where the guest order confirmation email input was too wide.
\ No newline at end of file
diff --git a/plugins/woocommerce/changelog/51284-e2e-external-pressable-include-api-tests b/plugins/woocommerce/changelog/51284-e2e-external-pressable-include-api-tests
new file mode 100644
index 00000000000..0351b91c1d8
--- /dev/null
+++ b/plugins/woocommerce/changelog/51284-e2e-external-pressable-include-api-tests
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Include API tests into test suites for Pressable and WPCOM.
\ No newline at end of file
diff --git a/plugins/woocommerce/changelog/51288-update-wccom-21570-in-app-product-cards-padding b/plugins/woocommerce/changelog/51288-update-wccom-21570-in-app-product-cards-padding
new file mode 100644
index 00000000000..1f91bb228e1
--- /dev/null
+++ b/plugins/woocommerce/changelog/51288-update-wccom-21570-in-app-product-cards-padding
@@ -0,0 +1,4 @@
+Significance: patch
+Type: tweak
+
+Update product card content padding to 24px and add 0 margin bottom to product cards
\ No newline at end of file
diff --git a/plugins/woocommerce/changelog/51315-update-wccom-21574-in-app-marketplace-footer b/plugins/woocommerce/changelog/51315-update-wccom-21574-in-app-marketplace-footer
new file mode 100644
index 00000000000..7f77d1fe125
--- /dev/null
+++ b/plugins/woocommerce/changelog/51315-update-wccom-21574-in-app-marketplace-footer
@@ -0,0 +1,4 @@
+Significance: patch
+Type: tweak
+
+Update footer design, add one more element to footer content and remove `woo-marketplace` copy at footer bottom.
\ No newline at end of file
diff --git a/plugins/woocommerce/changelog/51332-fix-focus-style-select-checkout-block b/plugins/woocommerce/changelog/51332-fix-focus-style-select-checkout-block
new file mode 100644
index 00000000000..da9cb8df7b4
--- /dev/null
+++ b/plugins/woocommerce/changelog/51332-fix-focus-style-select-checkout-block
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Add focus styles to the Checkout block select field.
\ No newline at end of file
diff --git a/plugins/woocommerce/changelog/add-50832 b/plugins/woocommerce/changelog/add-50832
new file mode 100644
index 00000000000..e50768a52a4
--- /dev/null
+++ b/plugins/woocommerce/changelog/add-50832
@@ -0,0 +1,4 @@
+Significance: minor
+Type: add
+
+Track data for font and color pairings including 'Create your own' option in CYS
diff --git a/plugins/woocommerce/changelog/add-delayed-account-creation-block-50632 b/plugins/woocommerce/changelog/add-delayed-account-creation-block-50632
new file mode 100644
index 00000000000..ffd1d6f1c9b
--- /dev/null
+++ b/plugins/woocommerce/changelog/add-delayed-account-creation-block-50632
@@ -0,0 +1,4 @@
+Significance: minor
+Type: update
+
+Added experimental delayed order creation block.
diff --git a/plugins/woocommerce/changelog/dev-42582_use_one_rating_component b/plugins/woocommerce/changelog/dev-42582_use_one_rating_component
new file mode 100644
index 00000000000..e50c3ca32e2
--- /dev/null
+++ b/plugins/woocommerce/changelog/dev-42582_use_one_rating_component
@@ -0,0 +1,4 @@
+Significance: minor
+Type: dev
+
+[Enhancement] Abstract rating block #50810
diff --git a/plugins/woocommerce/changelog/dev-slow-tests b/plugins/woocommerce/changelog/dev-slow-tests
new file mode 100644
index 00000000000..d60c7d44a53
--- /dev/null
+++ b/plugins/woocommerce/changelog/dev-slow-tests
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Fix slow test for Reports
diff --git a/plugins/woocommerce/changelog/fix-50875-disable-client-side-nav-for-filters-in-pc-block b/plugins/woocommerce/changelog/fix-50875-disable-client-side-nav-for-filters-in-pc-block
new file mode 100644
index 00000000000..e219a09d7aa
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-50875-disable-client-side-nav-for-filters-in-pc-block
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Product Collection: Disable client-side nav if filter blocks are detected inside
diff --git a/plugins/woocommerce/changelog/fix-correct-language-in-frontend b/plugins/woocommerce/changelog/fix-correct-language-in-frontend
new file mode 100644
index 00000000000..00edcbc0400
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-correct-language-in-frontend
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Use the correct language in Cart/Checkout when the user language is different from the store.
diff --git a/plugins/woocommerce/changelog/fix-remote-logger-undefined-wp-current-user b/plugins/woocommerce/changelog/fix-remote-logger-undefined-wp-current-user
new file mode 100644
index 00000000000..be10eb2ec34
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-remote-logger-undefined-wp-current-user
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Adds a function_exists() check so that we don't add a secondary fatal in remote logging if wp_get_current_user does not exist yet
diff --git a/plugins/woocommerce/changelog/fix-remove-help-panel-user-meta b/plugins/woocommerce/changelog/fix-remove-help-panel-user-meta
new file mode 100644
index 00000000000..9b1882ac793
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-remove-help-panel-user-meta
@@ -0,0 +1,4 @@
+Significance: minor
+Type: fix
+
+Removed the leftover user meta from the help panel spotlight
diff --git a/plugins/woocommerce/changelog/fix-unsnooze-notes b/plugins/woocommerce/changelog/fix-unsnooze-notes
new file mode 100644
index 00000000000..a2f5b082011
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-unsnooze-notes
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix wc_admin_unsnooze_admin_notes events are being needlessly created
diff --git a/plugins/woocommerce/changelog/pr-51020 b/plugins/woocommerce/changelog/pr-51020
new file mode 100644
index 00000000000..ac4e7978690
--- /dev/null
+++ b/plugins/woocommerce/changelog/pr-51020
@@ -0,0 +1,4 @@
+Significance: patch
+Type: tweak
+
+Fix version number in a template
diff --git a/plugins/woocommerce/changelog/test-skip-failing-tests b/plugins/woocommerce/changelog/test-skip-failing-tests
new file mode 100644
index 00000000000..723af34edc0
--- /dev/null
+++ b/plugins/woocommerce/changelog/test-skip-failing-tests
@@ -0,0 +1,5 @@
+Significance: patch
+Type: dev
+Comment: It's a test skip for experimental feature, not worth explaining
+
+
diff --git a/plugins/woocommerce/changelog/try-new-improved-filter-blocks-structure b/plugins/woocommerce/changelog/try-new-improved-filter-blocks-structure
new file mode 100644
index 00000000000..61232016454
--- /dev/null
+++ b/plugins/woocommerce/changelog/try-new-improved-filter-blocks-structure
@@ -0,0 +1,5 @@
+Significance: patch
+Type: add
+Comment: Filter blocks: new and improve filter blocks structure.
+
+
diff --git a/plugins/woocommerce/changelog/tweak-gtin-structured-data b/plugins/woocommerce/changelog/tweak-gtin-structured-data
new file mode 100644
index 00000000000..69fc8c38c2e
--- /dev/null
+++ b/plugins/woocommerce/changelog/tweak-gtin-structured-data
@@ -0,0 +1,4 @@
+Significance: patch
+Type: tweak
+
+Validate and prepare GTIN in structured data
diff --git a/plugins/woocommerce/changelog/tweak-reenable-remote-logging-by-default b/plugins/woocommerce/changelog/tweak-reenable-remote-logging-by-default
new file mode 100644
index 00000000000..efcc6da22eb
--- /dev/null
+++ b/plugins/woocommerce/changelog/tweak-reenable-remote-logging-by-default
@@ -0,0 +1,4 @@
+Significance: patch
+Type: tweak
+
+Reenable remote logging feature by default
diff --git a/plugins/woocommerce/changelog/update-action-scheduler-3.8.2 b/plugins/woocommerce/changelog/update-action-scheduler-3.8.2
new file mode 100644
index 00000000000..8265892ca69
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-action-scheduler-3.8.2
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Update the Action Scheduler package to version 3.8.2
diff --git a/plugins/woocommerce/changelog/update-deprecate-banner-layout b/plugins/woocommerce/changelog/update-deprecate-banner-layout
new file mode 100644
index 00000000000..4af22693683
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-deprecate-banner-layout
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Deprecate unsupported Inbox note banner layout
diff --git a/plugins/woocommerce/changelog/update-dynamically-set-plugin-name b/plugins/woocommerce/changelog/update-dynamically-set-plugin-name
new file mode 100644
index 00000000000..079eb126b45
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-dynamically-set-plugin-name
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Dynamically set plugin_name when redirecting to Jetpack Auth from core profiler
diff --git a/plugins/woocommerce/changelog/update-remove-deprecated-rin-classes b/plugins/woocommerce/changelog/update-remove-deprecated-rin-classes
new file mode 100644
index 00000000000..2fc99a0873a
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-remove-deprecated-rin-classes
@@ -0,0 +1,4 @@
+Significance: minor
+Type: dev
+
+Remove deprecated RemoteInboxNotification classes
diff --git a/plugins/woocommerce/composer.json b/plugins/woocommerce/composer.json
index cdc8c4f1dc1..a42b16a87a7 100644
--- a/plugins/woocommerce/composer.json
+++ b/plugins/woocommerce/composer.json
@@ -34,7 +34,7 @@
"composer/installers": "^1.9",
"maxmind-db/reader": "^1.11",
"pelago/emogrifier": "^6.0",
- "woocommerce/action-scheduler": "3.8.1",
+ "woocommerce/action-scheduler": "3.8.2",
"woocommerce/blueprint": "*"
},
"require-dev": {
diff --git a/plugins/woocommerce/composer.lock b/plugins/woocommerce/composer.lock
index 12b5fc18ba9..230b3d42e91 100644
--- a/plugins/woocommerce/composer.lock
+++ b/plugins/woocommerce/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "15d426b01c8ba919cabdd7078845595e",
+ "content-hash": "e068848765b4c2df4244eac75f7ea46d",
"packages": [
{
"name": "automattic/jetpack-a8c-mc-stats",
@@ -1251,20 +1251,20 @@
},
{
"name": "woocommerce/action-scheduler",
- "version": "3.8.1",
+ "version": "3.8.2",
"source": {
"type": "git",
"url": "https://github.com/woocommerce/action-scheduler.git",
- "reference": "e331b534d7de10402d7545a0de50177b874c0779"
+ "reference": "2bc91d88fdbc2c07ab899cbb56b983e11e62cf69"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/woocommerce/action-scheduler/zipball/e331b534d7de10402d7545a0de50177b874c0779",
- "reference": "e331b534d7de10402d7545a0de50177b874c0779",
+ "url": "https://api.github.com/repos/woocommerce/action-scheduler/zipball/2bc91d88fdbc2c07ab899cbb56b983e11e62cf69",
+ "reference": "2bc91d88fdbc2c07ab899cbb56b983e11e62cf69",
"shasum": ""
},
"require": {
- "php": ">=5.6"
+ "php": ">=7.0"
},
"require-dev": {
"phpunit/phpunit": "^7.5",
@@ -1288,9 +1288,9 @@
"homepage": "https://actionscheduler.org/",
"support": {
"issues": "https://github.com/woocommerce/action-scheduler/issues",
- "source": "https://github.com/woocommerce/action-scheduler/tree/3.8.1"
+ "source": "https://github.com/woocommerce/action-scheduler/tree/3.8.2"
},
- "time": "2024-06-20T19:53:06+00:00"
+ "time": "2024-09-12T23:12:58+00:00"
},
{
"name": "woocommerce/blueprint",
@@ -4984,7 +4984,7 @@
},
{
"name": "woocommerce/monorepo-plugin",
- "version": "dev-tweak/bump-jetpack-connection",
+ "version": "dev-update/action-scheduler-3.8.2",
"dist": {
"type": "path",
"url": "../../packages/php/monorepo-plugin",
@@ -5143,5 +5143,5 @@
"platform-overrides": {
"php": "7.4"
},
- "plugin-api-version": "2.3.0"
+ "plugin-api-version": "2.6.0"
}
diff --git a/plugins/woocommerce/includes/admin/class-wc-admin-importers.php b/plugins/woocommerce/includes/admin/class-wc-admin-importers.php
index 6dfec075b89..3c16a0b07d9 100644
--- a/plugins/woocommerce/includes/admin/class-wc-admin-importers.php
+++ b/plugins/woocommerce/includes/admin/class-wc-admin-importers.php
@@ -215,114 +215,12 @@ class WC_Admin_Importers {
* Ajax callback for importing one batch of products from a CSV.
*/
public function do_ajax_product_import() {
- global $wpdb;
-
- check_ajax_referer( 'wc-product-import', 'security' );
-
- if ( ! $this->import_allowed() || ! isset( $_POST['file'] ) ) { // PHPCS: input var ok.
+ if ( ! $this->import_allowed() ) {
wp_send_json_error( array( 'message' => __( 'Insufficient privileges to import products.', 'woocommerce' ) ) );
}
include_once WC_ABSPATH . 'includes/admin/importers/class-wc-product-csv-importer-controller.php';
- include_once WC_ABSPATH . 'includes/import/class-wc-product-csv-importer.php';
-
- $file = wc_clean( wp_unslash( $_POST['file'] ) ); // PHPCS: input var ok.
- $params = array(
- 'delimiter' => ! empty( $_POST['delimiter'] ) ? wc_clean( wp_unslash( $_POST['delimiter'] ) ) : ',', // PHPCS: input var ok.
- 'start_pos' => isset( $_POST['position'] ) ? absint( $_POST['position'] ) : 0, // PHPCS: input var ok.
- 'mapping' => isset( $_POST['mapping'] ) ? (array) wc_clean( wp_unslash( $_POST['mapping'] ) ) : array(), // PHPCS: input var ok.
- 'update_existing' => isset( $_POST['update_existing'] ) ? (bool) $_POST['update_existing'] : false, // PHPCS: input var ok.
- 'character_encoding' => isset( $_POST['character_encoding'] ) ? wc_clean( wp_unslash( $_POST['character_encoding'] ) ) : '',
-
- /**
- * Batch size for the product import process.
- *
- * @param int $size Batch size.
- *
- * @since 3.1.0
- */
- 'lines' => apply_filters( 'woocommerce_product_import_batch_size', 30 ),
- 'parse' => true,
- );
-
- // Log failures.
- if ( 0 !== $params['start_pos'] ) {
- $error_log = array_filter( (array) get_user_option( 'product_import_error_log' ) );
- } else {
- $error_log = array();
- }
-
- $importer = WC_Product_CSV_Importer_Controller::get_importer( $file, $params );
- $results = $importer->import();
- $percent_complete = $importer->get_percent_complete();
- $error_log = array_merge( $error_log, $results['failed'], $results['skipped'] );
-
- update_user_option( get_current_user_id(), 'product_import_error_log', $error_log );
-
- if ( 100 === $percent_complete ) {
- // @codingStandardsIgnoreStart.
- $wpdb->delete( $wpdb->postmeta, array( 'meta_key' => '_original_id' ) );
- $wpdb->delete( $wpdb->posts, array(
- 'post_type' => 'product',
- 'post_status' => 'importing',
- ) );
- $wpdb->delete( $wpdb->posts, array(
- 'post_type' => 'product_variation',
- 'post_status' => 'importing',
- ) );
- // @codingStandardsIgnoreEnd.
-
- // Clean up orphaned data.
- $wpdb->query(
- "
- DELETE {$wpdb->posts}.* FROM {$wpdb->posts}
- LEFT JOIN {$wpdb->posts} wp ON wp.ID = {$wpdb->posts}.post_parent
- WHERE wp.ID IS NULL AND {$wpdb->posts}.post_type = 'product_variation'
- "
- );
- $wpdb->query(
- "
- DELETE {$wpdb->postmeta}.* FROM {$wpdb->postmeta}
- LEFT JOIN {$wpdb->posts} wp ON wp.ID = {$wpdb->postmeta}.post_id
- WHERE wp.ID IS NULL
- "
- );
- // @codingStandardsIgnoreStart.
- $wpdb->query( "
- DELETE tr.* FROM {$wpdb->term_relationships} tr
- LEFT JOIN {$wpdb->posts} wp ON wp.ID = tr.object_id
- LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
- WHERE wp.ID IS NULL
- AND tt.taxonomy IN ( '" . implode( "','", array_map( 'esc_sql', get_object_taxonomies( 'product' ) ) ) . "' )
- " );
- // @codingStandardsIgnoreEnd.
-
- // Send success.
- wp_send_json_success(
- array(
- 'position' => 'done',
- 'percentage' => 100,
- 'url' => add_query_arg( array( '_wpnonce' => wp_create_nonce( 'woocommerce-csv-importer' ) ), admin_url( 'edit.php?post_type=product&page=product_importer&step=done' ) ),
- 'imported' => is_countable( $results['imported'] ) ? count( $results['imported'] ) : 0,
- 'imported_variations' => is_countable( $results['imported_variations'] ) ? count( $results['imported_variations'] ) : 0,
- 'failed' => is_countable( $results['failed'] ) ? count( $results['failed'] ) : 0,
- 'updated' => is_countable( $results['updated'] ) ? count( $results['updated'] ) : 0,
- 'skipped' => is_countable( $results['skipped'] ) ? count( $results['skipped'] ) : 0,
- )
- );
- } else {
- wp_send_json_success(
- array(
- 'position' => $importer->get_file_position(),
- 'percentage' => $percent_complete,
- 'imported' => is_countable( $results['imported'] ) ? count( $results['imported'] ) : 0,
- 'imported_variations' => is_countable( $results['imported_variations'] ) ? count( $results['imported_variations'] ) : 0,
- 'failed' => is_countable( $results['failed'] ) ? count( $results['failed'] ) : 0,
- 'updated' => is_countable( $results['updated'] ) ? count( $results['updated'] ) : 0,
- 'skipped' => is_countable( $results['skipped'] ) ? count( $results['skipped'] ) : 0,
- )
- );
- }
+ WC_Product_CSV_Importer_Controller::dispatch_ajax();
}
/**
diff --git a/plugins/woocommerce/includes/admin/helper/class-wc-helper-admin.php b/plugins/woocommerce/includes/admin/helper/class-wc-helper-admin.php
index 96cc160502c..15ed3ffe3bb 100644
--- a/plugins/woocommerce/includes/admin/helper/class-wc-helper-admin.php
+++ b/plugins/woocommerce/includes/admin/helper/class-wc-helper-admin.php
@@ -85,6 +85,7 @@ class WC_Helper_Admin {
if ( WC_Helper::is_site_connected() ) {
$settings['wccomHelper']['subscription_expired_notice'] = PluginsHelper::get_expired_subscription_notice( false );
$settings['wccomHelper']['subscription_expiring_notice'] = PluginsHelper::get_expiring_subscription_notice( false );
+ $settings['wccomHelper']['subscription_missing_notice'] = PluginsHelper::get_missing_subscription_notice();
}
return $settings;
diff --git a/plugins/woocommerce/includes/admin/helper/class-wc-helper-updater.php b/plugins/woocommerce/includes/admin/helper/class-wc-helper-updater.php
index 02eeb89e0aa..086071717d4 100644
--- a/plugins/woocommerce/includes/admin/helper/class-wc-helper-updater.php
+++ b/plugins/woocommerce/includes/admin/helper/class-wc-helper-updater.php
@@ -40,11 +40,13 @@ class WC_Helper_Updater {
}
if ( WC_Helper::is_site_connected() ) {
add_action( 'load-plugins.php', array( __CLASS__, 'setup_message_for_expired_and_expiring_subscriptions' ), 11 );
+ add_action( 'load-plugins.php', array( __CLASS__, 'setup_message_for_plugins_without_subscription' ), 11 );
}
}
/**
* Add the hook for modifying default WPCore update notices on the plugins management page.
+ * This is for plugins with expired or expiring subscriptions.
*/
public static function setup_message_for_expired_and_expiring_subscriptions() {
foreach ( WC_Helper::get_local_woo_plugins() as $plugin ) {
@@ -52,6 +54,16 @@ class WC_Helper_Updater {
}
}
+ /**
+ * Add the hook for modifying default WPCore update notices on the plugins management page.
+ * This is for plugins without a subscription.
+ */
+ public static function setup_message_for_plugins_without_subscription() {
+ foreach ( WC_Helper::get_local_woo_plugins() as $plugin ) {
+ add_action( 'in_plugin_update_message-' . $plugin['_filename'], array( __CLASS__, 'display_notice_for_plugins_without_subscription' ), 10, 2 );
+ }
+ }
+
/**
* Runs in a cron thread, or in a visitor thread if triggered
* by _maybe_update_plugins(), or in an auto-update thread.
@@ -294,10 +306,11 @@ class WC_Helper_Updater {
$renew_link = add_query_arg(
array(
+ 'add-to-cart' => $product_id,
'utm_source' => 'pu',
'utm_campaign' => 'pu_plugin_screen_renew',
),
- PluginsHelper::WOO_SUBSCRIPTION_PAGE_URL
+ PluginsHelper::WOO_CART_PAGE_URL
);
/* translators: 1: Product regular price */
@@ -340,6 +353,52 @@ class WC_Helper_Updater {
}
}
+ /**
+ * Runs on in_plugin_update_message-{file-name}, show a message if plugin is without a subscription.
+ * Only Woo local plugins are passed to this function.
+ *
+ * @see setup_message_for_plugins_without_subscription
+ * @param object $plugin_data An array of plugin metadata.
+ * @param object $response An object of metadata about the available plugin update.
+ *
+ * @return void.
+ */
+ public static function display_notice_for_plugins_without_subscription( $plugin_data, $response ) {
+ // Extract product ID from the response.
+ $product_id = preg_replace( '/[^0-9]/', '', $response->id );
+
+ if ( WC_Helper::has_product_subscription( $product_id ) ) {
+ return;
+ }
+
+ // Prepare the expiry notice based on subscription status.
+ $purchase_link = add_query_arg(
+ array(
+ 'add-to-cart' => $product_id,
+ 'utm_source' => 'pu',
+ 'utm_campaign' => 'pu_plugin_screen_purchase',
+ ),
+ PluginsHelper::WOO_CART_PAGE_URL,
+ );
+
+ $notice = sprintf(
+ /* translators: 1: URL to My Subscriptions page */
+ __( ' You don\'t have a subscription,
to update.', 'woocommerce' ),
+ esc_url( $purchase_link ),
+ );
+
+ // Display the expiry notice.
+ echo wp_kses(
+ $notice,
+ array(
+ 'a' => array(
+ 'href' => array(),
+ 'class' => array(),
+ ),
+ )
+ );
+ }
+
/**
* Get update data for all plugins.
*
diff --git a/plugins/woocommerce/includes/admin/importers/class-wc-product-csv-importer-controller.php b/plugins/woocommerce/includes/admin/importers/class-wc-product-csv-importer-controller.php
index e5fac1cecb9..cadf53a7bc5 100644
--- a/plugins/woocommerce/includes/admin/importers/class-wc-product-csv-importer-controller.php
+++ b/plugins/woocommerce/includes/admin/importers/class-wc-product-csv-importer-controller.php
@@ -103,6 +103,56 @@ class WC_Product_CSV_Importer_Controller {
return wc_is_file_valid_csv( $file, $check_path );
}
+ /**
+ * Runs before controller actions to check that the file used during the import is valid.
+ *
+ * @since 9.3.0
+ *
+ * @param string $path Path to test.
+ *
+ * @throws \Exception When file validation fails.
+ */
+ protected static function check_file_path( string $path ): void {
+ $is_valid_file = false;
+
+ if ( ! empty( $path ) ) {
+ $path = realpath( $path );
+ $is_valid_file = false !== $path;
+ }
+
+ // File must be readable.
+ $is_valid_file = $is_valid_file && is_readable( $path );
+
+ // Check that file is within an allowed location.
+ if ( $is_valid_file ) {
+ $in_valid_location = false;
+ $valid_locations = array();
+ $valid_locations[] = ABSPATH;
+
+ $upload_dir = wp_get_upload_dir();
+ if ( false === $upload_dir['error'] ) {
+ $valid_locations[] = $upload_dir['basedir'];
+ }
+
+ foreach ( $valid_locations as $valid_location ) {
+ if ( 0 === stripos( $path, trailingslashit( realpath( $valid_location ) ) ) ) {
+ $in_valid_location = true;
+ break;
+ }
+ }
+
+ $is_valid_file = $in_valid_location;
+ }
+
+ if ( ! $is_valid_file ) {
+ throw new \Exception( esc_html__( 'File path provided for import is invalid.', 'woocommerce' ) );
+ }
+
+ if ( ! self::is_file_valid_csv( $path ) ) {
+ throw new \Exception( esc_html__( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) );
+ }
+ }
+
/**
* Get all the valid filetypes for a CSV file.
*
@@ -263,17 +313,151 @@ class WC_Product_CSV_Importer_Controller {
* Dispatch current step and show correct view.
*/
public function dispatch() {
- // phpcs:ignore WordPress.Security.NonceVerification.Missing
- if ( ! empty( $_POST['save_step'] ) && ! empty( $this->steps[ $this->step ]['handler'] ) ) {
- call_user_func( $this->steps[ $this->step ]['handler'], $this );
+ $output = '';
+
+ try {
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
+ if ( ! empty( $_POST['save_step'] ) && ! empty( $this->steps[ $this->step ]['handler'] ) ) {
+ if ( is_callable( $this->steps[ $this->step ]['handler'] ) ) {
+ call_user_func( $this->steps[ $this->step ]['handler'], $this );
+ }
+ }
+
+ ob_start();
+
+ if ( is_callable( $this->steps[ $this->step ]['view'] ) ) {
+ call_user_func( $this->steps[ $this->step ]['view'], $this );
+ }
+
+ $output = ob_get_clean();
+ } catch ( \Exception $e ) {
+ $this->add_error( $e->getMessage() );
}
+
$this->output_header();
$this->output_steps();
$this->output_errors();
- call_user_func( $this->steps[ $this->step ]['view'], $this );
+ echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output is HTML we've generated ourselves.
$this->output_footer();
}
+ /**
+ * Processes AJAX requests related to a product CSV import.
+ *
+ * @since 9.3.0
+ */
+ public static function dispatch_ajax() {
+ global $wpdb;
+
+ check_ajax_referer( 'wc-product-import', 'security' );
+
+ try {
+ $file = wc_clean( wp_unslash( $_POST['file'] ?? '' ) ); // PHPCS: input var ok.
+ self::check_file_path( $file );
+
+ $params = array(
+ 'delimiter' => ! empty( $_POST['delimiter'] ) ? wc_clean( wp_unslash( $_POST['delimiter'] ) ) : ',', // PHPCS: input var ok.
+ 'start_pos' => isset( $_POST['position'] ) ? absint( $_POST['position'] ) : 0, // PHPCS: input var ok.
+ 'mapping' => isset( $_POST['mapping'] ) ? (array) wc_clean( wp_unslash( $_POST['mapping'] ) ) : array(), // PHPCS: input var ok.
+ 'update_existing' => isset( $_POST['update_existing'] ) ? (bool) $_POST['update_existing'] : false, // PHPCS: input var ok.
+ 'character_encoding' => isset( $_POST['character_encoding'] ) ? wc_clean( wp_unslash( $_POST['character_encoding'] ) ) : '',
+
+ /**
+ * Batch size for the product import process.
+ *
+ * @param int $size Batch size.
+ *
+ * @since 3.1.0
+ */
+ 'lines' => apply_filters( 'woocommerce_product_import_batch_size', 1 ),
+ 'parse' => true,
+ );
+
+ // Log failures.
+ if ( 0 !== $params['start_pos'] ) {
+ $error_log = array_filter( (array) get_user_option( 'product_import_error_log' ) );
+ } else {
+ $error_log = array();
+ }
+
+ include_once WC_ABSPATH . 'includes/import/class-wc-product-csv-importer.php';
+
+ $importer = self::get_importer( $file, $params );
+ $results = $importer->import();
+ $percent_complete = $importer->get_percent_complete();
+ $error_log = array_merge( $error_log, $results['failed'], $results['skipped'] );
+
+ update_user_option( get_current_user_id(), 'product_import_error_log', $error_log );
+
+ if ( 100 === $percent_complete ) {
+ // @codingStandardsIgnoreStart.
+ $wpdb->delete( $wpdb->postmeta, array( 'meta_key' => '_original_id' ) );
+ $wpdb->delete( $wpdb->posts, array(
+ 'post_type' => 'product',
+ 'post_status' => 'importing',
+ ) );
+ $wpdb->delete( $wpdb->posts, array(
+ 'post_type' => 'product_variation',
+ 'post_status' => 'importing',
+ ) );
+ // @codingStandardsIgnoreEnd.
+
+ // Clean up orphaned data.
+ $wpdb->query(
+ "
+ DELETE {$wpdb->posts}.* FROM {$wpdb->posts}
+ LEFT JOIN {$wpdb->posts} wp ON wp.ID = {$wpdb->posts}.post_parent
+ WHERE wp.ID IS NULL AND {$wpdb->posts}.post_type = 'product_variation'
+ "
+ );
+ $wpdb->query(
+ "
+ DELETE {$wpdb->postmeta}.* FROM {$wpdb->postmeta}
+ LEFT JOIN {$wpdb->posts} wp ON wp.ID = {$wpdb->postmeta}.post_id
+ WHERE wp.ID IS NULL
+ "
+ );
+ // @codingStandardsIgnoreStart.
+ $wpdb->query( "
+ DELETE tr.* FROM {$wpdb->term_relationships} tr
+ LEFT JOIN {$wpdb->posts} wp ON wp.ID = tr.object_id
+ LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
+ WHERE wp.ID IS NULL
+ AND tt.taxonomy IN ( '" . implode( "','", array_map( 'esc_sql', get_object_taxonomies( 'product' ) ) ) . "' )
+ " );
+ // @codingStandardsIgnoreEnd.
+
+ // Send success.
+ wp_send_json_success(
+ array(
+ 'position' => 'done',
+ 'percentage' => 100,
+ 'url' => add_query_arg( array( '_wpnonce' => wp_create_nonce( 'woocommerce-csv-importer' ) ), admin_url( 'edit.php?post_type=product&page=product_importer&step=done' ) ),
+ 'imported' => is_countable( $results['imported'] ) ? count( $results['imported'] ) : 0,
+ 'imported_variations' => is_countable( $results['imported_variations'] ) ? count( $results['imported_variations'] ) : 0,
+ 'failed' => is_countable( $results['failed'] ) ? count( $results['failed'] ) : 0,
+ 'updated' => is_countable( $results['updated'] ) ? count( $results['updated'] ) : 0,
+ 'skipped' => is_countable( $results['skipped'] ) ? count( $results['skipped'] ) : 0,
+ )
+ );
+ } else {
+ wp_send_json_success(
+ array(
+ 'position' => $importer->get_file_position(),
+ 'percentage' => $percent_complete,
+ 'imported' => is_countable( $results['imported'] ) ? count( $results['imported'] ) : 0,
+ 'imported_variations' => is_countable( $results['imported_variations'] ) ? count( $results['imported_variations'] ) : 0,
+ 'failed' => is_countable( $results['failed'] ) ? count( $results['failed'] ) : 0,
+ 'updated' => is_countable( $results['updated'] ) ? count( $results['updated'] ) : 0,
+ 'skipped' => is_countable( $results['skipped'] ) ? count( $results['skipped'] ) : 0,
+ )
+ );
+ }
+ } catch ( \Exception $e ) {
+ wp_send_json_error( array( 'message' => $e->getMessage() ) );
+ }
+ }
+
/**
* Output information about the uploading process.
*/
@@ -314,60 +498,20 @@ class WC_Product_CSV_Importer_Controller {
// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce already verified in WC_Product_CSV_Importer_Controller::upload_form_handler()
$file_url = isset( $_POST['file_url'] ) ? wc_clean( wp_unslash( $_POST['file_url'] ) ) : '';
- if ( empty( $file_url ) ) {
- if ( ! isset( $_FILES['import'] ) ) {
- return new WP_Error( 'woocommerce_product_csv_importer_upload_file_empty', __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.', 'woocommerce' ) );
+ try {
+ if ( ! empty( $file_url ) ) {
+ $path = ABSPATH . $file_url;
+ self::check_file_path( $path );
+ } else {
+ $csv_import_util = wc_get_container()->get( Automattic\WooCommerce\Internal\Admin\ImportExport\CSVUploadHelper::class );
+ $upload = $csv_import_util->handle_csv_upload( 'product', 'import', self::get_valid_csv_filetypes() );
+ $path = $upload['file'];
}
- // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
- if ( ! self::is_file_valid_csv( wc_clean( wp_unslash( $_FILES['import']['name'] ) ), false ) ) {
- return new WP_Error( 'woocommerce_product_csv_importer_upload_file_invalid', __( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) );
- }
-
- $overrides = array(
- 'test_form' => false,
- 'mimes' => self::get_valid_csv_filetypes(),
- );
- $import = $_FILES['import']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash
- $upload = wp_handle_upload( $import, $overrides );
-
- if ( isset( $upload['error'] ) ) {
- return new WP_Error( 'woocommerce_product_csv_importer_upload_error', $upload['error'] );
- }
-
- // Construct the object array.
- $object = array(
- 'post_title' => basename( $upload['file'] ),
- 'post_content' => $upload['url'],
- 'post_mime_type' => $upload['type'],
- 'guid' => $upload['url'],
- 'context' => 'import',
- 'post_status' => 'private',
- );
-
- // Save the data.
- $id = wp_insert_attachment( $object, $upload['file'] );
-
- /*
- * Schedule a cleanup for one day from now in case of failed
- * import or missing wp_import_cleanup() call.
- */
- wp_schedule_single_event( time() + DAY_IN_SECONDS, 'importer_scheduled_cleanup', array( $id ) );
-
- return $upload['file'];
- } elseif (
- ( 0 === stripos( realpath( ABSPATH . $file_url ), ABSPATH ) ) &&
- file_exists( ABSPATH . $file_url )
- ) {
- if ( ! self::is_file_valid_csv( ABSPATH . $file_url ) ) {
- return new WP_Error( 'woocommerce_product_csv_importer_upload_file_invalid', __( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) );
- }
-
- return ABSPATH . $file_url;
+ return $path;
+ } catch ( \Exception $e ) {
+ return new \WP_Error( 'woocommerce_product_csv_importer_upload_invalid_file', $e->getMessage() );
}
- // phpcs:enable
-
- return new WP_Error( 'woocommerce_product_csv_importer_upload_invalid_file', __( 'Please upload or provide the link to a valid CSV file.', 'woocommerce' ) );
}
/**
@@ -375,6 +519,8 @@ class WC_Product_CSV_Importer_Controller {
*/
protected function mapping_form() {
check_admin_referer( 'woocommerce-csv-importer' );
+ self::check_file_path( $this->file );
+
$args = array(
'lines' => 1,
'delimiter' => $this->delimiter,
@@ -412,18 +558,7 @@ class WC_Product_CSV_Importer_Controller {
// Displaying this page triggers Ajax action to run the import with a valid nonce,
// therefore this page needs to be nonce protected as well.
check_admin_referer( 'woocommerce-csv-importer' );
-
- if ( ! self::is_file_valid_csv( $this->file ) ) {
- $this->add_error( __( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) );
- $this->output_errors();
- return;
- }
-
- if ( ! is_file( $this->file ) ) {
- $this->add_error( __( 'The file does not exist, please try again.', 'woocommerce' ) );
- $this->output_errors();
- return;
- }
+ self::check_file_path( $this->file );
if ( ! empty( $_POST['map_from'] ) && ! empty( $_POST['map_to'] ) ) {
$mapping_from = wc_clean( wp_unslash( $_POST['map_from'] ) );
diff --git a/plugins/woocommerce/includes/class-wc-install.php b/plugins/woocommerce/includes/class-wc-install.php
index 002844d49c4..ec17ff0c71c 100644
--- a/plugins/woocommerce/includes/class-wc-install.php
+++ b/plugins/woocommerce/includes/class-wc-install.php
@@ -268,6 +268,7 @@ class WC_Install {
),
'9.4.0' => array(
'wc_update_940_add_phone_to_order_address_fts_index',
+ 'wc_update_940_remove_help_panel_highlight_shown',
),
);
diff --git a/plugins/woocommerce/includes/class-wc-structured-data.php b/plugins/woocommerce/includes/class-wc-structured-data.php
index 98acb513224..12f1861ad9e 100644
--- a/plugins/woocommerce/includes/class-wc-structured-data.php
+++ b/plugins/woocommerce/includes/class-wc-structured-data.php
@@ -214,9 +214,9 @@ class WC_Structured_Data {
$markup['sku'] = $product->get_id();
}
- // Add GTIN only if it's a valid number.
- $gtin = $product->get_global_unique_id();
- if ( $gtin && is_numeric( $gtin ) ) {
+ // Prepare GTIN and load it if it's valid.
+ $gtin = $this->prepare_gtin( $product->get_global_unique_id() );
+ if ( $this->is_valid_gtin( $gtin ) ) {
$markup['gtin'] = $gtin;
}
@@ -577,4 +577,30 @@ class WC_Structured_Data {
$this->set_data( apply_filters( 'woocommerce_structured_data_order', $markup, $sent_to_admin, $order ), true );
}
+
+ /**
+ * Check if a GTIN is valid.
+ * A valid GTIN is a string containing 8,12,13 or 14 digits.
+ *
+ * @see https://schema.org/gtin
+ * @param string $gtin The GTIN to check.
+ * @return bool True if valid. False otherwise.
+ */
+ public function is_valid_gtin( $gtin ) {
+ return is_string( $gtin ) && preg_match( '/^(\d{8}|\d{12,14})$/', $gtin );
+ }
+
+ /**
+ * Prepare a GTIN input removing everything except numbers.
+ *
+ * @param string $gtin The GTIN to prepare.
+ * @return string Empty string if no GTIN is provided or the string with the replacements.
+ */
+ public function prepare_gtin( $gtin ) {
+ if ( ! $gtin || ! is_string( $gtin ) ) {
+ return '';
+ }
+
+ return preg_replace( '/[^0-9]/', '', $gtin );
+ }
}
diff --git a/plugins/woocommerce/includes/wc-update-functions.php b/plugins/woocommerce/includes/wc-update-functions.php
index e4f880a2a76..79c42ac89fe 100644
--- a/plugins/woocommerce/includes/wc-update-functions.php
+++ b/plugins/woocommerce/includes/wc-update-functions.php
@@ -2872,3 +2872,51 @@ function wc_update_940_add_phone_to_order_address_fts_index(): void {
}
}
}
+
+/**
+ * Remove user meta associated with the key 'woocommerce_admin_help_panel_highlight_shown'.
+ *
+ * This key is no longer needed since the help panel spotlight tour has been removed.
+ *
+ * @return void
+ */
+function wc_update_940_remove_help_panel_highlight_shown() {
+ global $wpdb;
+
+ $meta_key = 'woocommerce_admin_help_panel_highlight_shown';
+
+ $deletions = $wpdb->query(
+ $wpdb->prepare(
+ "DELETE FROM $wpdb->usermeta WHERE meta_key = %s",
+ $meta_key
+ )
+ );
+
+ // Get the WooCommerce logger to track the results of the deletion.
+ $logger = wc_get_logger();
+
+ if ( null === $logger ) {
+ return;
+ }
+
+ if ( false === $deletions ) {
+ $logger->notice(
+ 'During the update to 9.4.0, WooCommerce attempted to remove user meta with the key "woocommerce_admin_help_panel_highlight_shown", but was unable to do so.',
+ array(
+ 'source' => 'wc-updater',
+ )
+ );
+ } else {
+ $logger->info(
+ sprintf(
+ 1 === $deletions
+ ? 'During the update to 9.4.0, WooCommerce removed %d user meta row associated with the meta key "woocommerce_admin_help_panel_highlight_shown".'
+ : 'During the update to 9.4.0, WooCommerce removed %d user meta rows associated with the meta key "woocommerce_admin_help_panel_highlight_shown".',
+ number_format_i18n( $deletions )
+ ),
+ array(
+ 'source' => 'wc-updater',
+ )
+ );
+ }
+}
diff --git a/plugins/woocommerce/package.json b/plugins/woocommerce/package.json
index a01cd250ffc..8ec41d6cfda 100644
--- a/plugins/woocommerce/package.json
+++ b/plugins/woocommerce/package.json
@@ -556,7 +556,7 @@
"on-demand"
],
"report": {
- "resultsBlobName": "default-pressable-core-e2e",
+ "resultsBlobName": "default-pressable-core-e2e-and-api",
"resultsPath": "tests/e2e-pw/test-results",
"allure": true
}
@@ -572,7 +572,7 @@
"on-demand"
],
"report": {
- "resultsBlobName": "default-wpcom-core-e2e",
+ "resultsBlobName": "default-wpcom-core-e2e-and-api",
"resultsPath": "tests/e2e-pw/test-results",
"allure": true
}
@@ -681,7 +681,6 @@
"node_modules/@woocommerce/e2e-core-tests/CHANGELOG.md",
"node_modules/@woocommerce/api/dist/",
"node_modules/@woocommerce/admin-e2e-tests/build",
- "node_modules/@woocommerce/classic-assets/build",
"node_modules/@woocommerce/block-library/build",
"node_modules/@woocommerce/block-library/blocks.ini",
"node_modules/@woocommerce/admin-library/build",
diff --git a/plugins/woocommerce/src/Admin/Notes/Note.php b/plugins/woocommerce/src/Admin/Notes/Note.php
index de8cde59dc7..9058906d87b 100644
--- a/plugins/woocommerce/src/Admin/Notes/Note.php
+++ b/plugins/woocommerce/src/Admin/Notes/Note.php
@@ -534,7 +534,7 @@ class Note extends \WC_Data {
$this->error( 'admin_note_invalid_data', __( 'The admin note date prop cannot be empty.', 'woocommerce' ) );
}
- if ( is_string( $date ) ) {
+ if ( is_string( $date ) && ! is_numeric( $date ) ) {
$date = wc_string_to_timestamp( $date );
}
$this->set_date_prop( 'date_created', $date );
@@ -546,7 +546,7 @@ class Note extends \WC_Data {
* @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if there is no date.
*/
public function set_date_reminder( $date ) {
- if ( is_string( $date ) ) {
+ if ( is_string( $date ) && ! is_numeric( $date ) ) {
$date = wc_string_to_timestamp( $date );
}
$this->set_date_prop( 'date_reminder', $date );
@@ -579,6 +579,11 @@ class Note extends \WC_Data {
$layout = 'plain';
}
$valid_layouts = array( 'banner', 'plain', 'thumbnail' );
+
+ if ( 'banner' === $layout ) {
+ wc_deprecated_argument( 'Note::set_layout', '9.4.0', 'The "banner" layout is deprecated. Please use "thumbnail" instead to display a image.' );
+ }
+
if ( in_array( $layout, $valid_layouts, true ) ) {
$this->set_prop( 'layout', $layout );
} else {
diff --git a/plugins/woocommerce/src/Admin/Notes/Notes.php b/plugins/woocommerce/src/Admin/Notes/Notes.php
index 138a49cafd6..8a7c6ccd2c2 100644
--- a/plugins/woocommerce/src/Admin/Notes/Notes.php
+++ b/plugins/woocommerce/src/Admin/Notes/Notes.php
@@ -24,6 +24,7 @@ class Notes {
add_action( 'admin_init', array( __CLASS__, 'schedule_unsnooze_notes' ) );
add_action( 'admin_init', array( __CLASS__, 'possibly_delete_survey_notes' ) );
add_action( 'update_option_woocommerce_show_marketplace_suggestions', array( __CLASS__, 'possibly_delete_marketing_notes' ), 10, 2 );
+ add_action( self::UNSNOOZE_HOOK, array( __CLASS__, 'unsnooze_notes' ) );
}
/**
@@ -406,7 +407,6 @@ class Notes {
wp_set_current_user( $user_id );
self::record_tracks_event_without_cookies( $event_name, $params );
wp_set_current_user( $current_user_id );
-
}
/**
diff --git a/plugins/woocommerce/src/Admin/PluginsHelper.php b/plugins/woocommerce/src/Admin/PluginsHelper.php
index efcf9152f9e..1900bfdf493 100644
--- a/plugins/woocommerce/src/Admin/PluginsHelper.php
+++ b/plugins/woocommerce/src/Admin/PluginsHelper.php
@@ -33,17 +33,24 @@ if ( ! function_exists( 'get_plugins' ) ) {
class PluginsHelper {
/**
- * Indicates whether the expiration notice for subscriptions can be displayed.
+ * Subscription notices in Woo screens are shown in clear priority order, first
+ * expired, and if those don't exist, expiring, and finally if none of those exist,
+ * then missing. This keeps track of whether we can show the next set of notices.
*
* @var bool
*/
- public static $can_show_expiring_subs_notice = true;
+ public static $subscription_usage_notices_already_shown = false;
/**
* The URL for the WooCommerce subscription page.
*/
const WOO_SUBSCRIPTION_PAGE_URL = 'https://woocommerce.com/my-account/my-subscriptions/';
+ /**
+ * The URL for the WooCommerce.com cart page.
+ */
+ const WOO_CART_PAGE_URL = 'https://woocommerce.com/cart/';
+
/**
* The URL for the WooCommerce.com add payment method page.
*/
@@ -59,6 +66,11 @@ class PluginsHelper {
*/
const DISMISS_EXPIRING_SUBS_NOTICE = 'woo_subscription_expiring_notice_dismiss';
+ /**
+ * Meta key for dismissing missing subscription notices
+ */
+ const DISMISS_MISSING_SUBS_NOTICE = 'woo_subscription_missing_notice_dismiss';
+
/**
* Initialize hooks.
*/
@@ -67,10 +79,7 @@ class PluginsHelper {
add_action( 'woocommerce_plugins_install_and_activate_async_callback', array( __CLASS__, 'install_and_activate_plugins_async_callback' ), 10, 2 );
add_action( 'woocommerce_plugins_activate_callback', array( __CLASS__, 'activate_plugins' ), 10, 2 );
add_action( 'admin_notices', array( __CLASS__, 'maybe_show_connect_notice_in_plugin_list' ) );
- add_action( 'admin_notices', array( __CLASS__, 'maybe_show_expired_subscriptions_notice' ), 10 );
- add_action( 'admin_notices', array( __CLASS__, 'maybe_show_expiring_subscriptions_notice' ), 11 );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'maybe_enqueue_scripts_for_connect_notice' ) );
- add_action( 'admin_enqueue_scripts', array( __CLASS__, 'maybe_enqueue_scripts_for_subscription_notice' ) );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'maybe_enqueue_scripts_for_notices_in_plugins' ) );
}
@@ -659,6 +668,7 @@ class PluginsHelper {
wp_enqueue_script( 'woo-plugin-update-connect-notice' );
wp_enqueue_script( 'woo-enable-autorenew' );
wp_enqueue_script( 'woo-renew-subscription' );
+ wp_enqueue_script( 'woo-purchase-subscription' );
}
/**
@@ -733,11 +743,15 @@ class PluginsHelper {
* @return array notice data to return. Contains type, parsed_message and product_id.
*/
public static function get_subscriptions_notice_data( array $all_subs, array $subs_to_show, int $total, array $messages, string $type ) {
+ $utm_campaign = 'expired' === $type ?
+ 'pu_settings_screen_renew' :
+ ( 'missing' === $type ? 'pu_settings_screen_purchase' : 'pu_settings_screen_enable_autorenew' );
+
if ( 1 < $total ) {
$hyperlink_url = add_query_arg(
array(
'utm_source' => 'pu',
- 'utm_campaign' => 'expired' === $type ? 'pu_settings_screen_renew' : 'pu_settings_screen_enable_autorenew',
+ 'utm_campaign' => $utm_campaign,
),
self::WOO_SUBSCRIPTION_PAGE_URL
@@ -750,10 +764,18 @@ class PluginsHelper {
esc_attr( $total ),
);
+ // All product ids.
+ $product_ids = array_map(
+ function ( $sub ) {
+ return $sub['product_id'];
+ },
+ $subs_to_show
+ );
+
return array(
'type' => 'different_subscriptions',
'parsed_message' => $parsed_message,
- 'product_id' => '',
+ 'product_ids' => $product_ids,
);
}
@@ -769,8 +791,9 @@ class PluginsHelper {
)
);
- $message_key = $has_multiple_subs_for_product ? 'multiple_manage' : 'single_manage';
- $renew_string = __( 'Renew', 'woocommerce' );
+ $message_key = $has_multiple_subs_for_product ? 'multiple_manage' : 'single_manage';
+ $renew_string = __( 'Renew', 'woocommerce' );
+ $subscribe_string = __( 'Subscribe', 'woocommerce' );
if ( isset( $subscription['product_regular_price'] ) ) {
/* translators: 1: Product price */
$renew_string = sprintf( __( 'Renew for %1$s', 'woocommerce' ), $subscription['product_regular_price'] );
@@ -781,7 +804,7 @@ class PluginsHelper {
'product_id' => $product_id,
'type' => $type,
'utm_source' => 'pu',
- 'utm_campaign' => 'expired' === $type ? 'pu_settings_screen_renew' : 'pu_settings_screen_enable_autorenew',
+ 'utm_campaign' => $utm_campaign,
),
self::WOO_SUBSCRIPTION_PAGE_URL
@@ -798,7 +821,8 @@ class PluginsHelper {
esc_attr( $subscription['product_name'] ),
esc_attr( $expiry_date ),
esc_url( $hyperlink_url ),
- esc_attr( $renew_string ),
+ // Show subscribe for missing subscriptions, renew otherwise.
+ 'missing' === $type ? esc_attr( $subscribe_string ) : esc_attr( $renew_string ),
);
return array(
@@ -826,7 +850,7 @@ class PluginsHelper {
return array();
}
- if ( ! self::$can_show_expiring_subs_notice ) {
+ if ( self::$subscription_usage_notices_already_shown ) {
return array();
}
@@ -851,6 +875,9 @@ class PluginsHelper {
$total_expiring_subscriptions = count( $expiring_subscriptions );
+ // Don't show missing notice if there are expiring subscriptions.
+ self::$subscription_usage_notices_already_shown = true;
+
// When payment method is missing on WooCommerce.com.
$helper_notices = WC_Helper::get_notices();
if ( ! empty( $helper_notices['missing_payment_method_notice'] ) ) {
@@ -927,8 +954,8 @@ class PluginsHelper {
return array();
}
- $total_expired_subscriptions = count( $expired_subscriptions );
- self::$can_show_expiring_subs_notice = false;
+ $total_expired_subscriptions = count( $expired_subscriptions );
+ self::$subscription_usage_notices_already_shown = true;
$notice_data = self::get_subscriptions_notice_data(
$subscriptions,
@@ -947,17 +974,17 @@ class PluginsHelper {
$button_link = add_query_arg(
array(
+ 'add-to-cart' => $notice_data['product_ids'],
'utm_source' => 'pu',
'utm_campaign' => $allowed_link ? 'pu_settings_screen_renew' : 'pu_in_apps_screen_renew',
),
- self::WOO_SUBSCRIPTION_PAGE_URL
+ self::WOO_CART_PAGE_URL
);
if ( in_array( $notice_data['type'], array( 'single_manage', 'multiple_manage' ), true ) ) {
$button_link = add_query_arg(
array(
- 'product_id' => $notice_data['product_id'],
- 'type' => 'expiring',
+ 'add-to-cart' => $notice_data['product_id'],
),
$button_link
);
@@ -970,6 +997,86 @@ class PluginsHelper {
);
}
+ /**
+ * Get formatted notice information for missing subscription.
+ *
+ * @return array notice information.
+ */
+ public static function get_missing_subscription_notice() {
+ if ( ! WC_Helper::is_site_connected() ) {
+ return array();
+ }
+
+ if ( self::$subscription_usage_notices_already_shown ) {
+ return array();
+ }
+
+ if ( ! self::should_show_notice( self::DISMISS_MISSING_SUBS_NOTICE ) ) {
+ return array();
+ }
+
+ $subscriptions = WC_Helper::get_subscription_list_data();
+ $missing_subscriptions = array_filter(
+ $subscriptions,
+ function ( $sub ) {
+ return ( ! empty( $sub['local']['installed'] ) && empty( $sub['product_key'] ) );
+ },
+ );
+
+ // Remove WUM from missing subscriptions list.
+ $missing_subscriptions = array_filter(
+ $missing_subscriptions,
+ function ( $sub ) {
+ return 'woo-update-manager' !== $sub['zip_slug'];
+ }
+ );
+
+ if ( ! $missing_subscriptions ) {
+ return array();
+ }
+
+ $total_missing_subscriptions = count( $missing_subscriptions );
+
+ $notice_data = self::get_subscriptions_notice_data(
+ $subscriptions,
+ $missing_subscriptions,
+ $total_missing_subscriptions,
+ array(
+ /* translators: 1) product name */
+ 'single_manage' => __( 'You don\'t have a subscription for
. Subscribe to receive updates and streamlined support.', 'woocommerce' ),
+ /* translators: 1) total expired subscriptions */
+ 'different_subscriptions' => __( 'You don\'t have subscriptions for
. Subscribe to receive updates and streamlined support.', 'woocommerce' ),
+ ),
+ 'missing',
+ );
+
+ $button_link = add_query_arg(
+ array(
+ 'add-to-cart' => $notice_data['product_ids'],
+ 'utm_source' => 'pu',
+ 'utm_campaign' => 'pu_in_apps_screen_purchase',
+ ),
+ self::WOO_CART_PAGE_URL
+ );
+
+ if ( in_array( $notice_data['type'], array( 'single_manage', 'multiple_manage' ), true ) ) {
+ $button_link = add_query_arg(
+ array(
+ 'add-to-cart' => $notice_data['product_id'],
+ ),
+ $button_link
+ );
+ }
+
+ $button_text = __( 'Subscribe', 'woocommerce' );
+
+ return array(
+ 'description' => $notice_data['parsed_message'],
+ 'button_text' => $button_text,
+ 'button_link' => $button_link,
+ );
+ }
+
/**
* Determine whether a specific notice should be shown to the current user.
*
diff --git a/plugins/woocommerce/src/Admin/RemoteInboxNotifications/BaseLocationCountryRuleProcessor.php b/plugins/woocommerce/src/Admin/RemoteInboxNotifications/BaseLocationCountryRuleProcessor.php
deleted file mode 100644
index 3854f372b83..00000000000
--- a/plugins/woocommerce/src/Admin/RemoteInboxNotifications/BaseLocationCountryRuleProcessor.php
+++ /dev/null
@@ -1,33 +0,0 @@
-source ) ) {
$note->set_source( $spec->source );
}
+ if ( isset( $spec->layout ) ) {
+ $note->set_layout( $spec->layout );
+ }
// Recreate actions.
$note->set_actions( self::get_actions( $spec ) );
diff --git a/plugins/woocommerce/src/Admin/RemoteInboxNotifications/StoredStateRuleProcessor.php b/plugins/woocommerce/src/Admin/RemoteInboxNotifications/StoredStateRuleProcessor.php
deleted file mode 100644
index bc4f2c5e9fb..00000000000
--- a/plugins/woocommerce/src/Admin/RemoteInboxNotifications/StoredStateRuleProcessor.php
+++ /dev/null
@@ -1,33 +0,0 @@
- "media" ),
- array("industry" => "software" )
-);
-```
-
-Use `array_column` to extract `array("media", "software")` then choose the first element with `dot_notation`.
-
-```php
-"transformers": [
- {
- "use": "array_column",
- "arguments": {
- "key": "industry"
- }
- },
- {
- "use": "dot_notation",
- "arguments": {
- "key": "0"
- }
- }
-],
-```
-
-**Output**: "media"
-
-
-
-
-
-## array_flatten
-
-Flattens a nested array.
-
-#### Arguments: N/A
-
-#### Definition:
-
-```php
-"transformers": [
- {
- "use": "array_flatten"
- }
-],
-```
-
-#### Example:
-
-Given the following data
-
-```php
-array(
- array(
- 'member1',
- ),
- array(
- 'member2',
- ),
- array(
- 'member3',
- ),
-);
-```
-
-Use `array_flatten` to extract `array("member1", "member2", "member3")` then use `array_search` to make sure it has `member2`
-
-
-```php
-"transformers": [
- {
- "use": "array_flatten",
- },
- {
- "use": "array_search",
- "arguments": {
- "key": "member2"
- }
- }
-],
-```
-
-**Output**: true
-
-## array_keys
-
-PHP's built-in `array_keys` to return keys from an array. For more information about how `array_keys` works, please see PHP’s [official documentation](https://www.php.net/manual/en/function.array-column.php).
-
-#### Arguments: N/A
-
-####Definition:
-
-```php
-"transformers": [
- {
- "use": "array_keys"
- }
-],
-```
-
-#### Example:
-
-Given the following data
-
-```php
-array(
- "name" => "tester",
- "address" => "test",
- "supports_version_2" => true
-)
-```
-
-Use `array_keys` to extract `array("name", "address", "supports_version_2")` and then use `array_search` to make sure it has `supports_version_2`
-
-```php
-"transformers": [
- {
- "use": "array_keys",
- },
- {
- "use": "array_search",
- "arguments": {
- "key": "member2"
- }
- }
-],
-```
-
-**Output**: true
-
-## array_search
-
-PHP's built-in `array_search` to search a value in an array. For more information about how `array_search` works, please see PHP’s [official documentation](https://www.php.net/manual/en/function.array-search.php).
-
-#### Arguments:
-
-|name|description|
-|----|---------|
-| value | a value to search in the given array |
-
-#### Definition:
-
-```php
-"transformers": [
- {
- "use": "array_search",
- "arguments": {
- "value": "test"
- }
- }
-],
-```
-
-#### Examples
-
-See examples from [array_flatten](#array_flatten) and [array_keys](#array_keys)
-
-## array_values
-
-PHP's built-in array_values to return values from an array. For more information about how `array_values` works, please see PHP’s [official documentation](https://www.php.net/manual/en/function.array-values).
-
-
-#### Arguments: N/A
-
-#### Definition:
-
-```php
-"transformers": [
- {
- "use": "array_values"
- }
-],
-```
-
-#### Example:
-
-Given the following data
-
-```php
-array (
- "size" => "x-large"
-)
-```
-
-Use `array_values` to extract `array("x-large")`
-
-```php
-"transformers": [
- {
- "use": "array_values",
- }
-],
-```
-
-**Output:** "x-large"
-
-
-## dot_notation
-
-Uses dot notation to select a value in an array. Dot notation lets you access an array as if it is an object.
-
-#### Arguments: N/A
-
-#### Definition:
-
-
-```php
-"transformers": [
- {
- "use": "dot_notation",
- "arguments": {
- "path": "name"
- }
- }
-],
-```
-
-#### Example:
-
-
-
-Given the following data
-
-```php
-array(
- 'name' => 'john',
- 'members' => ['member1', 'member2']
-);
-```
-
-Select `name` field.
-
-```php
-"transformers": [
- {
- "use": "dot_notation",
- "arguments": {
- "path": "name"
- }
- }
-],
-```
-
-**Output:** "john"
-
-Select `member2`. You can access array items with an index.
-
-```php
-"transformers": [
- {
- "use": "dot_notation",
- "arguments": {
- "path": "members.1"
- }
- }
-],
-```
-
-**Output:**: "member2"
-
-## count
-
-PHP's built-in count to return the number of values from a countable, such as an array.
-
-#### Arguments: N/A
-
-#### Definition:
-
-```php
-"transformers": [
- {
- "use": "count"
- }
-],
-```
-
-#### Example:
-
-Given the following list of usernames
-
-```php
-array(
- "username1",
- "username2",
- "username3"
-)
-```
-
-Let's count # of users with `count`
-
-```php
-"transformers": [
- {
- "use": "count",
- }
-],
-```
-
-**Output:** 3
-
-## prepare_url
-
-This prepares the site URL by removing the protocol and the last slash.
-
-#### Arguments: N/A
-
-####Definition:
-
-```php
-"transformers": [
- {
- "use": "prepare_url"
- }
-],
-```
-
-#### Example:
-
-Given the following data
-
-```php
-$siteurl = "https://mysite.com/"
-```
-
-Removes the protocol and the last slash.
-
-```php
-"transformers": [
- {
- "use": "prepare_url",
- }
-],
-```
-
-**Output:** "mysite.com"
diff --git a/plugins/woocommerce/src/Admin/RemoteInboxNotifications/WCAdminActiveForProvider.php b/plugins/woocommerce/src/Admin/RemoteInboxNotifications/WCAdminActiveForProvider.php
deleted file mode 100644
index 21d53b4c0c1..00000000000
--- a/plugins/woocommerce/src/Admin/RemoteInboxNotifications/WCAdminActiveForProvider.php
+++ /dev/null
@@ -1,31 +0,0 @@
-register_block_type()
+ * @param string $key Data to get, or default to everything.
+ * @return array|string
+ */
+ protected function get_block_type_script( $key = null ) {
+ $script = [
+ 'handle' => 'wc-order-confirmation-create-account-block-frontend',
+ 'path' => $this->asset_api->get_block_asset_build_path( 'order-confirmation-create-account-frontend' ),
+ 'dependencies' => [],
+ ];
+ return $key ? $script[ $key ] : $script;
+ }
+
+ /**
+ * Process posted account form.
+ *
+ * @param \WC_Order $order Order object.
+ * @return \WP_Error|int
+ */
+ protected function process_form_post( $order ) {
+ if ( ! isset( $_POST['create-account'], $_POST['email'], $_POST['password'], $_POST['_wpnonce'] ) ) {
+ return 0;
+ }
+
+ if ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['_wpnonce'] ?? '' ) ), 'wc_create_account' ) ) {
+ return new \WP_Error( 'invalid_nonce', __( 'Unable to create account. Please try again.', 'woocommerce' ) );
+ }
+
+ $user_email = sanitize_email( wp_unslash( $_POST['email'] ) );
+ $password = wp_unslash( $_POST['password'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
+
+ // Does order already have user?
+ if ( $order->get_customer_id() ) {
+ return new \WP_Error( 'order_already_has_user', __( 'This order is already linked to a user account.', 'woocommerce' ) );
+ }
+
+ // Check given details match the current viewed order.
+ if ( $order->get_billing_email() !== $user_email ) {
+ return new \WP_Error( 'email_mismatch', __( 'The email address provided does not match the email address on this order.', 'woocommerce' ) );
+ }
+
+ if ( empty( $password ) || strlen( $password ) < 8 ) {
+ return new \WP_Error( 'password_too_short', __( 'Password must be at least 8 characters.', 'woocommerce' ) );
+ }
+
+ $customer_id = wc_create_new_customer(
+ $user_email,
+ '',
+ $password,
+ [
+ 'first_name' => $order->get_billing_first_name(),
+ 'last_name' => $order->get_billing_last_name(),
+ 'source' => 'delayed-account-creation',
+ ]
+ );
+
+ if ( is_wp_error( $customer_id ) ) {
+ return $customer_id;
+ }
+
+ // Associate customer with the order.
+ $order->set_customer_id( $customer_id );
+ $order->save();
+
+ // Associate addresses from the order with the customer.
+ $order_controller = new OrderController();
+ $order_controller->sync_customer_data_with_order( $order );
+
+ // Set the customer auth cookie.
+ wc_set_customer_auth_cookie( $customer_id );
+
+ return $customer_id;
+ }
+
+ /**
+ * This renders the content of the block within the wrapper.
+ *
+ * @param \WC_Order $order Order object.
+ * @param string|false $permission If the current user can view the order details or not.
+ * @param array $attributes Block attributes.
+ * @param string $content Original block content.
+ * @return string
+ */
+ protected function render_content( $order, $permission = false, $attributes = [], $content = '' ) {
+ if ( ! $permission ) {
+ return '';
+ }
+
+ // Check registration is possible for this order/customer, and if not, return early.
+ if ( is_user_logged_in() || email_exists( $order->get_billing_email() ) ) {
+ return '';
+ }
+
+ $result = $this->process_form_post( $order );
+
+ if ( is_wp_error( $result ) ) {
+ $notice = wc_print_notice( $result->get_error_message(), 'error', [], true );
+ } elseif ( $result ) {
+ return $this->render_confirmation();
+ }
+
+ $processor = new \WP_HTML_Tag_Processor(
+ $content .
+ '
'
+ );
+
+ if ( ! $processor->next_tag( array( 'class_name' => 'wp-block-woocommerce-order-confirmation-create-account' ) ) ) {
+ return $content;
+ }
+
+ $processor->set_attribute( 'class', '' );
+ $processor->set_attribute( 'style', '' );
+ $processor->add_class( 'woocommerce-order-confirmation-create-account-content' );
+
+ if ( ! $processor->next_tag( array( 'class_name' => 'woocommerce-order-confirmation-create-account-form' ) ) ) {
+ return $content;
+ }
+
+ $processor->set_attribute( 'data-customer-email', $order->get_billing_email() );
+ $processor->set_attribute( 'data-nonce-token', wp_create_nonce( 'wc_create_account' ) );
+
+ if ( ! empty( $attributes['hasDarkControls'] ) ) {
+ $processor->add_class( 'has-dark-controls' );
+ }
+
+ return $processor->get_updated_html();
+ }
+
+ /**
+ * Render the block when an account has been registered.
+ *
+ * @return string
+ */
+ protected function render_confirmation() {
+ $content = '
';
+
+ return $content;
+ }
+}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/OrderConfirmation/Status.php b/plugins/woocommerce/src/Blocks/BlockTypes/OrderConfirmation/Status.php
index 6cc50f68d3a..047be224e28 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/OrderConfirmation/Status.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/OrderConfirmation/Status.php
@@ -2,8 +2,6 @@
namespace Automattic\WooCommerce\Blocks\BlockTypes\OrderConfirmation;
-use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;
-
/**
* Status class.
*/
@@ -265,7 +263,7 @@ class Status extends AbstractOrderConfirmationBlock {
',
esc_attr( 'verify-email-submit' ),
esc_html__( 'Confirm email and view order', 'woocommerce' ),
- wp_nonce_field( 'wc_verify_email', 'check_submission', true, false ),
+ wp_nonce_field( 'wc_verify_email', '_wpnonce', true, false ),
esc_attr( wc_wp_theme_get_element_class_name( 'button' ) )
) .
'';
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/ProductCollection.php b/plugins/woocommerce/src/Blocks/BlockTypes/ProductCollection.php
index 8f4c3ecfda1..d7d7be05d95 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/ProductCollection.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/ProductCollection.php
@@ -499,11 +499,18 @@ class ProductCollection extends AbstractBlock {
*/
private function is_block_compatible( $block_name ) {
// Check for explicitly unsupported blocks.
- if (
- 'core/post-content' === $block_name ||
- 'woocommerce/mini-cart' === $block_name ||
- 'woocommerce/featured-product' === $block_name
- ) {
+ $unsupported_blocks = array(
+ 'core/post-content',
+ 'woocommerce/mini-cart',
+ 'woocommerce/featured-product',
+ 'woocommerce/active-filters',
+ 'woocommerce/price-filter',
+ 'woocommerce/stock-filter',
+ 'woocommerce/attribute-filter',
+ 'woocommerce/rating-filter',
+ );
+
+ if ( in_array( $block_name, $unsupported_blocks, true ) ) {
return false;
}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilter.php b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilter.php
deleted file mode 100644
index 6cfc9a1465a..00000000000
--- a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilter.php
+++ /dev/null
@@ -1,157 +0,0 @@
-register_block_type()
- * @param string $key Data to get, or default to everything.
- * @return array|string|null
- */
- protected function get_block_type_script( $key = null ) {
- return null;
- }
-
- /**
- * Extra data passed through from server to client for block.
- *
- * @param array $attributes Any attributes that currently are available from the block.
- * Note, this will be empty in the editor context when the block is
- * not in the post content on editor load.
- */
- protected function enqueue_data( array $attributes = [] ) {
- global $pagenow;
- parent::enqueue_data( $attributes );
-
- $this->asset_data_registry->add( 'isBlockTheme', wc_current_theme_is_fse_theme() );
- $this->asset_data_registry->add( 'isProductArchive', is_shop() || is_product_taxonomy() );
- $this->asset_data_registry->add( 'isSiteEditor', 'site-editor.php' === $pagenow );
- $this->asset_data_registry->add( 'isWidgetEditor', 'widgets.php' === $pagenow || 'customize.php' === $pagenow );
- }
-
- /**
- * Check array for checked item.
- *
- * @param array $items Items to check.
- */
- private function hasSelectedFilter( $items ) {
- foreach ( $items as $key => $value ) {
- if ( 'checked' === $key && true === $value ) {
- return true;
- }
-
- if ( is_array( $value ) && $this->hasSelectedFilter( $value ) ) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Render the block.
- *
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
- * @return string Rendered block type output.
- */
- protected function render( $attributes, $content, $block ) {
- if ( is_admin() ) {
- return $content;
- }
-
- $tags = new WP_HTML_Tag_Processor( $content );
- $has_selected_filter = false;
-
- while ( $tags->next_tag( 'div' ) ) {
- $items = $tags->get_attribute( 'data-wc-context' ) ? json_decode( $tags->get_attribute( 'data-wc-context' ), true ) : null;
-
- // For checked box filters.
- if ( $items && array_key_exists( 'items', $items ) ) {
- $has_selected_filter = $this->hasSelectedFilter( $items['items'] );
- break;
- }
-
- // For price range filter.
- if ( $items && array_key_exists( 'minPrice', $items ) ) {
- if ( $items['minPrice'] > $items['minRange'] || $items['maxPrice'] < $items['maxRange'] ) {
- $has_selected_filter = true;
- break;
- }
- }
-
- // For dropdown filters.
- if ( $items && array_key_exists( 'selectedItems', $items ) ) {
- if ( count( $items['selectedItems'] ) > 0 ) {
- $has_selected_filter = true;
- break;
- }
- }
- }
-
- $attributes_data = array(
- 'data-wc-interactive' => wp_json_encode( array( 'namespace' => $this->get_full_block_name() ), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ),
- 'data-wc-context' => wp_json_encode( array( 'hasSelectedFilter' => $has_selected_filter ), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ),
- 'class' => 'wc-block-product-filters',
- );
-
- if ( ! isset( $block->context['queryId'] ) ) {
- $attributes_data['data-wc-navigation-id'] = $this->generate_navigation_id( $block );
- }
-
- $tags = new WP_HTML_Tag_Processor( $content );
-
- while ( $tags->next_tag( 'div' ) ) {
- if ( 'yes' === $tags->get_attribute( 'data-has-filter' ) ) {
- return sprintf(
- '
',
- get_block_wrapper_attributes( $attributes_data ),
- $content
- );
- }
- }
-
- return sprintf(
- '
',
- get_block_wrapper_attributes( $attributes_data ),
- );
- }
-
- /**
- * Generate a unique navigation ID for the block.
- *
- * @param mixed $block - Block instance.
- * @return string - Unique navigation ID.
- */
- private function generate_navigation_id( $block ) {
- return sprintf(
- 'wc-product-filter-%s',
- md5( wp_json_encode( $block->parsed_block['innerBlocks'] ) )
- );
- }
-}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterActive.php b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterActive.php
index 679227f3a09..11469663107 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterActive.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterActive.php
@@ -57,7 +57,6 @@ final class ProductFilterActive extends AbstractBlock {
array(
'data-wc-interactive' => wp_json_encode( array( 'namespace' => $this->get_full_block_name() ), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ),
'data-wc-context' => wp_json_encode( $context, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ),
- 'data-has-filter' => empty( $active_filters ) ? 'no' : 'yes',
)
);
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterAttribute.php b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterAttribute.php
index d997799c772..0a5327f9ce0 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterAttribute.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterAttribute.php
@@ -1,10 +1,10 @@
get_default_product_attribute();
- $attributes['attributeId'] = $default_product_attribute->attribute_id;
+ protected function render( $block_attributes, $content, $block ) {
+ if ( empty( $block_attributes['attributeId'] ) ) {
+ $default_product_attribute = $this->get_default_product_attribute();
+ $block_attributes['attributeId'] = $default_product_attribute->attribute_id;
}
// don't render if its admin, or ajax in progress.
- if ( is_admin() || wp_doing_ajax() || empty( $attributes['attributeId'] ) ) {
+ if ( is_admin() || wp_doing_ajax() || empty( $block_attributes['attributeId'] ) ) {
return '';
}
- $product_attribute = wc_get_attribute( $attributes['attributeId'] );
- $attribute_counts = $this->get_attribute_counts( $block, $product_attribute->slug, $attributes['queryType'] );
+ $product_attribute = wc_get_attribute( $block_attributes['attributeId'] );
+ $attribute_counts = $this->get_attribute_counts( $block, $product_attribute->slug, $block_attributes['queryType'] );
if ( empty( $attribute_counts ) ) {
return sprintf(
@@ -181,7 +182,6 @@ final class ProductFilterAttribute extends AbstractBlock {
get_block_wrapper_attributes(
array(
'data-wc-interactive' => wp_json_encode( array( 'namespace' => $this->get_full_block_name() ), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ),
- 'data-has-filter' => 'no',
)
),
);
@@ -202,118 +202,56 @@ final class ProductFilterAttribute extends AbstractBlock {
);
$attribute_options = array_map(
- function ( $term ) use ( $attribute_counts, $selected_terms ) {
+ function ( $term ) use ( $block_attributes, $attribute_counts, $selected_terms ) {
$term = (array) $term;
$term['count'] = $attribute_counts[ $term['term_id'] ];
$term['selected'] = in_array( $term['slug'], $selected_terms, true );
- return $term;
+ return array(
+ 'label' => $block_attributes['showCounts'] ? sprintf( '%1$s (%2$d)', $term['name'], $term['count'] ) : $term['name'],
+ 'value' => $term['slug'],
+ 'selected' => $term['selected'],
+ 'rawData' => $term,
+ );
},
$attribute_terms
);
$filtered_options = array_filter(
$attribute_options,
- function ( $option ) {
- return $option['count'] > 0;
+ function ( $option ) use ( $block_attributes ) {
+ $hide_empty = $block_attributes['hideEmpty'] ?? true;
+ if ( $hide_empty ) {
+ return $option['rawData']['count'] > 0;
+ }
+ return true;
}
);
- $filter_content = 'dropdown' === $attributes['displayStyle'] ?
- $this->render_attribute_dropdown( $filtered_options, $attributes ) :
- $this->render_attribute_checkbox_list( $filtered_options, $attributes );
+ $filter_context = array(
+ 'on_change' => "{$this->get_full_block_name()}::actions.updateProducts",
+ 'items' => $filtered_options,
+ );
+
+ foreach ( $block->parsed_block['innerBlocks'] as $inner_block ) {
+ $content .= ( new \WP_Block( $inner_block, array( 'filterData' => $filter_context ) ) )->render();
+ }
$context = array(
- 'attributeSlug' => str_replace( 'pa_', '', $product_attribute->slug ),
- 'queryType' => $attributes['queryType'],
- 'selectType' => 'multiple',
+ 'attributeSlug' => str_replace( 'pa_', '', $product_attribute->slug ),
+ 'queryType' => $block_attributes['queryType'],
+ 'selectType' => 'multiple',
+ 'hasSelectedFilters' => count( $selected_terms ) > 0,
);
return sprintf(
- '
',
get_block_wrapper_attributes(
array(
'data-wc-context' => wp_json_encode( $context, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ),
'data-wc-interactive' => wp_json_encode( array( 'namespace' => $this->get_full_block_name() ), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ),
- 'data-has-filter' => 'yes',
)
),
- $content,
- $filter_content
- );
- }
-
- /**
- * Render the dropdown.
- *
- * @param array $options Data to render the dropdown.
- * @param bool $attributes Block attributes.
- */
- private function render_attribute_dropdown( $options, $attributes ) {
- if ( empty( $options ) ) {
- return '';
- }
-
- $list_items = array();
- $selected_items = array();
-
- $product_attribute = wc_get_attribute( $attributes['attributeId'] );
-
- foreach ( $options as $option ) {
- $item = array(
- 'label' => $attributes['showCounts'] ? sprintf( '%1$s (%2$d)', $option['name'], $option['count'] ) : $option['name'],
- 'value' => $option['slug'],
- );
-
- $list_items[] = $item;
-
- if ( $option['selected'] ) {
- $selected_items[] = $item;
- }
- }
-
- return Dropdown::render(
- array(
- 'items' => $list_items,
- 'action' => "{$this->get_full_block_name()}::actions.navigate",
- 'selected_items' => $selected_items,
- 'select_type' => 'multiple',
- // translators: %s is a product attribute name.
- 'placeholder' => sprintf( __( 'Select %s', 'woocommerce' ), $product_attribute->name ),
- )
- );
- }
-
- /**
- * Render the attribute filter checkbox list.
- *
- * @param mixed $options Attribute filter options to render in the checkbox list.
- * @param mixed $attributes Block attributes.
- * @return string
- */
- private function render_attribute_checkbox_list( $options, $attributes ) {
- if ( empty( $options ) ) {
- return '';
- }
-
- $show_counts = $attributes['showCounts'] ?? false;
-
- $list_options = array_map(
- function ( $option ) use ( $show_counts ) {
- return array(
- 'id' => $option['slug'] . '-' . $option['term_id'],
- 'checked' => $option['selected'],
- 'label' => $show_counts ? sprintf( '%1$s (%2$d)', $option['name'], $option['count'] ) : $option['name'],
- 'value' => $option['slug'],
- );
- },
- $options
- );
-
- return CheckboxList::render(
- array(
- 'items' => $list_options,
- 'on_change' => "{$this->get_full_block_name()}::actions.updateProducts",
- )
+ $content
);
}
@@ -380,7 +318,16 @@ final class ProductFilterAttribute extends AbstractBlock {
$cached = get_transient( 'wc_block_product_filter_attribute_default_attribute' );
- if ( $cached ) {
+ if (
+ $cached &&
+ isset( $cached->attribute_id ) &&
+ isset( $cached->attribute_name ) &&
+ isset( $cached->attribute_label ) &&
+ isset( $cached->attribute_type ) &&
+ isset( $cached->attribute_orderby ) &&
+ isset( $cached->attribute_public ) &&
+ '0' !== $cached->attribute_id
+ ) {
return $cached;
}
@@ -428,10 +375,9 @@ final class ProductFilterAttribute extends AbstractBlock {
if ( $attribute_id ) {
$default_attribute = $attributes[ $attribute_id ];
+ set_transient( 'wc_block_product_filter_attribute_default_attribute', $default_attribute, DAY_IN_SECONDS );
}
- set_transient( 'wc_block_product_filter_attribute_default_attribute', $default_attribute );
-
return $default_attribute;
}
@@ -447,32 +393,26 @@ final class ProductFilterAttribute extends AbstractBlock {
'inserter' => false,
'content' => strtr(
'
-
-
-
-
-
{{attribute_label}}
-
+
+
+
+
+
+
{{attribute_label}}
+
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
+
',
array(
'{{attribute_id}}' => intval( $default_attribute->attribute_id ),
@@ -482,4 +422,18 @@ final class ProductFilterAttribute extends AbstractBlock {
)
);
}
+
+ /**
+ * Skip default rendering routine for inner blocks.
+ *
+ * @param array $settings Array of determined settings for registering a block type.
+ * @param array $metadata Metadata provided for registering a block type.
+ * @return array
+ */
+ public function add_block_type_metadata_settings( $settings, $metadata ) {
+ if ( ! empty( $metadata['name'] ) && "woocommerce/{$this->block_name}" === $metadata['name'] ) {
+ $settings['skip_inner_blocks'] = true;
+ }
+ return $settings;
+ }
}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterCheckboxList.php b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterCheckboxList.php
new file mode 100644
index 00000000000..a4a299d9ff8
--- /dev/null
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterCheckboxList.php
@@ -0,0 +1,155 @@
+context['filterData'];
+ $items = $context['items'] ?? array();
+ $checkbox_list_context = array( 'items' => $items );
+ $on_change = $context['on_change'] ?? '';
+ $namespace = wp_json_encode( array( 'namespace' => 'woocommerce/product-filter-checkbox-list' ), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP );
+
+ $classes = array(
+ 'has-option-element-border-color' => $this->get_color_attribute_value( 'optionElementBorder', $attributes ),
+ 'has-option-element-selected-color' => $this->get_color_attribute_value( 'optionElementSelected', $attributes ),
+ 'has-option-element-color' => $this->get_color_attribute_value( 'optionElement', $attributes ),
+ );
+ $classes = array_filter( $classes );
+
+ $styles = array(
+ '--wc-product-filter-checkbox-list-option-element-border' => $this->get_color_attribute_value( 'optionElementBorder', $attributes ),
+ '--wc-product-filter-checkbox-list-option-element-selected' => $this->get_color_attribute_value( 'optionElementSelected', $attributes ),
+ '--wc-product-filter-checkbox-list-option-element' => $this->get_color_attribute_value( 'optionElement', $attributes ),
+ );
+ $style = array_reduce(
+ array_keys( $styles ),
+ function ( $acc, $key ) use ( $styles ) {
+ if ( $styles[ $key ] ) {
+ return $acc . "{$key}: var( --wp--preset--color--{$styles[$key]} );";
+ }
+ }
+ );
+
+ $checked_items = array_filter(
+ $items,
+ function ( $item ) {
+ return $item['selected'];
+ }
+ );
+ $show_initially = $context['show_initially'] ?? 15;
+ $remaining_initial_unchecked = count( $checked_items ) > $show_initially ? count( $checked_items ) : $show_initially - count( $checked_items );
+ $count = 0;
+
+ $wrapper_attributes = array(
+ 'data-wc-interactive' => esc_attr( $namespace ),
+ 'data-wc-context' => wp_json_encode( $checkbox_list_context, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ),
+ 'class' => implode( ' ', array_keys( $classes ) ),
+ 'style' => esc_attr( $style ),
+ );
+
+ ob_start();
+ ?>
+
>
+
+ $show_initially ) : ?>
+
+
+
+
+
+ '!context.hasSelectedFilter',
+ 'data-wc-bind--hidden' => '!context.hasSelectedFilters',
)
);
$p = new \WP_HTML_Tag_Processor( $content );
if ( $p->next_tag( array( 'class_name' => 'wp-block-button__link' ) ) ) {
- $p->set_attribute( 'data-wc-on--click', 'actions.clear' );
+ $p->set_attribute( 'data-wc-on--click', 'actions.clearFilters' );
$style = $p->get_attribute( 'style' );
$p->set_attribute( 'style', 'outline:none;' . $style );
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilters.php b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilters.php
index 9c149ef6b3c..0137f32abf4 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilters.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilters.php
@@ -23,6 +23,23 @@ class ProductFilters extends AbstractBlock {
return array( 'postId' );
}
+ /**
+ * Extra data passed through from server to client for block.
+ *
+ * @param array $attributes Any attributes that currently are available from the block.
+ * Note, this will be empty in the editor context when the block is
+ * not in the post content on editor load.
+ */
+ protected function enqueue_data( array $attributes = array() ) {
+ global $pagenow;
+ parent::enqueue_data( $attributes );
+
+ $this->asset_data_registry->add( 'isBlockTheme', wc_current_theme_is_fse_theme() );
+ $this->asset_data_registry->add( 'isProductArchive', is_shop() || is_product_taxonomy() );
+ $this->asset_data_registry->add( 'isSiteEditor', 'site-editor.php' === $pagenow );
+ $this->asset_data_registry->add( 'isWidgetEditor', 'widgets.php' === $pagenow || 'customize.php' === $pagenow );
+ }
+
/**
* Return the dialog content.
*
@@ -116,12 +133,10 @@ class ProductFilters extends AbstractBlock {
* @return string Rendered block type output.
*/
protected function render( $attributes, $content, $block ) {
- $html = $content;
- $p = new \WP_HTML_Tag_Processor( $html );
-
- if ( $p->next_tag() ) {
- $p->set_attribute( 'data-wc-interactive', wp_json_encode( array( 'namespace' => 'woocommerce/product-filters' ), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ) );
- $p->set_attribute(
+ $tags = new \WP_HTML_Tag_Processor( $content );
+ if ( $tags->next_tag() ) {
+ $tags->set_attribute( 'data-wc-interactive', wp_json_encode( array( 'namespace' => 'woocommerce/' . $this->block_name ), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ) );
+ $tags->set_attribute(
'data-wc-context',
wp_json_encode(
array(
@@ -131,13 +146,29 @@ class ProductFilters extends AbstractBlock {
JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
)
);
- $html = $p->get_updated_html();
+ $tags->set_attribute( 'data-wc-navigation-id', $this->generate_navigation_id( $block ) );
+
+ if (
+ 'always' === $attributes['overlay'] ||
+ ( 'mobile' === $attributes['overlay'] && wp_is_mobile() )
+ ) {
+ return $this->inject_dialog( $tags->get_updated_html(), $this->render_dialog() );
+ }
+
+ return $tags->get_updated_html();
}
+ }
- $dialog_html = $this->render_dialog();
-
- $html = $this->inject_dialog( $html, $dialog_html );
-
- return $html;
+ /**
+ * Generate a unique navigation ID for the block.
+ *
+ * @param mixed $block - Block instance.
+ * @return string - Unique navigation ID.
+ */
+ private function generate_navigation_id( $block ) {
+ return sprintf(
+ 'wc-product-filters-%s',
+ md5( wp_json_encode( $block->parsed_block['innerBlocks'] ) )
+ );
}
}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypesController.php b/plugins/woocommerce/src/Blocks/BlockTypesController.php
index f6d84ecc051..03e87ecbbad 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypesController.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypesController.php
@@ -404,7 +404,6 @@ final class BlockTypesController {
// Update plugins/woocommerce-blocks/docs/internal-developers/blocks/feature-flags-and-experimental-interfaces.md
// when modifying this list.
if ( Features::is_enabled( 'experimental-blocks' ) ) {
- $block_types[] = 'ProductFilter';
$block_types[] = 'ProductFilters';
$block_types[] = 'ProductFiltersOverlay';
$block_types[] = 'ProductFiltersOverlayNavigation';
@@ -414,6 +413,9 @@ final class BlockTypesController {
$block_types[] = 'ProductFilterRating';
$block_types[] = 'ProductFilterActive';
$block_types[] = 'ProductFilterClearButton';
+ $block_types[] = 'ProductFilterCheckboxList';
+ $block_types[] = 'ProductFilterChips';
+ $block_types[] = 'OrderConfirmation\CreateAccount';
}
/**
diff --git a/plugins/woocommerce/src/Container.php b/plugins/woocommerce/src/Container.php
index 56d3b5b1e98..17ceac62783 100644
--- a/plugins/woocommerce/src/Container.php
+++ b/plugins/woocommerce/src/Container.php
@@ -32,6 +32,7 @@ use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\BatchP
use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\LayoutTemplatesServiceProvider;
use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\ComingSoonServiceProvider;
use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\StatsServiceProvider;
+use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\ImportExportServiceProvider;
/**
* PSR11 compliant dependency injection container for WooCommerce.
@@ -83,6 +84,7 @@ final class Container {
EnginesServiceProvider::class,
ComingSoonServiceProvider::class,
StatsServiceProvider::class,
+ ImportExportServiceProvider::class,
);
/**
diff --git a/plugins/woocommerce/src/Internal/Admin/Homescreen.php b/plugins/woocommerce/src/Internal/Admin/Homescreen.php
index 1a9cd90f776..dfb0cde522e 100644
--- a/plugins/woocommerce/src/Internal/Admin/Homescreen.php
+++ b/plugins/woocommerce/src/Internal/Admin/Homescreen.php
@@ -166,7 +166,6 @@ class Homescreen {
'homepage_layout',
'homepage_stats',
'task_list_tracked_started_tasks',
- 'help_panel_highlight_shown',
)
);
}
diff --git a/plugins/woocommerce/src/Internal/Admin/ImportExport/CSVUploadHelper.php b/plugins/woocommerce/src/Internal/Admin/ImportExport/CSVUploadHelper.php
new file mode 100644
index 00000000000..c1759bc5e93
--- /dev/null
+++ b/plugins/woocommerce/src/Internal/Admin/ImportExport/CSVUploadHelper.php
@@ -0,0 +1,175 @@
+get_import_subdir_name();
+ if ( $create ) {
+ FilesystemUtil::mkdir_p_not_indexable( $upload_dir );
+ }
+ return $upload_dir;
+ }
+
+ /**
+ * Handles a CSV file upload.
+ *
+ * @param string $import_type Type of upload or context.
+ * @param string $files_index $_FILES index that contains the file to upload.
+ * @param array|null $allowed_mime_types List of allowed MIME types.
+ * @return array {
+ * Details for the uploaded file.
+ *
+ * @type int $id Attachment ID.
+ * @type string $file Full path to uploaded file.
+ * }
+ *
+ * @throws \Exception In case of error.
+ */
+ public function handle_csv_upload( string $import_type, string $files_index = 'import', ?array $allowed_mime_types = null ): array {
+ $import_type = sanitize_key( $import_type );
+ if ( ! $import_type ) {
+ throw new \Exception( 'Import type is invalid.' );
+ }
+
+ if ( ! $allowed_mime_types ) {
+ $allowed_mime_types = array(
+ 'csv' => 'text/csv',
+ 'txt' => 'text/plain',
+ );
+ }
+
+ $file = $_FILES[ $files_index ] ?? null; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.NonceVerification.Missing
+ if ( ! isset( $file['tmp_name'] ) || ! is_uploaded_file( $file['tmp_name'] ) ) {
+ throw new \Exception( esc_html__( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.', 'woocommerce' ) );
+ }
+
+ if ( ! function_exists( 'wp_import_handle_upload' ) ) {
+ require_once ABSPATH . 'wp-admin/includes/import.php';
+ }
+
+ // Make sure upload dir exists.
+ $this->get_import_dir();
+
+ // Add prefix.
+ $file['name'] = $import_type . '-' . $file['name'];
+
+ $overrides_callback = function ( $overrides_ ) use ( $allowed_mime_types ) {
+ $overrides_['test_form'] = false;
+ $overrides_['test_type'] = true;
+ $overrides_['mimes'] = $allowed_mime_types;
+ return $overrides_;
+ };
+
+ self::add_filter( 'upload_dir', array( $this, 'override_upload_dir' ) );
+ self::add_filter( 'wp_unique_filename', array( $this, 'override_unique_filename' ), 0, 2 );
+ self::add_filter( 'wp_handle_upload_overrides', $overrides_callback, 999 );
+ self::add_filter( 'wp_handle_upload_prefilter', array( $this, 'remove_txt_from_uploaded_file' ), 0 );
+
+ $orig_files_import = $_FILES['import'] ?? null; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.NonceVerification.Missing
+ $_FILES['import'] = $file; // wp_import_handle_upload() expects the file to be in 'import'.
+
+ $upload = wp_import_handle_upload();
+
+ remove_filter( 'upload_dir', array( $this, 'override_upload_dir' ) );
+ remove_filter( 'wp_unique_filename', array( $this, 'override_unique_filename' ), 0 );
+ remove_filter( 'wp_handle_upload_overrides', $overrides_callback, 999 );
+ remove_filter( 'wp_handle_upload_prefilter', array( $this, 'remove_txt_from_uploaded_file' ), 0 );
+
+ if ( $orig_files_import ) {
+ $_FILES['import'] = $orig_files_import;
+ } else {
+ unset( $_FILES['import'] );
+ }
+
+ if ( ! empty( $upload['error'] ) ) {
+ throw new \Exception( esc_html( $upload['error'] ) );
+ }
+
+ if ( ! wc_is_file_valid_csv( $upload['file'], false ) ) {
+ wp_delete_attachment( $file['id'], true );
+ throw new \Exception( esc_html__( 'Invalid file type for a CSV import.', 'woocommerce' ) );
+ }
+
+ return $upload;
+ }
+
+ /**
+ * Hooked onto 'upload_dir' to override the default upload directory for a CSV upload.
+ *
+ * @param array $uploads WP upload dir details.
+ * @return array
+ */
+ private function override_upload_dir( $uploads ): array {
+ $new_subdir = '/' . $this->get_import_subdir_name();
+
+ $uploads['path'] = $uploads['basedir'] . $new_subdir;
+ $uploads['url'] = $uploads['baseurl'] . $new_subdir;
+ $uploads['subdir'] = $new_subdir;
+
+ return $uploads;
+ }
+
+ /**
+ * Adds a random string to the name of an uploaded CSV file to make it less discoverable. Hooked onto 'wp_unique_filename'.
+ *
+ * @param string $filename File name.
+ * @param string $ext File extension.
+ * @return string
+ */
+ private function override_unique_filename( string $filename, string $ext ): string {
+ $length = min( 10, 255 - strlen( $filename ) - 1 );
+ if ( 1 < $length ) {
+ $suffix = strtolower( wp_generate_password( $length, false, false ) );
+ $filename = substr( $filename, 0, strlen( $filename ) - strlen( $ext ) ) . '-' . $suffix . $ext;
+ }
+
+ return $filename;
+ }
+
+ /**
+ * `wp_import_handle_upload()` appends .txt to any file name. This function is hooked onto 'wp_handle_upload_prefilter'
+ * to remove those extra characters.
+ *
+ * @param array $file File details in the form of a $_FILES entry.
+ * @return array Modified file details.
+ */
+ private function remove_txt_from_uploaded_file( array $file ): array {
+ $file['name'] = substr( $file['name'], 0, -4 );
+ return $file;
+ }
+}
diff --git a/plugins/woocommerce/src/Internal/DependencyManagement/ServiceProviders/ImportExportServiceProvider.php b/plugins/woocommerce/src/Internal/DependencyManagement/ServiceProviders/ImportExportServiceProvider.php
new file mode 100644
index 00000000000..58984a41fbf
--- /dev/null
+++ b/plugins/woocommerce/src/Internal/DependencyManagement/ServiceProviders/ImportExportServiceProvider.php
@@ -0,0 +1,35 @@
+share( CSVUploadHelper::class );
+ }
+}
diff --git a/plugins/woocommerce/src/Internal/Logging/RemoteLogger.php b/plugins/woocommerce/src/Internal/Logging/RemoteLogger.php
index 3043cd110fe..a15792fb29b 100644
--- a/plugins/woocommerce/src/Internal/Logging/RemoteLogger.php
+++ b/plugins/woocommerce/src/Internal/Logging/RemoteLogger.php
@@ -88,7 +88,7 @@ class RemoteLogger extends \WC_Log_Handler {
unset( $context['tags'] );
}
- if ( class_exists( '\WC_Tracks' ) ) {
+ if ( class_exists( '\WC_Tracks' ) && function_exists( 'wp_get_current_user' ) ) {
$user = wp_get_current_user();
$blog_details = \WC_Tracks::get_blog_details( $user->ID );
@@ -233,7 +233,7 @@ class RemoteLogger extends \WC_Log_Handler {
}
return true;
- } catch ( \Exception $e ) {
+ } catch ( \Throwable $e ) {
// Log the error locally if the remote logging fails.
error_log( 'Remote logging failed: ' . $e->getMessage() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
return false;
diff --git a/plugins/woocommerce/src/Internal/Utilities/FilesystemUtil.php b/plugins/woocommerce/src/Internal/Utilities/FilesystemUtil.php
index 4bac73265b3..3b91fcbc721 100644
--- a/plugins/woocommerce/src/Internal/Utilities/FilesystemUtil.php
+++ b/plugins/woocommerce/src/Internal/Utilities/FilesystemUtil.php
@@ -31,6 +31,36 @@ class FilesystemUtil {
return $wp_filesystem;
}
+ /**
+ * Recursively creates a directory (if it doesn't exist) and adds an empty index.html and a .htaccess to prevent
+ * directory listing.
+ *
+ * @since 9.3.0
+ *
+ * @param string $path Directory to create.
+ * @throws \Exception In case of error.
+ */
+ public static function mkdir_p_not_indexable( string $path ): void {
+ $wp_fs = self::get_wp_filesystem();
+
+ if ( $wp_fs->is_dir( $path ) ) {
+ return;
+ }
+
+ if ( ! wp_mkdir_p( $path ) ) {
+ throw new \Exception( esc_html( sprintf( 'Could not create directory: %s.', wp_basename( $path ) ) ) );
+ }
+
+ $files = array(
+ '.htaccess' => 'deny from all',
+ 'index.html' => '',
+ );
+
+ foreach ( $files as $name => $content ) {
+ $wp_fs->put_contents( trailingslashit( $path ) . $name, $content );
+ }
+ }
+
/**
* Wrapper to initialize the WP filesystem with defined credentials if they are available.
*
diff --git a/plugins/woocommerce/templates/cart/mini-cart.php b/plugins/woocommerce/templates/cart/mini-cart.php
index ecf51eb96eb..27ae9454260 100644
--- a/plugins/woocommerce/templates/cart/mini-cart.php
+++ b/plugins/woocommerce/templates/cart/mini-cart.php
@@ -14,7 +14,7 @@
*
* @see https://woocommerce.com/document/template-structure/
* @package WooCommerce\Templates
- * @version 9.2.0
+ * @version 9.3.0
*/
defined( 'ABSPATH' ) || exit;
diff --git a/plugins/woocommerce/templates/parts/product-filters.html b/plugins/woocommerce/templates/parts/product-filters.html
index 9e699ccd71d..a4e82272829 100644
--- a/plugins/woocommerce/templates/parts/product-filters.html
+++ b/plugins/woocommerce/templates/parts/product-filters.html
@@ -1,79 +1,28 @@
-
-
-
+
+
+
Filters
+
-
-
Filters
-
+
-
-
-
Active
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
diff --git a/plugins/woocommerce/tests/e2e-pw/envs/default-pressable/playwright.config.js b/plugins/woocommerce/tests/e2e-pw/envs/default-pressable/playwright.config.js
index 259c06b7fc6..4de1709668c 100644
--- a/plugins/woocommerce/tests/e2e-pw/envs/default-pressable/playwright.config.js
+++ b/plugins/woocommerce/tests/e2e-pw/envs/default-pressable/playwright.config.js
@@ -16,6 +16,7 @@ config = {
'**/customize-store/**/*.spec.js',
'**/merchant/**/*.spec.js',
'**/shopper/**/*.spec.js',
+ '**/api-tests/**/*.test.js',
],
grepInvert: /@skip-on-default-pressable/,
},
diff --git a/plugins/woocommerce/tests/e2e-pw/envs/default-wpcom/playwright.config.js b/plugins/woocommerce/tests/e2e-pw/envs/default-wpcom/playwright.config.js
index 62169c1d0dc..08977a04e71 100644
--- a/plugins/woocommerce/tests/e2e-pw/envs/default-wpcom/playwright.config.js
+++ b/plugins/woocommerce/tests/e2e-pw/envs/default-wpcom/playwright.config.js
@@ -7,7 +7,11 @@ config = {
{
name: 'default wpcom',
use: { ...devices[ 'Desktop Chrome' ] },
- testMatch: [ '**/basic.spec.js', '**/shopper/**/*.spec.js' ],
+ testMatch: [
+ '**/basic.spec.js',
+ '**/shopper/**/*.spec.js',
+ '**/api-tests/**/*.test.js',
+ ],
grepInvert: /@skip-on-default-wpcom/,
},
],
diff --git a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/coupons/coupons.test.js b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/coupons/coupons.test.js
index 7c9a8a06565..a4a7cc9abe9 100644
--- a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/coupons/coupons.test.js
+++ b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/coupons/coupons.test.js
@@ -69,26 +69,30 @@ test.describe( 'Coupons API tests', () => {
);
} );
- test( 'can permanently delete a coupon', async ( { request } ) => {
- //call API to delete previously created coupon
- const response = await request.delete(
- `/wp-json/wc/v3/coupons/${ couponId }`,
- {
- data: { force: true },
- }
- );
+ test(
+ 'can permanently delete a coupon',
+ { tag: '@skip-on-default-wpcom' },
+ async ( { request } ) => {
+ //call API to delete previously created coupon
+ const response = await request.delete(
+ `/wp-json/wc/v3/coupons/${ couponId }`,
+ {
+ data: { force: true },
+ }
+ );
- //validate response
- expect( response.status() ).toEqual( 200 );
+ //validate response
+ expect( response.status() ).toEqual( 200 );
- //call API to retrieve previously deleted coupon
- const getCouponResponse = await request.get(
- `/wp-json/wc/v3/coupons/${ couponId }`
- );
+ //call API to retrieve previously deleted coupon
+ const getCouponResponse = await request.get(
+ `/wp-json/wc/v3/coupons/${ couponId }`
+ );
- //validate response
- expect( getCouponResponse.status() ).toEqual( 404 );
- } );
+ //validate response
+ expect( getCouponResponse.status() ).toEqual( 404 );
+ }
+ );
} );
test.describe( 'Batch update coupons', () => {
@@ -180,38 +184,42 @@ test.describe( 'Batch update coupons', () => {
expect( updatedCoupons[ 1 ].amount ).toEqual( '25.00' );
} );
- test( 'can batch delete coupons', async ( { request } ) => {
- // Batch delete the 2 coupons.
- const couponIdsToDelete = expectedCoupons.map( ( { id } ) => id );
- const batchDeletePayload = {
- delete: couponIdsToDelete,
- };
+ test(
+ 'can batch delete coupons',
+ { tag: '@skip-on-default-wpcom' },
+ async ( { request } ) => {
+ // Batch delete the 2 coupons.
+ const couponIdsToDelete = expectedCoupons.map( ( { id } ) => id );
+ const batchDeletePayload = {
+ delete: couponIdsToDelete,
+ };
- //Call API to batch delete the coupons
- const batchDeleteResponse = await request.post(
- 'wp-json/wc/v3/coupons/batch',
- {
- data: batchDeletePayload,
- }
- );
- const batchDeletePayloadJSON = await batchDeleteResponse.json();
-
- // Verify that the response shows the 2 coupons.
- const deletedCouponIds = batchDeletePayloadJSON.delete.map(
- ( { id } ) => id
- );
- expect( batchDeleteResponse.status() ).toEqual( 200 );
- expect( deletedCouponIds ).toEqual( couponIdsToDelete );
-
- // Verify that the 2 deleted coupons cannot be retrieved.
- for ( const couponId of couponIdsToDelete ) {
- //Call the API to attempte to retrieve the coupons
- const response = await request.get(
- `wp-json/wc/v3/coupons/${ couponId }`
+ //Call API to batch delete the coupons
+ const batchDeleteResponse = await request.post(
+ 'wp-json/wc/v3/coupons/batch',
+ {
+ data: batchDeletePayload,
+ }
);
- expect( response.status() ).toEqual( 404 );
+ const batchDeletePayloadJSON = await batchDeleteResponse.json();
+
+ // Verify that the response shows the 2 coupons.
+ const deletedCouponIds = batchDeletePayloadJSON.delete.map(
+ ( { id } ) => id
+ );
+ expect( batchDeleteResponse.status() ).toEqual( 200 );
+ expect( deletedCouponIds ).toEqual( couponIdsToDelete );
+
+ // Verify that the 2 deleted coupons cannot be retrieved.
+ for ( const couponId of couponIdsToDelete ) {
+ //Call the API to attempte to retrieve the coupons
+ const response = await request.get(
+ `wp-json/wc/v3/coupons/${ couponId }`
+ );
+ expect( response.status() ).toEqual( 404 );
+ }
}
- } );
+ );
} );
test.describe( 'List coupons', () => {
diff --git a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/customers/customers-crud.test.js b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/customers/customers-crud.test.js
index 17be7e0a3bc..a93fef4198a 100644
--- a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/customers/customers-crud.test.js
+++ b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/customers/customers-crud.test.js
@@ -2,500 +2,537 @@ const { test, expect } = require( '../../../fixtures/api-tests-fixtures' );
const { admin } = require( '../../../test-data/data' );
const { customer } = require( '../../../data' );
-test.describe( 'Customers API tests: CRUD', () => {
- let customerId;
- let subscriberUserId;
- let subscriberUserCreatedDuringTests = false;
+test.describe(
+ 'Customers API tests: CRUD',
+ { tag: [ '@skip-on-default-pressable', '@skip-on-default-wpcom' ] },
+ () => {
+ let customerId;
+ let subscriberUserId;
+ let subscriberUserCreatedDuringTests = false;
- test.beforeAll( async ( { request } ) => {
- // Call the API to return all users and determine if a
- // subscriber user has been created
- const customersResponse = await request.get(
- '/wp-json/wc/v3/customers',
- {
- params: {
- role: 'all',
- },
- }
- );
- const customersResponseJSON = await customersResponse.json();
-
- for ( const element of customersResponseJSON ) {
- if ( element.role === 'subscriber' ) {
- subscriberUserId = element.id;
- break;
- }
- }
-
- // If a subscriber user has not been created then create one
- if ( ! subscriberUserId ) {
- const now = Date.now();
- const userResponse = await request.post( '/wp-json/wp/v2/users', {
- data: {
- username: `customer_${ now }`,
- email: `customer_${ now }@woocommercecoretestsuite.com`,
- first_name: 'Jane',
- last_name: 'Smith',
- roles: [ 'subscriber' ],
- password: 'password',
- name: 'Jane',
- },
- } );
- const userResponseJSON = await userResponse.json();
- // set subscriber user id to newly created user
- subscriberUserId = userResponseJSON.id;
- subscriberUserCreatedDuringTests = true;
- }
-
- // Verify the subscriber user has been created
- const response = await request.get(
- `/wp-json/wc/v3/customers/${ subscriberUserId }`
- );
- const responseJSON = await response.json();
- // eslint-disable-next-line jest/no-standalone-expect
- expect( response.status() ).toEqual( 200 );
- // eslint-disable-next-line jest/no-standalone-expect
- expect( responseJSON.role ).toEqual( 'subscriber' );
- } );
-
- test.afterAll( async ( { request } ) => {
- // delete subscriber user if one was created during the execution of these tests
- if ( subscriberUserCreatedDuringTests ) {
- await request.delete(
- `/wp-json/wc/v3/customers/${ subscriberUserId }`,
+ test.beforeAll( async ( { request } ) => {
+ // Call the API to return all users and determine if a
+ // subscriber user has been created
+ const customersResponse = await request.get(
+ '/wp-json/wc/v3/customers',
{
- data: {
- force: true,
+ params: {
+ role: 'all',
},
}
);
- }
- } );
+ const customersResponseJSON = await customersResponse.json();
- test.describe( 'Retrieve after env setup', () => {
- /**
- * when the environment is created,
- * (https://github.com/woocommerce/woocommerce/tree/trunk/plugins/woocommerce/tests/e2e-pw#woocommerce-playwright-end-to-end-tests),
- * we have an admin user and a subscriber user that can both be
- * accessed through their ids
- * admin user will have id 1 and subscriber user will have id 2
- * neither of these are returned as part of the get all customers call
- * unless the role 'all' is passed as a search param
- * but they can be accessed by specific id reference
- */
- test( 'can retrieve admin user', async ( { request } ) => {
- // call API to retrieve the previously saved customer
- const response = await request.get( '/wp-json/wc/v3/customers/1' );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( responseJSON.is_paying_customer ).toEqual( false );
- expect( responseJSON.role ).toEqual( 'administrator' );
- // this test was updated to allow for local test setup and other test sites.
- expect( responseJSON.username ).toEqual( admin.username );
- } );
+ for ( const element of customersResponseJSON ) {
+ if ( element.role === 'subscriber' ) {
+ subscriberUserId = element.id;
+ break;
+ }
+ }
- test( 'can retrieve subscriber user', async ( { request } ) => {
- // if environment was created with subscriber user
- // call API to retrieve the customer with id 2
+ // If a subscriber user has not been created then create one
+ if ( ! subscriberUserId ) {
+ const now = Date.now();
+ const userResponse = await request.post(
+ '/wp-json/wp/v2/users',
+ {
+ data: {
+ username: `customer_${ now }`,
+ email: `customer_${ now }@woocommercecoretestsuite.com`,
+ first_name: 'Jane',
+ last_name: 'Smith',
+ roles: [ 'subscriber' ],
+ password: 'password',
+ name: 'Jane',
+ },
+ }
+ );
+ const userResponseJSON = await userResponse.json();
+ // set subscriber user id to newly created user
+ subscriberUserId = userResponseJSON.id;
+ subscriberUserCreatedDuringTests = true;
+ }
+
+ // Verify the subscriber user has been created
const response = await request.get(
`/wp-json/wc/v3/customers/${ subscriberUserId }`
);
const responseJSON = await response.json();
+ // eslint-disable-next-line jest/no-standalone-expect
expect( response.status() ).toEqual( 200 );
- expect( responseJSON.is_paying_customer ).toEqual( false );
+ // eslint-disable-next-line jest/no-standalone-expect
expect( responseJSON.role ).toEqual( 'subscriber' );
} );
- test( 'retrieve user with id 0 is invalid', async ( { request } ) => {
- // call API to retrieve the previously saved customer
- const response = await request.get( '/wp-json/wc/v3/customers/0' );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 404 );
- expect( responseJSON.code ).toEqual(
- 'woocommerce_rest_invalid_id'
- );
- expect( responseJSON.message ).toEqual( 'Invalid resource ID.' );
+ test.afterAll( async ( { request } ) => {
+ // delete subscriber user if one was created during the execution of these tests
+ if ( subscriberUserCreatedDuringTests ) {
+ await request.delete(
+ `/wp-json/wc/v3/customers/${ subscriberUserId }`,
+ {
+ data: {
+ force: true,
+ },
+ }
+ );
+ }
} );
- test( 'can retrieve customers', async ( { request } ) => {
- // call API to retrieve all customers should initially return empty array
- const response = await request.get( '/wp-json/wc/v3/customers' );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( Array.isArray( responseJSON ) ).toBe( true );
- expect( responseJSON.length ).toEqual( 1 );
- } );
-
- // however, if we pass in the search string for role 'all' then all users are returned
- test( 'can retrieve all customers', async ( { request } ) => {
- // call API to retrieve all customers should initially return empty array
- // unless the role 'all' is passed as a search string, in which case the admin
- // and subscriber users will be returned
- const response = await request.get( '/wp-json/wc/v3/customers', {
- params: {
- role: 'all',
- },
- } );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( Array.isArray( responseJSON ) ).toBe( true );
- expect( responseJSON.length ).toBeGreaterThanOrEqual( 3 );
- } );
- } );
-
- test.describe( 'Create a customer', () => {
- test( 'can create a customer', async ( { request } ) => {
- // call API to create a customer
- const response = await request.post( '/wp-json/wc/v3/customers', {
- data: customer,
- } );
- const responseJSON = await response.json();
-
- // Save the customer ID. It will be used by the retrieve, update, and delete tests.
- customerId = responseJSON.id;
-
- expect( response.status() ).toEqual( 201 );
- expect( typeof responseJSON.id ).toEqual( 'number' );
- // Verify that the customer role is 'customer'
- expect( responseJSON.role ).toEqual( 'customer' );
- } );
- } );
-
- test.describe( 'Retrieve after create', () => {
- test( 'can retrieve a customer', async ( { request } ) => {
- // call API to retrieve the previously saved customer
- const response = await request.get(
- `/wp-json/wc/v3/customers/${ customerId }`
- );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( responseJSON.id ).toEqual( customerId );
- expect( responseJSON.is_paying_customer ).toEqual( false );
- expect( responseJSON.role ).toEqual( 'customer' );
- } );
-
- test( 'can retrieve all customers after create', async ( {
- request,
- } ) => {
- // call API to retrieve all customers
- const response = await request.get( '/wp-json/wc/v3/customers' );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( Array.isArray( responseJSON ) ).toBe( true );
- expect( responseJSON.length ).toBeGreaterThan( 0 );
- } );
- } );
-
- test.describe( 'Update a customer', () => {
- test( `can update the admin user/customer`, async ( { request } ) => {
+ test.describe( 'Retrieve after env setup', () => {
/**
- * update customer names (regular, billing and shipping) to admin
- * (these were initialised blank when the environment is created,
- * (https://github.com/woocommerce/woocommerce/tree/trunk/plugins/woocommerce/tests/e2e-pw#woocommerce-playwright-end-to-end-tests
+ * when the environment is created,
+ * (https://github.com/woocommerce/woocommerce/tree/trunk/plugins/woocommerce/tests/e2e-pw#woocommerce-playwright-end-to-end-tests),
+ * we have an admin user and a subscriber user that can both be
+ * accessed through their ids
+ * admin user will have id 1 and subscriber user will have id 2
+ * neither of these are returned as part of the get all customers call
+ * unless the role 'all' is passed as a search param
+ * but they can be accessed by specific id reference
*/
- const response = await request.put( `/wp-json/wc/v3/customers/1`, {
- data: {
- first_name: 'admin',
+ test( 'can retrieve admin user', async ( { request } ) => {
+ // call API to retrieve the previously saved customer
+ const response = await request.get(
+ '/wp-json/wc/v3/customers/1'
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( responseJSON.is_paying_customer ).toEqual( false );
+ expect( responseJSON.role ).toEqual( 'administrator' );
+ // this test was updated to allow for local test setup and other test sites.
+ expect( responseJSON.username ).toEqual( admin.username );
+ } );
+
+ test( 'can retrieve subscriber user', async ( { request } ) => {
+ // if environment was created with subscriber user
+ // call API to retrieve the customer with id 2
+ const response = await request.get(
+ `/wp-json/wc/v3/customers/${ subscriberUserId }`
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( responseJSON.is_paying_customer ).toEqual( false );
+ expect( responseJSON.role ).toEqual( 'subscriber' );
+ } );
+
+ test( 'retrieve user with id 0 is invalid', async ( {
+ request,
+ } ) => {
+ // call API to retrieve the previously saved customer
+ const response = await request.get(
+ '/wp-json/wc/v3/customers/0'
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 404 );
+ expect( responseJSON.code ).toEqual(
+ 'woocommerce_rest_invalid_id'
+ );
+ expect( responseJSON.message ).toEqual(
+ 'Invalid resource ID.'
+ );
+ } );
+
+ test( 'can retrieve customers', async ( { request } ) => {
+ // call API to retrieve all customers should initially return empty array
+ const response = await request.get(
+ '/wp-json/wc/v3/customers'
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( Array.isArray( responseJSON ) ).toBe( true );
+ expect( responseJSON.length ).toEqual( 1 );
+ } );
+
+ // however, if we pass in the search string for role 'all' then all users are returned
+ test( 'can retrieve all customers', async ( { request } ) => {
+ // call API to retrieve all customers should initially return empty array
+ // unless the role 'all' is passed as a search string, in which case the admin
+ // and subscriber users will be returned
+ const response = await request.get(
+ '/wp-json/wc/v3/customers',
+ {
+ params: {
+ role: 'all',
+ },
+ }
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( Array.isArray( responseJSON ) ).toBe( true );
+ expect( responseJSON.length ).toBeGreaterThanOrEqual( 3 );
+ } );
+ } );
+
+ test.describe( 'Create a customer', () => {
+ test( 'can create a customer', async ( { request } ) => {
+ // call API to create a customer
+ const response = await request.post(
+ '/wp-json/wc/v3/customers',
+ {
+ data: customer,
+ }
+ );
+ const responseJSON = await response.json();
+
+ // Save the customer ID. It will be used by the retrieve, update, and delete tests.
+ customerId = responseJSON.id;
+
+ expect( response.status() ).toEqual( 201 );
+ expect( typeof responseJSON.id ).toEqual( 'number' );
+ // Verify that the customer role is 'customer'
+ expect( responseJSON.role ).toEqual( 'customer' );
+ } );
+ } );
+
+ test.describe( 'Retrieve after create', () => {
+ test( 'can retrieve a customer', async ( { request } ) => {
+ // call API to retrieve the previously saved customer
+ const response = await request.get(
+ `/wp-json/wc/v3/customers/${ customerId }`
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( responseJSON.id ).toEqual( customerId );
+ expect( responseJSON.is_paying_customer ).toEqual( false );
+ expect( responseJSON.role ).toEqual( 'customer' );
+ } );
+
+ test( 'can retrieve all customers after create', async ( {
+ request,
+ } ) => {
+ // call API to retrieve all customers
+ const response = await request.get(
+ '/wp-json/wc/v3/customers'
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( Array.isArray( responseJSON ) ).toBe( true );
+ expect( responseJSON.length ).toBeGreaterThan( 0 );
+ } );
+ } );
+
+ test.describe( 'Update a customer', () => {
+ test( `can update the admin user/customer`, async ( {
+ request,
+ } ) => {
+ /**
+ * update customer names (regular, billing and shipping) to admin
+ * (these were initialised blank when the environment is created,
+ * (https://github.com/woocommerce/woocommerce/tree/trunk/plugins/woocommerce/tests/e2e-pw#woocommerce-playwright-end-to-end-tests
+ */
+ const response = await request.put(
+ `/wp-json/wc/v3/customers/1`,
+ {
+ data: {
+ first_name: 'admin',
+ billing: {
+ first_name: 'admin',
+ },
+ shipping: {
+ first_name: 'admin',
+ },
+ },
+ }
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( responseJSON.first_name ).toEqual( 'admin' );
+ expect( responseJSON.billing.first_name ).toEqual( 'admin' );
+ expect( responseJSON.shipping.first_name ).toEqual( 'admin' );
+ } );
+
+ test( 'retrieve after update admin', async ( { request } ) => {
+ // call API to retrieve the admin customer we updated above
+ const response = await request.get(
+ '/wp-json/wc/v3/customers/1'
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( responseJSON.first_name ).toEqual( 'admin' );
+ expect( responseJSON.billing.first_name ).toEqual( 'admin' );
+ expect( responseJSON.shipping.first_name ).toEqual( 'admin' );
+ } );
+
+ test( `can update the subscriber user/customer`, async ( {
+ request,
+ } ) => {
+ // update customer names (billing and shipping) to Jane
+ // (these were initialised blank, only regular first_name was populated)
+ const response = await request.put(
+ `/wp-json/wc/v3/customers/${ subscriberUserId }`,
+ {
+ data: {
+ billing: {
+ first_name: 'Jane',
+ },
+ shipping: {
+ first_name: 'Jane',
+ },
+ },
+ }
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( responseJSON.first_name ).toEqual( 'Jane' );
+ expect( responseJSON.billing.first_name ).toEqual( 'Jane' );
+ expect( responseJSON.shipping.first_name ).toEqual( 'Jane' );
+ } );
+
+ test( 'retrieve after update subscriber', async ( { request } ) => {
+ // call API to retrieve the subscriber customer we updated above
+ const response = await request.get(
+ `/wp-json/wc/v3/customers/${ subscriberUserId }`
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( responseJSON.first_name ).toEqual( 'Jane' );
+ expect( responseJSON.billing.first_name ).toEqual( 'Jane' );
+ expect( responseJSON.shipping.first_name ).toEqual( 'Jane' );
+ } );
+
+ test( `can update a customer`, async ( { request } ) => {
+ // update customer names (regular, billing and shipping) from John to Jack
+ const response = await request.put(
+ `/wp-json/wc/v3/customers/${ customerId }`,
+ {
+ data: {
+ first_name: 'Jack',
+ billing: {
+ first_name: 'Jack',
+ },
+ shipping: {
+ first_name: 'Jack',
+ },
+ },
+ }
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( responseJSON.first_name ).toEqual( 'Jack' );
+ expect( responseJSON.billing.first_name ).toEqual( 'Jack' );
+ expect( responseJSON.shipping.first_name ).toEqual( 'Jack' );
+ } );
+
+ test( 'retrieve after update customer', async ( { request } ) => {
+ // call API to retrieve the updated customer we created above
+ const response = await request.get(
+ `/wp-json/wc/v3/customers/${ customerId }`
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( responseJSON.first_name ).toEqual( 'Jack' );
+ expect( responseJSON.billing.first_name ).toEqual( 'Jack' );
+ expect( responseJSON.shipping.first_name ).toEqual( 'Jack' );
+ } );
+ } );
+
+ test.describe( 'Delete a customer', () => {
+ test( 'can permanently delete an customer', async ( {
+ request,
+ } ) => {
+ // Delete the customer.
+ const response = await request.delete(
+ `/wp-json/wc/v3/customers/${ customerId }`,
+ {
+ data: {
+ force: true,
+ },
+ }
+ );
+ expect( response.status() ).toEqual( 200 );
+
+ // Verify that the customer can no longer be retrieved.
+ const getDeletedCustomerResponse = await request.get(
+ `/wp-json/wc/v3/customers/${ customer }`
+ );
+ expect( getDeletedCustomerResponse.status() ).toEqual( 404 );
+ } );
+ } );
+
+ test.describe( 'Batch update customers', () => {
+ /**
+ * 2 Customers to be created in one batch.
+ */
+ const expectedCustomers = [
+ {
+ email: 'john.doe2@example.com',
+ first_name: 'John',
+ last_name: 'Doe',
+ username: 'john.doe2',
billing: {
- first_name: 'admin',
+ first_name: 'John',
+ last_name: 'Doe',
+ company: '',
+ address_1: '969 Market',
+ address_2: '',
+ city: 'San Francisco',
+ state: 'CA',
+ postcode: '94103',
+ country: 'US',
+ email: 'john.doe2@example.com',
+ phone: '(555) 555-5555',
},
shipping: {
- first_name: 'admin',
+ first_name: 'John',
+ last_name: 'Doe',
+ company: '',
+ address_1: '969 Market',
+ address_2: '',
+ city: 'San Francisco',
+ state: 'CA',
+ postcode: '94103',
+ country: 'US',
},
},
- } );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( responseJSON.first_name ).toEqual( 'admin' );
- expect( responseJSON.billing.first_name ).toEqual( 'admin' );
- expect( responseJSON.shipping.first_name ).toEqual( 'admin' );
- } );
-
- test( 'retrieve after update admin', async ( { request } ) => {
- // call API to retrieve the admin customer we updated above
- const response = await request.get( '/wp-json/wc/v3/customers/1' );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( responseJSON.first_name ).toEqual( 'admin' );
- expect( responseJSON.billing.first_name ).toEqual( 'admin' );
- expect( responseJSON.shipping.first_name ).toEqual( 'admin' );
- } );
-
- test( `can update the subscriber user/customer`, async ( {
- request,
- } ) => {
- // update customer names (billing and shipping) to Jane
- // (these were initialised blank, only regular first_name was populated)
- const response = await request.put(
- `/wp-json/wc/v3/customers/${ subscriberUserId }`,
{
- data: {
- billing: {
- first_name: 'Jane',
- },
- shipping: {
- first_name: 'Jane',
- },
- },
- }
- );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( responseJSON.first_name ).toEqual( 'Jane' );
- expect( responseJSON.billing.first_name ).toEqual( 'Jane' );
- expect( responseJSON.shipping.first_name ).toEqual( 'Jane' );
- } );
-
- test( 'retrieve after update subscriber', async ( { request } ) => {
- // call API to retrieve the subscriber customer we updated above
- const response = await request.get(
- `/wp-json/wc/v3/customers/${ subscriberUserId }`
- );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( responseJSON.first_name ).toEqual( 'Jane' );
- expect( responseJSON.billing.first_name ).toEqual( 'Jane' );
- expect( responseJSON.shipping.first_name ).toEqual( 'Jane' );
- } );
-
- test( `can update a customer`, async ( { request } ) => {
- // update customer names (regular, billing and shipping) from John to Jack
- const response = await request.put(
- `/wp-json/wc/v3/customers/${ customerId }`,
- {
- data: {
- first_name: 'Jack',
- billing: {
- first_name: 'Jack',
- },
- shipping: {
- first_name: 'Jack',
- },
- },
- }
- );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( responseJSON.first_name ).toEqual( 'Jack' );
- expect( responseJSON.billing.first_name ).toEqual( 'Jack' );
- expect( responseJSON.shipping.first_name ).toEqual( 'Jack' );
- } );
-
- test( 'retrieve after update customer', async ( { request } ) => {
- // call API to retrieve the updated customer we created above
- const response = await request.get(
- `/wp-json/wc/v3/customers/${ customerId }`
- );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( responseJSON.first_name ).toEqual( 'Jack' );
- expect( responseJSON.billing.first_name ).toEqual( 'Jack' );
- expect( responseJSON.shipping.first_name ).toEqual( 'Jack' );
- } );
- } );
-
- test.describe( 'Delete a customer', () => {
- test( 'can permanently delete an customer', async ( { request } ) => {
- // Delete the customer.
- const response = await request.delete(
- `/wp-json/wc/v3/customers/${ customerId }`,
- {
- data: {
- force: true,
- },
- }
- );
- expect( response.status() ).toEqual( 200 );
-
- // Verify that the customer can no longer be retrieved.
- const getDeletedCustomerResponse = await request.get(
- `/wp-json/wc/v3/customers/${ customer }`
- );
- expect( getDeletedCustomerResponse.status() ).toEqual( 404 );
- } );
- } );
-
- test.describe( 'Batch update customers', () => {
- /**
- * 2 Customers to be created in one batch.
- */
- const expectedCustomers = [
- {
- email: 'john.doe2@example.com',
- first_name: 'John',
- last_name: 'Doe',
- username: 'john.doe2',
- billing: {
- first_name: 'John',
- last_name: 'Doe',
- company: '',
- address_1: '969 Market',
- address_2: '',
- city: 'San Francisco',
- state: 'CA',
- postcode: '94103',
- country: 'US',
- email: 'john.doe2@example.com',
- phone: '(555) 555-5555',
- },
- shipping: {
- first_name: 'John',
- last_name: 'Doe',
- company: '',
- address_1: '969 Market',
- address_2: '',
- city: 'San Francisco',
- state: 'CA',
- postcode: '94103',
- country: 'US',
- },
- },
- {
- email: 'joao.silva2@example.com',
- first_name: 'João',
- last_name: 'Silva',
- username: 'joao.silva2',
- billing: {
- first_name: 'João',
- last_name: 'Silva',
- company: '',
- address_1: 'Av. Brasil, 432',
- address_2: '',
- city: 'Rio de Janeiro',
- state: 'RJ',
- postcode: '12345-000',
- country: 'BR',
email: 'joao.silva2@example.com',
- phone: '(55) 5555-5555',
- },
- shipping: {
first_name: 'João',
last_name: 'Silva',
- company: '',
- address_1: 'Av. Brasil, 432',
- address_2: '',
- city: 'Rio de Janeiro',
- state: 'RJ',
- postcode: '12345-000',
- country: 'BR',
+ username: 'joao.silva2',
+ billing: {
+ first_name: 'João',
+ last_name: 'Silva',
+ company: '',
+ address_1: 'Av. Brasil, 432',
+ address_2: '',
+ city: 'Rio de Janeiro',
+ state: 'RJ',
+ postcode: '12345-000',
+ country: 'BR',
+ email: 'joao.silva2@example.com',
+ phone: '(55) 5555-5555',
+ },
+ shipping: {
+ first_name: 'João',
+ last_name: 'Silva',
+ company: '',
+ address_1: 'Av. Brasil, 432',
+ address_2: '',
+ city: 'Rio de Janeiro',
+ state: 'RJ',
+ postcode: '12345-000',
+ country: 'BR',
+ },
},
- },
- ];
+ ];
- // set payload to use batch create: action
- const batchCreate2CustomersPayload = {
- create: expectedCustomers,
- };
-
- test( 'can batch create customers', async ( { request } ) => {
- // Batch create 2 new customers.
- // call API to batch create customers
- const response = await request.post(
- 'wp-json/wc/v3/customers/batch',
- {
- data: batchCreate2CustomersPayload,
- }
- );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
-
- // Verify that the 2 new customers were created
- const actualCustomers = responseJSON.create;
- expect( actualCustomers ).toHaveLength( expectedCustomers.length );
-
- for ( let i = 0; i < actualCustomers.length; i++ ) {
- const { id, first_name } = actualCustomers[ i ];
- const expectedCustomerName = expectedCustomers[ i ].first_name;
-
- expect( id ).toBeDefined();
- expect( first_name ).toEqual( expectedCustomerName );
-
- // Save the customer id
- expectedCustomers[ i ].id = id;
- }
- } );
-
- test( 'can batch update customers', async ( { request } ) => {
- // set payload to use batch update: action
- const batchUpdatePayload = {
- update: [
- {
- id: expectedCustomers[ 0 ].id,
- email: 'emailupdated@example.com',
- },
- {
- id: expectedCustomers[ 1 ].id,
- billing: {
- address_1: '123 Addressupdate Street',
- },
- },
- ],
+ // set payload to use batch create: action
+ const batchCreate2CustomersPayload = {
+ create: expectedCustomers,
};
- // Call API to update the customers
- const response = await request.post(
- 'wp-json/wc/v3/customers/batch',
- {
- data: batchUpdatePayload,
- }
- );
- const responseJSON = await response.json();
-
- // Verify the response code and the number of customers that were updated.
- const updatedCustomers = responseJSON.update;
- expect( response.status() ).toEqual( 200 );
- expect( updatedCustomers ).toHaveLength( 2 );
-
- // Verify that the 1st customer was updated to have a new email address.
- expect( updatedCustomers[ 0 ].id ).toEqual(
- expectedCustomers[ 0 ].id
- );
- expect( updatedCustomers[ 0 ].email ).toEqual(
- 'emailupdated@example.com'
- );
-
- // Verify that the amount of the 2nd customer was updated to have a new billing address.
- expect( updatedCustomers[ 1 ].id ).toEqual(
- expectedCustomers[ 1 ].id
- );
- expect( updatedCustomers[ 1 ].billing.address_1 ).toEqual(
- '123 Addressupdate Street'
- );
- } );
-
- test( 'can batch delete customers', async ( { request } ) => {
- // Batch delete the 2 customers.
- const customerIdsToDelete = expectedCustomers.map(
- ( { id } ) => id
- );
- const batchDeletePayload = {
- delete: customerIdsToDelete,
- };
-
- //Call API to batch delete the customers
- const response = await request.post(
- 'wp-json/wc/v3/customers/batch',
- {
- data: batchDeletePayload,
- }
- );
- const responseJSON = await response.json();
-
- // Verify that the response shows the 2 customers.
- const deletedCustomerIds = responseJSON.delete.map(
- ( { id } ) => id
- );
- expect( response.status() ).toEqual( 200 );
- expect( deletedCustomerIds ).toEqual( customerIdsToDelete );
-
- // Verify that the 2 deleted customers cannot be retrieved.
- for ( const id of customerIdsToDelete ) {
- //Call the API to attempte to retrieve the customers
- const r = await request.get(
- `wp-json/wc/v3/customers/${ id }`
+ test( 'can batch create customers', async ( { request } ) => {
+ // Batch create 2 new customers.
+ // call API to batch create customers
+ const response = await request.post(
+ 'wp-json/wc/v3/customers/batch',
+ {
+ data: batchCreate2CustomersPayload,
+ }
);
- expect( r.status() ).toEqual( 404 );
- }
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+
+ // Verify that the 2 new customers were created
+ const actualCustomers = responseJSON.create;
+ expect( actualCustomers ).toHaveLength(
+ expectedCustomers.length
+ );
+
+ for ( let i = 0; i < actualCustomers.length; i++ ) {
+ const { id, first_name } = actualCustomers[ i ];
+ const expectedCustomerName =
+ expectedCustomers[ i ].first_name;
+
+ expect( id ).toBeDefined();
+ expect( first_name ).toEqual( expectedCustomerName );
+
+ // Save the customer id
+ expectedCustomers[ i ].id = id;
+ }
+ } );
+
+ test( 'can batch update customers', async ( { request } ) => {
+ // set payload to use batch update: action
+ const batchUpdatePayload = {
+ update: [
+ {
+ id: expectedCustomers[ 0 ].id,
+ email: 'emailupdated@example.com',
+ },
+ {
+ id: expectedCustomers[ 1 ].id,
+ billing: {
+ address_1: '123 Addressupdate Street',
+ },
+ },
+ ],
+ };
+
+ // Call API to update the customers
+ const response = await request.post(
+ 'wp-json/wc/v3/customers/batch',
+ {
+ data: batchUpdatePayload,
+ }
+ );
+ const responseJSON = await response.json();
+
+ // Verify the response code and the number of customers that were updated.
+ const updatedCustomers = responseJSON.update;
+ expect( response.status() ).toEqual( 200 );
+ expect( updatedCustomers ).toHaveLength( 2 );
+
+ // Verify that the 1st customer was updated to have a new email address.
+ expect( updatedCustomers[ 0 ].id ).toEqual(
+ expectedCustomers[ 0 ].id
+ );
+ expect( updatedCustomers[ 0 ].email ).toEqual(
+ 'emailupdated@example.com'
+ );
+
+ // Verify that the amount of the 2nd customer was updated to have a new billing address.
+ expect( updatedCustomers[ 1 ].id ).toEqual(
+ expectedCustomers[ 1 ].id
+ );
+ expect( updatedCustomers[ 1 ].billing.address_1 ).toEqual(
+ '123 Addressupdate Street'
+ );
+ } );
+
+ test( 'can batch delete customers', async ( { request } ) => {
+ // Batch delete the 2 customers.
+ const customerIdsToDelete = expectedCustomers.map(
+ ( { id } ) => id
+ );
+ const batchDeletePayload = {
+ delete: customerIdsToDelete,
+ };
+
+ //Call API to batch delete the customers
+ const response = await request.post(
+ 'wp-json/wc/v3/customers/batch',
+ {
+ data: batchDeletePayload,
+ }
+ );
+ const responseJSON = await response.json();
+
+ // Verify that the response shows the 2 customers.
+ const deletedCustomerIds = responseJSON.delete.map(
+ ( { id } ) => id
+ );
+ expect( response.status() ).toEqual( 200 );
+ expect( deletedCustomerIds ).toEqual( customerIdsToDelete );
+
+ // Verify that the 2 deleted customers cannot be retrieved.
+ for ( const id of customerIdsToDelete ) {
+ //Call the API to attempte to retrieve the customers
+ const r = await request.get(
+ `wp-json/wc/v3/customers/${ id }`
+ );
+ expect( r.status() ).toEqual( 404 );
+ }
+ } );
} );
- } );
-} );
+ }
+);
diff --git a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/orders/order-complex.test.js b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/orders/order-complex.test.js
index 5308ecdcfa1..90df59a1b9c 100644
--- a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/orders/order-complex.test.js
+++ b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/orders/order-complex.test.js
@@ -208,48 +208,52 @@ test.describe( 'Orders API test', () => {
} );
} );
- test( 'can add complex order', async ( { request } ) => {
- //ensure tax calculations are enabled
- await request.put(
- '/wp-json/wc/v3/settings/general/woocommerce_calc_taxes',
- {
- data: {
- value: 'yes',
- },
+ test(
+ 'can add complex order',
+ { tag: [ '@skip-on-default-pressable', '@skip-on-default-wpcom' ] },
+ async ( { request } ) => {
+ //ensure tax calculations are enabled
+ await request.put(
+ '/wp-json/wc/v3/settings/general/woocommerce_calc_taxes',
+ {
+ data: {
+ value: 'yes',
+ },
+ }
+ );
+
+ // Create the complex order and save its ID.
+ const response = await request.post( '/wp-json/wc/v3/orders', {
+ data: order,
+ } );
+ const responseJSON = await response.json();
+
+ order.id = responseJSON.id;
+
+ expect( response.status() ).toEqual( 201 );
+
+ // Verify order and tax totals
+ expect( responseJSON.total ).toEqual( expectedOrderTotal );
+ expect( responseJSON.total_tax ).toEqual( expectedTaxTotal );
+
+ // Verify total tax of each product line item
+ const expectedTaxTotalsPerLineItem = [
+ [ simpleProduct, expectedSimpleProductTaxTotal ],
+ [ variableProduct, expectedVariableProductTaxTotal ],
+ [ groupedProduct, expectedSimpleProductTaxTotal ],
+ [ externalProduct, expectedExternalProductTaxTotal ],
+ ];
+ for ( const [
+ product,
+ expectedLineTaxTotal,
+ ] of expectedTaxTotalsPerLineItem ) {
+ const { total_tax: actualLineTaxTotal } =
+ responseJSON.line_items.find(
+ ( { product_id } ) => product_id === product.id
+ );
+
+ expect( actualLineTaxTotal ).toEqual( expectedLineTaxTotal );
}
- );
-
- // Create the complex order and save its ID.
- const response = await request.post( '/wp-json/wc/v3/orders', {
- data: order,
- } );
- const responseJSON = await response.json();
-
- order.id = responseJSON.id;
-
- expect( response.status() ).toEqual( 201 );
-
- // Verify order and tax totals
- expect( responseJSON.total ).toEqual( expectedOrderTotal );
- expect( responseJSON.total_tax ).toEqual( expectedTaxTotal );
-
- // Verify total tax of each product line item
- const expectedTaxTotalsPerLineItem = [
- [ simpleProduct, expectedSimpleProductTaxTotal ],
- [ variableProduct, expectedVariableProductTaxTotal ],
- [ groupedProduct, expectedSimpleProductTaxTotal ],
- [ externalProduct, expectedExternalProductTaxTotal ],
- ];
- for ( const [
- product,
- expectedLineTaxTotal,
- ] of expectedTaxTotalsPerLineItem ) {
- const { total_tax: actualLineTaxTotal } =
- responseJSON.line_items.find(
- ( { product_id } ) => product_id === product.id
- );
-
- expect( actualLineTaxTotal ).toEqual( expectedLineTaxTotal );
}
- } );
+ );
} );
diff --git a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/orders/orders.test.js b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/orders/orders.test.js
index f0164b40982..b6a556ce2de 100644
--- a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/orders/orders.test.js
+++ b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/orders/orders.test.js
@@ -34,3232 +34,3274 @@ const updatedCustomerShipping = {
phone: '123456789',
};
-test.describe.serial( 'Orders API tests', () => {
- let orderId, sampleData;
+test.describe.serial(
+ 'Orders API tests',
+ { tag: [ '@skip-on-default-pressable', '@skip-on-default-wpcom' ] },
+ () => {
+ let orderId, sampleData;
- test.beforeAll( async ( { request } ) => {
- const createSampleCategories = async () => {
- const clothing = await request.post(
- '/wp-json/wc/v3/products/categories',
- {
- data: {
- name: 'Clothing',
- },
- }
- );
- const clothingJSON = await clothing.json();
-
- const accessories = await request.post(
- '/wp-json/wc/v3/products/categories',
- {
- data: {
- name: 'Accessories',
- parent: clothingJSON.id,
- },
- }
- );
- const accessoriesJSON = await accessories.json();
-
- const hoodies = await request.post(
- '/wp-json/wc/v3/products/categories',
- {
- data: {
- name: 'Hoodies',
- parent: clothingJSON.id,
- },
- }
- );
- const hoodiesJSON = await hoodies.json();
-
- const tshirts = await request.post(
- '/wp-json/wc/v3/products/categories',
- {
- data: {
- name: 'Tshirts',
- parent: clothingJSON.id,
- },
- }
- );
- const tshirtsJSON = await tshirts.json();
-
- const decor = await request.post(
- '/wp-json/wc/v3/products/categories',
- {
- data: {
- name: 'Decor',
- },
- }
- );
- const decorJSON = await decor.json();
-
- const music = await request.post(
- '/wp-json/wc/v3/products/categories',
- {
- data: {
- name: 'Music',
- },
- }
- );
- const musicJSON = await music.json();
-
- return {
- clothingJSON,
- accessoriesJSON,
- hoodiesJSON,
- tshirtsJSON,
- decorJSON,
- musicJSON,
- };
- };
-
- const createSampleAttributes = async () => {
- const color = await request.post(
- '/wp-json/wc/v3/products/attributes',
- {
- data: {
- name: 'Color',
- },
- }
- );
- const colorJSON = await color.json();
-
- const size = await request.post(
- '/wp-json/wc/v3/products/attributes',
- {
- data: {
- name: 'Size',
- },
- }
- );
- const sizeJSON = await size.json();
-
- const colorNames = [ 'Blue', 'Gray', 'Green', 'Red', 'Yellow' ];
-
- const colorNamesObjectArray = colorNames.map( ( name ) => ( {
- name,
- } ) );
-
- const colors = await request.post(
- `/wp-json/wc/v3/products/attributes/${ colorJSON.id }/terms/batch`,
- {
- data: {
- create: colorNamesObjectArray,
- },
- }
- );
-
- const colorsJSON = await colors.json();
-
- const sizeNames = [ 'Large', 'Medium', 'Small' ];
-
- const sizeNamesObjectArray = sizeNames.map( ( name ) => ( {
- name,
- } ) );
-
- const sizes = await request.post(
- `/wp-json/wc/v3/products/attributes/${ sizeJSON.id }/terms/batch`,
- {
- data: {
- create: sizeNamesObjectArray,
- },
- }
- );
- const sizesJSON = await sizes.json();
-
- return {
- colorJSON,
- colors: colorsJSON.create,
- sizeJSON,
- sizes: sizesJSON.create,
- };
- };
-
- const createSampleTags = async () => {
- const cool = await request.post( '/wp-json/wc/v3/products/tags', {
- data: {
- name: 'Cool',
- },
- } );
- const coolJSON = await cool.json();
-
- return {
- coolJSON,
- };
- };
-
- const createSampleShippingClasses = async () => {
- const freight = await request.post(
- '/wp-json/wc/v3/products/shipping_classes',
- {
- data: {
- name: 'Freight',
- },
- }
- );
- const freightJSON = await freight.json();
-
- return {
- freightJSON,
- };
- };
-
- const createSampleTaxClasses = async () => {
- //check to see if Reduced Rate tax class exists - if not, create it
- let reducedRate = await request.get(
- '/wp-json/wc/v3/taxes/classes/reduced-rate'
- );
- let reducedRateJSON = await reducedRate.json();
- expect( Array.isArray( reducedRateJSON ) ).toBe( true );
-
- //if tax class does not exist then create it
- if ( reducedRateJSON.length < 1 ) {
- reducedRate = await request.post(
- '/wp-json/wc/v3/taxes/classes',
+ test.beforeAll( async ( { request } ) => {
+ const createSampleCategories = async () => {
+ const clothing = await request.post(
+ '/wp-json/wc/v3/products/categories',
{
data: {
- name: 'Reduced Rate',
+ name: 'Clothing',
},
}
);
- reducedRateJSON = await reducedRate.json();
- return { reducedRateJSON };
- }
+ const clothingJSON = await clothing.json();
- // return an empty object as nothing new was created so nothing will
- // need deleted during cleanup
- return {};
- };
-
- const createSampleSimpleProducts = async (
- categories,
- attributes,
- tags
- ) => {
- const description =
- '
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.
\n';
-
- const simpleProducts = await request.post(
- '/wp-json/wc/v3/products/batch',
- {
- data: {
- create: [
- {
- name: 'Beanie with Logo oxo',
- date_created_gmt: '2021-09-01T15:50:20',
- type: 'simple',
- status: 'publish',
- featured: false,
- catalog_visibility: 'visible',
- description,
- short_description:
- '
This is a simple product.
\n',
- sku: 'Woo-beanie-logo',
- price: '18',
- regular_price: '20',
- sale_price: '18',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: true,
- purchasable: true,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '0.2',
- dimensions: {
- length: '6',
- width: '4',
- height: '1',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.accessoriesJSON.id,
- },
- ],
- tags: [],
- attributes: [
- {
- id: attributes.colorJSON.id,
- position: 0,
- visible: true,
- variation: false,
- options: [ 'Red' ],
- },
- ],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [ 62, 63, 61, 60 ],
- stock_status: 'instock',
- },
- {
- name: 'T-Shirt with Logo oxo',
- date_created_gmt: '2021-09-02T15:50:20',
- type: 'simple',
- status: 'publish',
- featured: false,
- catalog_visibility: 'visible',
- description,
- short_description:
- '
This is a simple product.
\n',
- sku: 'Woo-tshirt-logo',
- price: '18',
- regular_price: '18',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- purchasable: true,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '0.5',
- dimensions: {
- length: '10',
- width: '12',
- height: '0.5',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.tshirtsJSON.id,
- },
- ],
- tags: [],
- attributes: [
- {
- id: attributes.colorJSON.id,
- position: 0,
- visible: true,
- variation: false,
- options: [ 'Gray' ],
- },
- ],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [ 59, 67, 66, 56 ],
- stock_status: 'instock',
- },
- {
- name: 'Single oxo',
- date_created_gmt: '2021-09-03T15:50:19',
- type: 'simple',
- status: 'publish',
- featured: false,
- catalog_visibility: 'visible',
- description,
- short_description:
- '
This is a simple, virtual product.
\n',
- sku: 'woo-single',
- price: '2',
- regular_price: '3',
- sale_price: '2',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: true,
- purchasable: true,
- total_sales: 0,
- virtual: true,
- downloadable: true,
- downloads: [
- {
- id: '2579cf07-8b08-4c25-888a-b6258dd1f035',
- name: 'Single',
- file: 'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg',
- },
- ],
- download_limit: 1,
- download_expiry: 1,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '',
- dimensions: {
- length: '',
- width: '',
- height: '',
- },
- shipping_required: false,
- shipping_taxable: false,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.musicJSON.id,
- },
- ],
- tags: [],
- attributes: [],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [ 68 ],
- stock_status: 'instock',
- },
- {
- name: 'Album oxo',
- date_created_gmt: '2021-09-04T15:50:19',
- type: 'simple',
- status: 'publish',
- featured: false,
- catalog_visibility: 'visible',
- description,
- short_description:
- '
This is a simple, virtual product.
\n',
- sku: 'woo-album',
- price: '15',
- regular_price: '15',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- purchasable: true,
- total_sales: 0,
- virtual: true,
- downloadable: true,
- downloads: [
- {
- id: 'cc10249f-1de2-44d4-93d3-9f88ae629f76',
- name: 'Single 1',
- file: 'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg',
- },
- {
- id: 'aea8ef69-ccdc-4d83-8e21-3c395ebb9411',
- name: 'Single 2',
- file: 'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/album.jpg',
- },
- ],
- download_limit: 1,
- download_expiry: 1,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '',
- dimensions: {
- length: '',
- width: '',
- height: '',
- },
- shipping_required: false,
- shipping_taxable: false,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.musicJSON.id,
- },
- ],
- tags: [],
- attributes: [],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [ 69 ],
- stock_status: 'instock',
- },
- {
- name: 'Polo oxo',
- date_created_gmt: '2021-09-05T15:50:19',
- type: 'simple',
- status: 'pending',
- featured: false,
- catalog_visibility: 'visible',
- description,
- short_description:
- '
This is a simple product.
\n',
- sku: 'woo-polo',
- price: '20',
- regular_price: '20',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- purchasable: true,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '0.8',
- dimensions: {
- length: '6',
- width: '5',
- height: '1',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.tshirtsJSON.id,
- },
- ],
- tags: [],
- attributes: [
- {
- id: attributes.colorJSON.id,
- position: 0,
- visible: true,
- variation: false,
- options: [ 'Blue' ],
- },
- ],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [ 59, 56, 66, 76 ],
- stock_status: 'instock',
- },
- {
- name: 'Long Sleeve Tee oxo',
- date_created_gmt: '2021-09-06T15:50:19',
- type: 'simple',
- status: 'publish',
- featured: false,
- catalog_visibility: 'visible',
- description,
- short_description:
- '
This is a simple product.
\n',
- sku: 'woo-long-sleeve-tee',
- price: '25',
- regular_price: '25',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- purchasable: true,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '1',
- dimensions: {
- length: '7',
- width: '5',
- height: '1',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: 'freight',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.tshirtsJSON.id,
- },
- ],
- tags: [],
- attributes: [
- {
- id: attributes.colorJSON.id,
- position: 0,
- visible: true,
- variation: false,
- options: [ 'Green' ],
- },
- ],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [ 59, 56, 76, 67 ],
- stock_status: 'instock',
- },
- {
- name: 'Hoodie with Zipper oxo',
- date_created_gmt: '2021-09-07T15:50:19',
- type: 'simple',
- status: 'publish',
- featured: true,
- catalog_visibility: 'visible',
- description,
- short_description:
- '
This is a simple product.
\n',
- sku: 'woo-hoodie-with-zipper',
- price: '45',
- regular_price: '45',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- purchasable: true,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '2',
- dimensions: {
- length: '8',
- width: '6',
- height: '2',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.hoodiesJSON.id,
- },
- ],
- tags: [],
- attributes: [],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [ 57, 58 ],
- stock_status: 'instock',
- },
- {
- name: 'Hoodie with Pocket oxo',
- date_created_gmt: '2021-09-08T15:50:19',
- type: 'simple',
- status: 'publish',
- featured: true,
- catalog_visibility: 'hidden',
- description,
- short_description:
- '
This is a simple product.
\n',
- sku: 'woo-hoodie-with-pocket',
- price: '35',
- regular_price: '45',
- sale_price: '35',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: true,
- purchasable: true,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '3',
- dimensions: {
- length: '10',
- width: '8',
- height: '2',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.hoodiesJSON.id,
- },
- ],
- tags: [
- {
- id: tags.coolJSON.id,
- },
- ],
- attributes: [
- {
- id: attributes.colorJSON.id,
- position: 0,
- visible: true,
- variation: false,
- options: [ 'Gray' ],
- },
- ],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [ 65, 57, 58 ],
- stock_status: 'instock',
- },
- {
- name: 'Sunglasses oxo',
- date_created_gmt: '2021-09-09T15:50:19',
- type: 'simple',
- status: 'publish',
- featured: true,
- catalog_visibility: 'visible',
- description,
- short_description:
- '
This is a simple product.
\n',
- sku: 'woo-sunglasses',
- price: '90',
- regular_price: '90',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- purchasable: true,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: 'reduced-rate',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '0.2',
- dimensions: {
- length: '4',
- width: '1.4',
- height: '1',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.accessoriesJSON.id,
- },
- ],
- tags: [
- {
- id: tags.coolJSON.id,
- },
- ],
- attributes: [],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [ 60, 62, 77, 61 ],
- stock_status: 'instock',
- },
- {
- name: 'Cap oxo',
- date_created_gmt: '2021-09-10T15:50:19',
- type: 'simple',
- status: 'publish',
- featured: true,
- catalog_visibility: 'visible',
- description,
- short_description:
- '
This is a simple product.
\n',
- sku: 'woo-cap',
- price: '16',
- regular_price: '18',
- sale_price: '16',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: true,
- purchasable: true,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '0.6',
- dimensions: {
- length: '8',
- width: '6.5',
- height: '4',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.accessoriesJSON.id,
- },
- ],
- tags: [],
- attributes: [
- {
- id: attributes.colorJSON.id,
- position: 0,
- visible: true,
- variation: false,
- options: [ 'Yellow' ],
- },
- ],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [ 60, 77, 61, 63 ],
- stock_status: 'instock',
- },
- {
- name: 'Belt oxo',
- date_created_gmt: '2021-09-12T15:50:19',
- type: 'simple',
- status: 'publish',
- featured: false,
- catalog_visibility: 'visible',
- description,
- short_description:
- '
This is a simple product.
\n',
- sku: 'woo-belt',
- price: '55',
- regular_price: '65',
- sale_price: '55',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: true,
- purchasable: true,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '1.2',
- dimensions: {
- length: '12',
- width: '2',
- height: '1.5',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.accessoriesJSON.id,
- },
- ],
- tags: [],
- attributes: [],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [ 63, 77, 62, 60 ],
- stock_status: 'instock',
- },
- {
- name: 'Beanie oxo',
- date_created_gmt: '2021-09-13T15:50:19',
- type: 'simple',
- status: 'publish',
- featured: false,
- catalog_visibility: 'visible',
- description,
- short_description:
- '
This is a simple product.
\n',
- sku: 'woo-beanie',
- price: '18',
- regular_price: '20',
- sale_price: '18',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: true,
- purchasable: true,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '0.2',
- dimensions: {
- length: '4',
- width: '5',
- height: '0.5',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.accessoriesJSON.id,
- },
- ],
- tags: [
- {
- id: tags.coolJSON.id,
- },
- ],
- attributes: [
- {
- id: attributes.colorJSON.id,
- position: 0,
- visible: true,
- variation: false,
- options: [ 'Red' ],
- },
- ],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [ 63, 62, 61, 77 ],
- stock_status: 'instock',
- },
- {
- name: 'T-Shirt oxo',
- date_created_gmt: '2021-09-14T15:50:19',
- type: 'simple',
- status: 'publish',
- featured: false,
- catalog_visibility: 'visible',
- description,
- short_description:
- '
This is a simple product.
\n',
- sku: 'woo-tshirt',
- price: '18',
- regular_price: '18',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- purchasable: true,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '0.8',
- dimensions: {
- length: '8',
- width: '6',
- height: '1',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.tshirtsJSON.id,
- },
- ],
- tags: [],
- attributes: [
- {
- id: attributes.colorJSON.id,
- position: 0,
- visible: true,
- variation: false,
- options: [ 'Gray' ],
- },
- ],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [ 67, 76, 56, 66 ],
- stock_status: 'onbackorder',
- },
- {
- name: 'Hoodie with Logo oxo',
- date_created_gmt: '2021-09-15T15:50:19',
- type: 'simple',
- status: 'publish',
- featured: false,
- catalog_visibility: 'visible',
- description,
- short_description:
- '
This is a simple product.
\n',
- sku: 'woo-hoodie-with-logo',
- price: '45',
- regular_price: '45',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- purchasable: true,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '2',
- dimensions: {
- length: '10',
- width: '6',
- height: '3',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.hoodiesJSON.id,
- },
- ],
- tags: [],
- attributes: [
- {
- id: attributes.colorJSON.id,
- position: 0,
- visible: true,
- variation: false,
- options: [ 'Blue' ],
- },
- ],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [ 57, 65 ],
- stock_status: 'instock',
- },
- ],
- },
- }
- );
- const simpleProductsJSON = await simpleProducts.json();
-
- return simpleProductsJSON.create;
- };
-
- const createSampleExternalProducts = async ( categories ) => {
- const externalProducts = await request.post(
- '/wp-json/wc/v3/products/batch',
- {
- data: {
- create: [
- {
- name: 'WordPress Pennant oxo',
- date_created_gmt: '2021-09-16T15:50:20',
- type: 'external',
- status: 'publish',
- featured: false,
- catalog_visibility: 'visible',
- description:
- '
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.
\n',
- short_description:
- '
This is an external product.
\n',
- sku: 'wp-pennant',
- price: '11.05',
- regular_price: '11.05',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- purchasable: false,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url:
- 'https://mercantile.wordpress.org/product/wordpress-pennant/',
- button_text: 'Buy on the WordPress swag store!',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '',
- dimensions: {
- length: '',
- width: '',
- height: '',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.decorJSON.id,
- },
- ],
- tags: [],
- attributes: [],
- default_attributes: [],
- variations: [],
- grouped_products: [],
- menu_order: 0,
- related_ids: [],
- stock_status: 'instock',
- },
- ],
- },
- }
- );
- const externalProductsJSON = await externalProducts.json();
-
- return externalProductsJSON.create;
- };
-
- const createSampleGroupedProduct = async ( categories ) => {
- const logoProducts = await request.get( '/wp-json/wc/v3/products', {
- params: {
- search: 'logo',
- _fields: [ 'id' ],
- },
- } );
- const logoProductsJSON = await logoProducts.json();
-
- const groupedProducts = await request.post(
- '/wp-json/wc/v3/products/batch',
- {
- data: {
- create: [
- {
- name: 'Logo Collection oxo',
- date_created_gmt: '2021-09-17T15:50:20',
- type: 'grouped',
- status: 'publish',
- featured: false,
- catalog_visibility: 'visible',
- description:
- '
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.
\n',
- short_description:
- '
This is a grouped product.
\n',
- sku: 'logo-collection',
- price: '18',
- regular_price: '',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: true,
- purchasable: false,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '',
- dimensions: {
- length: '',
- width: '',
- height: '',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.clothingJSON.id,
- },
- ],
- tags: [],
- attributes: [],
- default_attributes: [],
- variations: [],
- grouped_products: logoProductsJSON.map(
- ( p ) => p.id
- ),
- menu_order: 0,
- related_ids: [],
- stock_status: 'instock',
- },
- ],
- },
- }
- );
- const groupedProductsJSON = await groupedProducts.json();
-
- return groupedProductsJSON.create;
- };
-
- const createSampleVariableProducts = async (
- categories,
- attributes
- ) => {
- const description =
- '
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.
\n';
-
- const hoodie = await request.post( '/wp-json/wc/v3/products', {
- data: {
- name: 'Hoodie oxo',
- date_created_gmt: '2021-09-18T15:50:19',
- type: 'variable',
- status: 'publish',
- featured: false,
- catalog_visibility: 'visible',
- description,
- short_description: '
This is a variable product.
\n',
- sku: 'woo-hoodie',
- price: '42',
- regular_price: '',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: true,
- purchasable: true,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '1.5',
- dimensions: {
- length: '10',
- width: '8',
- height: '3',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.hoodiesJSON.id,
+ const accessories = await request.post(
+ '/wp-json/wc/v3/products/categories',
+ {
+ data: {
+ name: 'Accessories',
+ parent: clothingJSON.id,
},
- ],
- tags: [],
- attributes: [
- {
- id: attributes.colorJSON.id,
- position: 0,
- visible: true,
- variation: true,
- options: [ 'Blue', 'Green', 'Red' ],
- },
- {
- id: 0,
- name: 'Logo',
- position: 1,
- visible: true,
- variation: true,
- options: [ 'Yes', 'No' ],
- },
- ],
- default_attributes: [],
- grouped_products: [],
- menu_order: 0,
- stock_status: 'instock',
- },
- } );
- const hoodieJSON = await hoodie.json();
+ }
+ );
+ const accessoriesJSON = await accessories.json();
- const variationDescription =
- '
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.
\n';
-
- const hoodieVariations = await request.post(
- `/wp-json/wc/v3/products/${ hoodieJSON.id }/variations/batch`,
- {
- data: {
- create: [
- {
- date_created_gmt: '2021-09-19T15:50:20',
- description: variationDescription,
- sku: 'woo-hoodie-blue-logo',
- price: '45',
- regular_price: '45',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- status: 'publish',
- purchasable: true,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- stock_status: 'instock',
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- weight: '1.5',
- dimensions: {
- length: '10',
- width: '8',
- height: '3',
- },
- shipping_class: '',
- attributes: [
- {
- id: attributes.colorJSON.id,
- option: 'Blue',
- },
- {
- id: 0,
- name: 'Logo',
- option: 'Yes',
- },
- ],
- menu_order: 0,
- },
- {
- date_created_gmt: '2021-09-20T15:50:20',
- description: variationDescription,
- sku: 'woo-hoodie-blue',
- price: '45',
- regular_price: '45',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- status: 'publish',
- purchasable: true,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- stock_status: 'instock',
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- weight: '1.5',
- dimensions: {
- length: '10',
- width: '8',
- height: '3',
- },
- shipping_class: '',
- attributes: [
- {
- id: attributes.colorJSON.id,
- option: 'Blue',
- },
- {
- id: 0,
- name: 'Logo',
- option: 'No',
- },
- ],
- menu_order: 3,
- },
- {
- date_created_gmt: '2021-09-21T15:50:20',
- description: variationDescription,
- sku: 'woo-hoodie-green',
- price: '45',
- regular_price: '45',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- status: 'publish',
- purchasable: true,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- stock_status: 'instock',
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- weight: '1.5',
- dimensions: {
- length: '10',
- width: '8',
- height: '3',
- },
- shipping_class: '',
- attributes: [
- {
- id: attributes.colorJSON.id,
- option: 'Green',
- },
- {
- id: 0,
- name: 'Logo',
- option: 'No',
- },
- ],
- menu_order: 2,
- },
- {
- date_created_gmt: '2021-09-22T15:50:19',
- description: variationDescription,
- sku: 'woo-hoodie-red',
- price: '42',
- regular_price: '45',
- sale_price: '42',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: true,
- status: 'publish',
- purchasable: true,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- stock_status: 'instock',
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- weight: '1.5',
- dimensions: {
- length: '10',
- width: '8',
- height: '3',
- },
- shipping_class: '',
- attributes: [
- {
- id: attributes.colorJSON.id,
- option: 'Red',
- },
- {
- id: 0,
- name: 'Logo',
- option: 'No',
- },
- ],
- menu_order: 1,
- },
- ],
- },
- }
- );
- const hoodieVariationsJSON = await hoodieVariations.json();
-
- const vneck = await request.post( '/wp-json/wc/v3/products', {
- data: {
- name: 'V-Neck T-Shirt oxo',
- date_created_gmt: '2021-09-23T15:50:19',
- type: 'variable',
- status: 'publish',
- featured: true,
- catalog_visibility: 'visible',
- description,
- short_description: '
This is a variable product.
\n',
- sku: 'woo-vneck-tee',
- price: '15',
- regular_price: '',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- purchasable: true,
- total_sales: 0,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- external_url: '',
- button_text: '',
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- sold_individually: false,
- weight: '0.5',
- dimensions: {
- length: '24',
- width: '1',
- height: '2',
- },
- shipping_required: true,
- shipping_taxable: true,
- shipping_class: '',
- reviews_allowed: true,
- average_rating: '0.00',
- rating_count: 0,
- upsell_ids: [],
- cross_sell_ids: [],
- parent_id: 0,
- purchase_note: '',
- categories: [
- {
- id: categories.tshirtsJSON.id,
+ const hoodies = await request.post(
+ '/wp-json/wc/v3/products/categories',
+ {
+ data: {
+ name: 'Hoodies',
+ parent: clothingJSON.id,
},
- ],
- tags: [],
- attributes: [
- {
- id: attributes.colorJSON.id,
- position: 0,
- visible: true,
- variation: true,
- options: [ 'Blue', 'Green', 'Red' ],
- },
- {
- id: attributes.sizeJSON.id,
- position: 1,
- visible: true,
- variation: true,
- options: [ 'Large', 'Medium', 'Small' ],
- },
- ],
- default_attributes: [],
- grouped_products: [],
- menu_order: 0,
- stock_status: 'instock',
- },
- } );
- const vneckJSON = await vneck.json();
+ }
+ );
+ const hoodiesJSON = await hoodies.json();
- const vneckVariations = await request.post(
- `/wp-json/wc/v3/products/${ vneckJSON.id }/variations/batch`,
- {
- data: {
- create: [
- {
- date_created_gmt: '2021-09-24T15:50:19',
- description: variationDescription,
- sku: 'woo-vneck-tee-blue',
- price: '15',
- regular_price: '15',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- status: 'publish',
- purchasable: true,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- stock_status: 'instock',
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- weight: '0.5',
- dimensions: {
- length: '24',
- width: '1',
- height: '2',
- },
- shipping_class: '',
- attributes: [
- {
- id: attributes.colorJSON.id,
- option: 'Blue',
- },
- ],
- menu_order: 0,
- },
- {
- date_created_gmt: '2021-09-25T15:50:19',
- description: variationDescription,
- sku: 'woo-vneck-tee-green',
- price: '20',
- regular_price: '20',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- status: 'publish',
- purchasable: true,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- stock_status: 'instock',
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- weight: '0.5',
- dimensions: {
- length: '24',
- width: '1',
- height: '2',
- },
- shipping_class: '',
- attributes: [
- {
- id: attributes.colorJSON.id,
- option: 'Green',
- },
- ],
- menu_order: 0,
- },
- {
- date_created_gmt: '2021-09-26T15:50:19',
- description: variationDescription,
- sku: 'woo-vneck-tee-red',
- price: '20',
- regular_price: '20',
- sale_price: '',
- date_on_sale_from_gmt: null,
- date_on_sale_to_gmt: null,
- on_sale: false,
- status: 'publish',
- purchasable: true,
- virtual: false,
- downloadable: false,
- downloads: [],
- download_limit: 0,
- download_expiry: 0,
- tax_status: 'taxable',
- tax_class: '',
- manage_stock: false,
- stock_quantity: null,
- stock_status: 'instock',
- backorders: 'no',
- backorders_allowed: false,
- backordered: false,
- low_stock_amount: null,
- weight: '0.5',
- dimensions: {
- length: '24',
- width: '1',
- height: '2',
- },
- shipping_class: '',
- attributes: [
- {
- id: attributes.colorJSON.id,
- option: 'Red',
- },
- ],
- menu_order: 0,
- },
- ],
- },
- }
- );
- const vneckVariationsJSON = await vneckVariations.json();
+ const tshirts = await request.post(
+ '/wp-json/wc/v3/products/categories',
+ {
+ data: {
+ name: 'Tshirts',
+ parent: clothingJSON.id,
+ },
+ }
+ );
+ const tshirtsJSON = await tshirts.json();
- return {
- hoodieJSON,
- hoodieVariations: hoodieVariationsJSON.create,
- vneckJSON,
- vneckVariations: vneckVariationsJSON.create,
+ const decor = await request.post(
+ '/wp-json/wc/v3/products/categories',
+ {
+ data: {
+ name: 'Decor',
+ },
+ }
+ );
+ const decorJSON = await decor.json();
+
+ const music = await request.post(
+ '/wp-json/wc/v3/products/categories',
+ {
+ data: {
+ name: 'Music',
+ },
+ }
+ );
+ const musicJSON = await music.json();
+
+ return {
+ clothingJSON,
+ accessoriesJSON,
+ hoodiesJSON,
+ tshirtsJSON,
+ decorJSON,
+ musicJSON,
+ };
};
- };
- const createSampleHierarchicalProducts = async () => {
- const parent = await request.post( '/wp-json/wc/v3/products', {
- data: {
- name: 'Parent Product oxo',
- date_created_gmt: '2021-09-27T15:50:19',
- },
- } );
- const parentJSON = await parent.json();
+ const createSampleAttributes = async () => {
+ const color = await request.post(
+ '/wp-json/wc/v3/products/attributes',
+ {
+ data: {
+ name: 'Color',
+ },
+ }
+ );
+ const colorJSON = await color.json();
- const child = await request.post( '/wp-json/wc/v3/products', {
- data: {
- name: 'Child Product oxo',
- parent_id: parentJSON.id,
- date_created_gmt: '2021-09-28T15:50:19',
- },
- } );
- const childJSON = await child.json();
+ const size = await request.post(
+ '/wp-json/wc/v3/products/attributes',
+ {
+ data: {
+ name: 'Size',
+ },
+ }
+ );
+ const sizeJSON = await size.json();
- return {
- parentJSON,
- childJSON,
+ const colorNames = [ 'Blue', 'Gray', 'Green', 'Red', 'Yellow' ];
+
+ const colorNamesObjectArray = colorNames.map( ( name ) => ( {
+ name,
+ } ) );
+
+ const colors = await request.post(
+ `/wp-json/wc/v3/products/attributes/${ colorJSON.id }/terms/batch`,
+ {
+ data: {
+ create: colorNamesObjectArray,
+ },
+ }
+ );
+
+ const colorsJSON = await colors.json();
+
+ const sizeNames = [ 'Large', 'Medium', 'Small' ];
+
+ const sizeNamesObjectArray = sizeNames.map( ( name ) => ( {
+ name,
+ } ) );
+
+ const sizes = await request.post(
+ `/wp-json/wc/v3/products/attributes/${ sizeJSON.id }/terms/batch`,
+ {
+ data: {
+ create: sizeNamesObjectArray,
+ },
+ }
+ );
+ const sizesJSON = await sizes.json();
+
+ return {
+ colorJSON,
+ colors: colorsJSON.create,
+ sizeJSON,
+ sizes: sizesJSON.create,
+ };
};
- };
- const createSampleProductReviews = async ( simpleProducts ) => {
- const cap = simpleProducts.find( ( p ) => p.name === 'Cap oxo' );
-
- const shirt = simpleProducts.find(
- ( p ) => p.name === 'T-Shirt oxo'
- );
-
- const sunglasses = simpleProducts.find(
- ( p ) => p.name === 'Sunglasses oxo'
- );
-
- const review1 = await request.post(
- '/wp-json/wc/v3/products/reviews',
- {
- data: {
- product_id: cap.id,
- rating: 3,
- review: 'Decent cap.',
- reviewer: 'John Doe',
- reviewer_email: 'john.doe@example.com',
- },
- }
- );
- const review1JSON = await review1.json();
-
- // We need to update the review in order for the product's
- // average_rating to be recalculated.
- // See: https://github.com/woocommerce/woocommerce/issues/29906.
- //await updateProductReview(review1.id);
- await request.post(
- `/wp-json/wc/v3/products/reviews/${ review1JSON.id }`,
- {
- data: {},
- }
- );
-
- const review2 = await request.post(
- '/wp-json/wc/v3/products/reviews',
- {
- data: {
- product_id: shirt.id,
- rating: 5,
- review: 'The BEST shirt ever!!',
- reviewer: 'Shannon Smith',
- reviewer_email: 'shannon.smith@example.com',
- },
- }
- );
- const review2JSON = await review2.json();
-
- //await updateProductReview(review2.id);
- await request.post(
- `/wp-json/wc/v3/products/reviews/${ review2JSON.id }`,
- {
- data: {},
- }
- );
-
- const review3 = await request.post(
- '/wp-json/wc/v3/products/reviews',
- {
- data: {
- product_id: sunglasses.id,
- rating: 1,
- review: 'These are way too expensive.',
- reviewer: 'Tim Frugalman',
- reviewer_email: 'timmyfrufru@example.com',
- },
- }
- );
- const review3JSON = await review3.json();
-
- await request.post(
- `/wp-json/wc/v3/products/reviews/${ review3JSON.id }`,
- {
- data: {},
- }
- );
-
- return [ review1JSON.id, review2JSON.id, review3JSON.id ];
- };
-
- const createSampleProductOrders = async ( simpleProducts ) => {
- const single = simpleProducts.find(
- ( p ) => p.name === 'Single oxo'
- );
- const beanie = simpleProducts.find(
- ( p ) => p.name === 'Beanie with Logo oxo'
- );
- const shirt = simpleProducts.find(
- ( p ) => p.name === 'T-Shirt oxo'
- );
-
- const order1 = await request.post( '/wp-json/wc/v3/orders', {
- data: {
- set_paid: true,
- status: 'completed',
- line_items: [
- {
- product_id: single.id,
- quantity: 2,
+ const createSampleTags = async () => {
+ const cool = await request.post(
+ '/wp-json/wc/v3/products/tags',
+ {
+ data: {
+ name: 'Cool',
},
- {
- product_id: beanie.id,
- quantity: 3,
+ }
+ );
+ const coolJSON = await cool.json();
+
+ return {
+ coolJSON,
+ };
+ };
+
+ const createSampleShippingClasses = async () => {
+ const freight = await request.post(
+ '/wp-json/wc/v3/products/shipping_classes',
+ {
+ data: {
+ name: 'Freight',
},
+ }
+ );
+ const freightJSON = await freight.json();
+
+ return {
+ freightJSON,
+ };
+ };
+
+ const createSampleTaxClasses = async () => {
+ //check to see if Reduced Rate tax class exists - if not, create it
+ let reducedRate = await request.get(
+ '/wp-json/wc/v3/taxes/classes/reduced-rate'
+ );
+ let reducedRateJSON = await reducedRate.json();
+ expect( Array.isArray( reducedRateJSON ) ).toBe( true );
+
+ //if tax class does not exist then create it
+ if ( reducedRateJSON.length < 1 ) {
+ reducedRate = await request.post(
+ '/wp-json/wc/v3/taxes/classes',
{
- product_id: shirt.id,
- quantity: 1,
- },
- ],
- },
- } );
- const orderJSON = await order1.json();
+ data: {
+ name: 'Reduced Rate',
+ },
+ }
+ );
+ reducedRateJSON = await reducedRate.json();
+ return { reducedRateJSON };
+ }
- return [ orderJSON ];
- };
+ // return an empty object as nothing new was created so nothing will
+ // need deleted during cleanup
+ return {};
+ };
- const productsTestSetupCreateSampleData = async () => {
- const categories = await createSampleCategories();
-
- const attributes = await createSampleAttributes();
-
- const tags = await createSampleTags();
-
- const shippingClasses = await createSampleShippingClasses();
-
- const taxClasses = await createSampleTaxClasses();
-
- const simpleProducts = await createSampleSimpleProducts(
+ const createSampleSimpleProducts = async (
categories,
attributes,
tags
- );
+ ) => {
+ const description =
+ '
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.
\n';
- const externalProducts = await createSampleExternalProducts(
- categories
- );
+ const simpleProducts = await request.post(
+ '/wp-json/wc/v3/products/batch',
+ {
+ data: {
+ create: [
+ {
+ name: 'Beanie with Logo oxo',
+ date_created_gmt: '2021-09-01T15:50:20',
+ type: 'simple',
+ status: 'publish',
+ featured: false,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a simple product.
\n',
+ sku: 'Woo-beanie-logo',
+ price: '18',
+ regular_price: '20',
+ sale_price: '18',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: true,
+ purchasable: true,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '0.2',
+ dimensions: {
+ length: '6',
+ width: '4',
+ height: '1',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.accessoriesJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ position: 0,
+ visible: true,
+ variation: false,
+ options: [ 'Red' ],
+ },
+ ],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [ 62, 63, 61, 60 ],
+ stock_status: 'instock',
+ },
+ {
+ name: 'T-Shirt with Logo oxo',
+ date_created_gmt: '2021-09-02T15:50:20',
+ type: 'simple',
+ status: 'publish',
+ featured: false,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a simple product.
\n',
+ sku: 'Woo-tshirt-logo',
+ price: '18',
+ regular_price: '18',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ purchasable: true,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '0.5',
+ dimensions: {
+ length: '10',
+ width: '12',
+ height: '0.5',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.tshirtsJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ position: 0,
+ visible: true,
+ variation: false,
+ options: [ 'Gray' ],
+ },
+ ],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [ 59, 67, 66, 56 ],
+ stock_status: 'instock',
+ },
+ {
+ name: 'Single oxo',
+ date_created_gmt: '2021-09-03T15:50:19',
+ type: 'simple',
+ status: 'publish',
+ featured: false,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a simple, virtual product.
\n',
+ sku: 'woo-single',
+ price: '2',
+ regular_price: '3',
+ sale_price: '2',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: true,
+ purchasable: true,
+ total_sales: 0,
+ virtual: true,
+ downloadable: true,
+ downloads: [
+ {
+ id: '2579cf07-8b08-4c25-888a-b6258dd1f035',
+ name: 'Single',
+ file: 'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg',
+ },
+ ],
+ download_limit: 1,
+ download_expiry: 1,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '',
+ dimensions: {
+ length: '',
+ width: '',
+ height: '',
+ },
+ shipping_required: false,
+ shipping_taxable: false,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.musicJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [ 68 ],
+ stock_status: 'instock',
+ },
+ {
+ name: 'Album oxo',
+ date_created_gmt: '2021-09-04T15:50:19',
+ type: 'simple',
+ status: 'publish',
+ featured: false,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a simple, virtual product.
\n',
+ sku: 'woo-album',
+ price: '15',
+ regular_price: '15',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ purchasable: true,
+ total_sales: 0,
+ virtual: true,
+ downloadable: true,
+ downloads: [
+ {
+ id: 'cc10249f-1de2-44d4-93d3-9f88ae629f76',
+ name: 'Single 1',
+ file: 'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg',
+ },
+ {
+ id: 'aea8ef69-ccdc-4d83-8e21-3c395ebb9411',
+ name: 'Single 2',
+ file: 'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/album.jpg',
+ },
+ ],
+ download_limit: 1,
+ download_expiry: 1,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '',
+ dimensions: {
+ length: '',
+ width: '',
+ height: '',
+ },
+ shipping_required: false,
+ shipping_taxable: false,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.musicJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [ 69 ],
+ stock_status: 'instock',
+ },
+ {
+ name: 'Polo oxo',
+ date_created_gmt: '2021-09-05T15:50:19',
+ type: 'simple',
+ status: 'pending',
+ featured: false,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a simple product.
\n',
+ sku: 'woo-polo',
+ price: '20',
+ regular_price: '20',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ purchasable: true,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '0.8',
+ dimensions: {
+ length: '6',
+ width: '5',
+ height: '1',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.tshirtsJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ position: 0,
+ visible: true,
+ variation: false,
+ options: [ 'Blue' ],
+ },
+ ],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [ 59, 56, 66, 76 ],
+ stock_status: 'instock',
+ },
+ {
+ name: 'Long Sleeve Tee oxo',
+ date_created_gmt: '2021-09-06T15:50:19',
+ type: 'simple',
+ status: 'publish',
+ featured: false,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a simple product.
\n',
+ sku: 'woo-long-sleeve-tee',
+ price: '25',
+ regular_price: '25',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ purchasable: true,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '1',
+ dimensions: {
+ length: '7',
+ width: '5',
+ height: '1',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: 'freight',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.tshirtsJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ position: 0,
+ visible: true,
+ variation: false,
+ options: [ 'Green' ],
+ },
+ ],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [ 59, 56, 76, 67 ],
+ stock_status: 'instock',
+ },
+ {
+ name: 'Hoodie with Zipper oxo',
+ date_created_gmt: '2021-09-07T15:50:19',
+ type: 'simple',
+ status: 'publish',
+ featured: true,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a simple product.
\n',
+ sku: 'woo-hoodie-with-zipper',
+ price: '45',
+ regular_price: '45',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ purchasable: true,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '2',
+ dimensions: {
+ length: '8',
+ width: '6',
+ height: '2',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.hoodiesJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [ 57, 58 ],
+ stock_status: 'instock',
+ },
+ {
+ name: 'Hoodie with Pocket oxo',
+ date_created_gmt: '2021-09-08T15:50:19',
+ type: 'simple',
+ status: 'publish',
+ featured: true,
+ catalog_visibility: 'hidden',
+ description,
+ short_description:
+ '
This is a simple product.
\n',
+ sku: 'woo-hoodie-with-pocket',
+ price: '35',
+ regular_price: '45',
+ sale_price: '35',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: true,
+ purchasable: true,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '3',
+ dimensions: {
+ length: '10',
+ width: '8',
+ height: '2',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.hoodiesJSON.id,
+ },
+ ],
+ tags: [
+ {
+ id: tags.coolJSON.id,
+ },
+ ],
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ position: 0,
+ visible: true,
+ variation: false,
+ options: [ 'Gray' ],
+ },
+ ],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [ 65, 57, 58 ],
+ stock_status: 'instock',
+ },
+ {
+ name: 'Sunglasses oxo',
+ date_created_gmt: '2021-09-09T15:50:19',
+ type: 'simple',
+ status: 'publish',
+ featured: true,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a simple product.
\n',
+ sku: 'woo-sunglasses',
+ price: '90',
+ regular_price: '90',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ purchasable: true,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: 'reduced-rate',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '0.2',
+ dimensions: {
+ length: '4',
+ width: '1.4',
+ height: '1',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.accessoriesJSON.id,
+ },
+ ],
+ tags: [
+ {
+ id: tags.coolJSON.id,
+ },
+ ],
+ attributes: [],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [ 60, 62, 77, 61 ],
+ stock_status: 'instock',
+ },
+ {
+ name: 'Cap oxo',
+ date_created_gmt: '2021-09-10T15:50:19',
+ type: 'simple',
+ status: 'publish',
+ featured: true,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a simple product.
\n',
+ sku: 'woo-cap',
+ price: '16',
+ regular_price: '18',
+ sale_price: '16',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: true,
+ purchasable: true,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '0.6',
+ dimensions: {
+ length: '8',
+ width: '6.5',
+ height: '4',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.accessoriesJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ position: 0,
+ visible: true,
+ variation: false,
+ options: [ 'Yellow' ],
+ },
+ ],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [ 60, 77, 61, 63 ],
+ stock_status: 'instock',
+ },
+ {
+ name: 'Belt oxo',
+ date_created_gmt: '2021-09-12T15:50:19',
+ type: 'simple',
+ status: 'publish',
+ featured: false,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a simple product.
\n',
+ sku: 'woo-belt',
+ price: '55',
+ regular_price: '65',
+ sale_price: '55',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: true,
+ purchasable: true,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '1.2',
+ dimensions: {
+ length: '12',
+ width: '2',
+ height: '1.5',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.accessoriesJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [ 63, 77, 62, 60 ],
+ stock_status: 'instock',
+ },
+ {
+ name: 'Beanie oxo',
+ date_created_gmt: '2021-09-13T15:50:19',
+ type: 'simple',
+ status: 'publish',
+ featured: false,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a simple product.
\n',
+ sku: 'woo-beanie',
+ price: '18',
+ regular_price: '20',
+ sale_price: '18',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: true,
+ purchasable: true,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '0.2',
+ dimensions: {
+ length: '4',
+ width: '5',
+ height: '0.5',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.accessoriesJSON.id,
+ },
+ ],
+ tags: [
+ {
+ id: tags.coolJSON.id,
+ },
+ ],
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ position: 0,
+ visible: true,
+ variation: false,
+ options: [ 'Red' ],
+ },
+ ],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [ 63, 62, 61, 77 ],
+ stock_status: 'instock',
+ },
+ {
+ name: 'T-Shirt oxo',
+ date_created_gmt: '2021-09-14T15:50:19',
+ type: 'simple',
+ status: 'publish',
+ featured: false,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a simple product.
\n',
+ sku: 'woo-tshirt',
+ price: '18',
+ regular_price: '18',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ purchasable: true,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '0.8',
+ dimensions: {
+ length: '8',
+ width: '6',
+ height: '1',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.tshirtsJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ position: 0,
+ visible: true,
+ variation: false,
+ options: [ 'Gray' ],
+ },
+ ],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [ 67, 76, 56, 66 ],
+ stock_status: 'onbackorder',
+ },
+ {
+ name: 'Hoodie with Logo oxo',
+ date_created_gmt: '2021-09-15T15:50:19',
+ type: 'simple',
+ status: 'publish',
+ featured: false,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a simple product.
\n',
+ sku: 'woo-hoodie-with-logo',
+ price: '45',
+ regular_price: '45',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ purchasable: true,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '2',
+ dimensions: {
+ length: '10',
+ width: '6',
+ height: '3',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.hoodiesJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ position: 0,
+ visible: true,
+ variation: false,
+ options: [ 'Blue' ],
+ },
+ ],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [ 57, 65 ],
+ stock_status: 'instock',
+ },
+ ],
+ },
+ }
+ );
+ const simpleProductsJSON = await simpleProducts.json();
- const groupedProducts = await createSampleGroupedProduct(
- categories
- );
+ return simpleProductsJSON.create;
+ };
- const variableProducts = await createSampleVariableProducts(
+ const createSampleExternalProducts = async ( categories ) => {
+ const externalProducts = await request.post(
+ '/wp-json/wc/v3/products/batch',
+ {
+ data: {
+ create: [
+ {
+ name: 'WordPress Pennant oxo',
+ date_created_gmt: '2021-09-16T15:50:20',
+ type: 'external',
+ status: 'publish',
+ featured: false,
+ catalog_visibility: 'visible',
+ description:
+ '
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.
\n',
+ short_description:
+ '
This is an external product.
\n',
+ sku: 'wp-pennant',
+ price: '11.05',
+ regular_price: '11.05',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ purchasable: false,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url:
+ 'https://mercantile.wordpress.org/product/wordpress-pennant/',
+ button_text:
+ 'Buy on the WordPress swag store!',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '',
+ dimensions: {
+ length: '',
+ width: '',
+ height: '',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.decorJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [],
+ default_attributes: [],
+ variations: [],
+ grouped_products: [],
+ menu_order: 0,
+ related_ids: [],
+ stock_status: 'instock',
+ },
+ ],
+ },
+ }
+ );
+ const externalProductsJSON = await externalProducts.json();
+
+ return externalProductsJSON.create;
+ };
+
+ const createSampleGroupedProduct = async ( categories ) => {
+ const logoProducts = await request.get(
+ '/wp-json/wc/v3/products',
+ {
+ params: {
+ search: 'logo',
+ _fields: [ 'id' ],
+ },
+ }
+ );
+ const logoProductsJSON = await logoProducts.json();
+
+ const groupedProducts = await request.post(
+ '/wp-json/wc/v3/products/batch',
+ {
+ data: {
+ create: [
+ {
+ name: 'Logo Collection oxo',
+ date_created_gmt: '2021-09-17T15:50:20',
+ type: 'grouped',
+ status: 'publish',
+ featured: false,
+ catalog_visibility: 'visible',
+ description:
+ '
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.
\n',
+ short_description:
+ '
This is a grouped product.
\n',
+ sku: 'logo-collection',
+ price: '18',
+ regular_price: '',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: true,
+ purchasable: false,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '',
+ dimensions: {
+ length: '',
+ width: '',
+ height: '',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.clothingJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [],
+ default_attributes: [],
+ variations: [],
+ grouped_products: logoProductsJSON.map(
+ ( p ) => p.id
+ ),
+ menu_order: 0,
+ related_ids: [],
+ stock_status: 'instock',
+ },
+ ],
+ },
+ }
+ );
+ const groupedProductsJSON = await groupedProducts.json();
+
+ return groupedProductsJSON.create;
+ };
+
+ const createSampleVariableProducts = async (
categories,
attributes
- );
+ ) => {
+ const description =
+ '
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.
\n';
- const hierarchicalProducts =
- await createSampleHierarchicalProducts();
+ const hoodie = await request.post( '/wp-json/wc/v3/products', {
+ data: {
+ name: 'Hoodie oxo',
+ date_created_gmt: '2021-09-18T15:50:19',
+ type: 'variable',
+ status: 'publish',
+ featured: false,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a variable product.
\n',
+ sku: 'woo-hoodie',
+ price: '42',
+ regular_price: '',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: true,
+ purchasable: true,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '1.5',
+ dimensions: {
+ length: '10',
+ width: '8',
+ height: '3',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.hoodiesJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ position: 0,
+ visible: true,
+ variation: true,
+ options: [ 'Blue', 'Green', 'Red' ],
+ },
+ {
+ id: 0,
+ name: 'Logo',
+ position: 1,
+ visible: true,
+ variation: true,
+ options: [ 'Yes', 'No' ],
+ },
+ ],
+ default_attributes: [],
+ grouped_products: [],
+ menu_order: 0,
+ stock_status: 'instock',
+ },
+ } );
+ const hoodieJSON = await hoodie.json();
- const reviewIds = await createSampleProductReviews(
- simpleProducts
- );
+ const variationDescription =
+ '
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.
\n';
- const orders = await createSampleProductOrders( simpleProducts );
+ const hoodieVariations = await request.post(
+ `/wp-json/wc/v3/products/${ hoodieJSON.id }/variations/batch`,
+ {
+ data: {
+ create: [
+ {
+ date_created_gmt: '2021-09-19T15:50:20',
+ description: variationDescription,
+ sku: 'woo-hoodie-blue-logo',
+ price: '45',
+ regular_price: '45',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ status: 'publish',
+ purchasable: true,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ stock_status: 'instock',
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ weight: '1.5',
+ dimensions: {
+ length: '10',
+ width: '8',
+ height: '3',
+ },
+ shipping_class: '',
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ option: 'Blue',
+ },
+ {
+ id: 0,
+ name: 'Logo',
+ option: 'Yes',
+ },
+ ],
+ menu_order: 0,
+ },
+ {
+ date_created_gmt: '2021-09-20T15:50:20',
+ description: variationDescription,
+ sku: 'woo-hoodie-blue',
+ price: '45',
+ regular_price: '45',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ status: 'publish',
+ purchasable: true,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ stock_status: 'instock',
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ weight: '1.5',
+ dimensions: {
+ length: '10',
+ width: '8',
+ height: '3',
+ },
+ shipping_class: '',
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ option: 'Blue',
+ },
+ {
+ id: 0,
+ name: 'Logo',
+ option: 'No',
+ },
+ ],
+ menu_order: 3,
+ },
+ {
+ date_created_gmt: '2021-09-21T15:50:20',
+ description: variationDescription,
+ sku: 'woo-hoodie-green',
+ price: '45',
+ regular_price: '45',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ status: 'publish',
+ purchasable: true,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ stock_status: 'instock',
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ weight: '1.5',
+ dimensions: {
+ length: '10',
+ width: '8',
+ height: '3',
+ },
+ shipping_class: '',
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ option: 'Green',
+ },
+ {
+ id: 0,
+ name: 'Logo',
+ option: 'No',
+ },
+ ],
+ menu_order: 2,
+ },
+ {
+ date_created_gmt: '2021-09-22T15:50:19',
+ description: variationDescription,
+ sku: 'woo-hoodie-red',
+ price: '42',
+ regular_price: '45',
+ sale_price: '42',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: true,
+ status: 'publish',
+ purchasable: true,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ stock_status: 'instock',
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ weight: '1.5',
+ dimensions: {
+ length: '10',
+ width: '8',
+ height: '3',
+ },
+ shipping_class: '',
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ option: 'Red',
+ },
+ {
+ id: 0,
+ name: 'Logo',
+ option: 'No',
+ },
+ ],
+ menu_order: 1,
+ },
+ ],
+ },
+ }
+ );
+ const hoodieVariationsJSON = await hoodieVariations.json();
- return {
- categories,
- attributes,
- tags,
- shippingClasses,
- taxClasses,
- simpleProducts,
- externalProducts,
- groupedProducts,
- variableProducts,
- hierarchicalProducts,
- reviewIds,
- orders,
+ const vneck = await request.post( '/wp-json/wc/v3/products', {
+ data: {
+ name: 'V-Neck T-Shirt oxo',
+ date_created_gmt: '2021-09-23T15:50:19',
+ type: 'variable',
+ status: 'publish',
+ featured: true,
+ catalog_visibility: 'visible',
+ description,
+ short_description:
+ '
This is a variable product.
\n',
+ sku: 'woo-vneck-tee',
+ price: '15',
+ regular_price: '',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ purchasable: true,
+ total_sales: 0,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ external_url: '',
+ button_text: '',
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ sold_individually: false,
+ weight: '0.5',
+ dimensions: {
+ length: '24',
+ width: '1',
+ height: '2',
+ },
+ shipping_required: true,
+ shipping_taxable: true,
+ shipping_class: '',
+ reviews_allowed: true,
+ average_rating: '0.00',
+ rating_count: 0,
+ upsell_ids: [],
+ cross_sell_ids: [],
+ parent_id: 0,
+ purchase_note: '',
+ categories: [
+ {
+ id: categories.tshirtsJSON.id,
+ },
+ ],
+ tags: [],
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ position: 0,
+ visible: true,
+ variation: true,
+ options: [ 'Blue', 'Green', 'Red' ],
+ },
+ {
+ id: attributes.sizeJSON.id,
+ position: 1,
+ visible: true,
+ variation: true,
+ options: [ 'Large', 'Medium', 'Small' ],
+ },
+ ],
+ default_attributes: [],
+ grouped_products: [],
+ menu_order: 0,
+ stock_status: 'instock',
+ },
+ } );
+ const vneckJSON = await vneck.json();
+
+ const vneckVariations = await request.post(
+ `/wp-json/wc/v3/products/${ vneckJSON.id }/variations/batch`,
+ {
+ data: {
+ create: [
+ {
+ date_created_gmt: '2021-09-24T15:50:19',
+ description: variationDescription,
+ sku: 'woo-vneck-tee-blue',
+ price: '15',
+ regular_price: '15',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ status: 'publish',
+ purchasable: true,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ stock_status: 'instock',
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ weight: '0.5',
+ dimensions: {
+ length: '24',
+ width: '1',
+ height: '2',
+ },
+ shipping_class: '',
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ option: 'Blue',
+ },
+ ],
+ menu_order: 0,
+ },
+ {
+ date_created_gmt: '2021-09-25T15:50:19',
+ description: variationDescription,
+ sku: 'woo-vneck-tee-green',
+ price: '20',
+ regular_price: '20',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ status: 'publish',
+ purchasable: true,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ stock_status: 'instock',
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ weight: '0.5',
+ dimensions: {
+ length: '24',
+ width: '1',
+ height: '2',
+ },
+ shipping_class: '',
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ option: 'Green',
+ },
+ ],
+ menu_order: 0,
+ },
+ {
+ date_created_gmt: '2021-09-26T15:50:19',
+ description: variationDescription,
+ sku: 'woo-vneck-tee-red',
+ price: '20',
+ regular_price: '20',
+ sale_price: '',
+ date_on_sale_from_gmt: null,
+ date_on_sale_to_gmt: null,
+ on_sale: false,
+ status: 'publish',
+ purchasable: true,
+ virtual: false,
+ downloadable: false,
+ downloads: [],
+ download_limit: 0,
+ download_expiry: 0,
+ tax_status: 'taxable',
+ tax_class: '',
+ manage_stock: false,
+ stock_quantity: null,
+ stock_status: 'instock',
+ backorders: 'no',
+ backorders_allowed: false,
+ backordered: false,
+ low_stock_amount: null,
+ weight: '0.5',
+ dimensions: {
+ length: '24',
+ width: '1',
+ height: '2',
+ },
+ shipping_class: '',
+ attributes: [
+ {
+ id: attributes.colorJSON.id,
+ option: 'Red',
+ },
+ ],
+ menu_order: 0,
+ },
+ ],
+ },
+ }
+ );
+ const vneckVariationsJSON = await vneckVariations.json();
+
+ return {
+ hoodieJSON,
+ hoodieVariations: hoodieVariationsJSON.create,
+ vneckJSON,
+ vneckVariations: vneckVariationsJSON.create,
+ };
};
- };
- // create Sample Data function
- const createSampleData = async () => {
- const testProductData = await productsTestSetupCreateSampleData();
- const orderedProducts = {
- pocketHoodie: testProductData.simpleProducts.find(
- ( p ) => p.name === 'Hoodie with Pocket oxo'
- ),
- sunglasses: testProductData.simpleProducts.find(
+ const createSampleHierarchicalProducts = async () => {
+ const parent = await request.post( '/wp-json/wc/v3/products', {
+ data: {
+ name: 'Parent Product oxo',
+ date_created_gmt: '2021-09-27T15:50:19',
+ },
+ } );
+ const parentJSON = await parent.json();
+
+ const child = await request.post( '/wp-json/wc/v3/products', {
+ data: {
+ name: 'Child Product oxo',
+ parent_id: parentJSON.id,
+ date_created_gmt: '2021-09-28T15:50:19',
+ },
+ } );
+ const childJSON = await child.json();
+
+ return {
+ parentJSON,
+ childJSON,
+ };
+ };
+
+ const createSampleProductReviews = async ( simpleProducts ) => {
+ const cap = simpleProducts.find(
+ ( p ) => p.name === 'Cap oxo'
+ );
+
+ const shirt = simpleProducts.find(
+ ( p ) => p.name === 'T-Shirt oxo'
+ );
+
+ const sunglasses = simpleProducts.find(
( p ) => p.name === 'Sunglasses oxo'
- ),
- beanie: testProductData.simpleProducts.find(
- ( p ) => p.name === 'Beanie oxo'
- ),
- blueVneck:
- testProductData.variableProducts.vneckVariations.find(
- ( p ) => p.sku === 'woo-vneck-tee-blue'
+ );
+
+ const review1 = await request.post(
+ '/wp-json/wc/v3/products/reviews',
+ {
+ data: {
+ product_id: cap.id,
+ rating: 3,
+ review: 'Decent cap.',
+ reviewer: 'John Doe',
+ reviewer_email: 'john.doe@example.com',
+ },
+ }
+ );
+ const review1JSON = await review1.json();
+
+ // We need to update the review in order for the product's
+ // average_rating to be recalculated.
+ // See: https://github.com/woocommerce/woocommerce/issues/29906.
+ //await updateProductReview(review1.id);
+ await request.post(
+ `/wp-json/wc/v3/products/reviews/${ review1JSON.id }`,
+ {
+ data: {},
+ }
+ );
+
+ const review2 = await request.post(
+ '/wp-json/wc/v3/products/reviews',
+ {
+ data: {
+ product_id: shirt.id,
+ rating: 5,
+ review: 'The BEST shirt ever!!',
+ reviewer: 'Shannon Smith',
+ reviewer_email: 'shannon.smith@example.com',
+ },
+ }
+ );
+ const review2JSON = await review2.json();
+
+ //await updateProductReview(review2.id);
+ await request.post(
+ `/wp-json/wc/v3/products/reviews/${ review2JSON.id }`,
+ {
+ data: {},
+ }
+ );
+
+ const review3 = await request.post(
+ '/wp-json/wc/v3/products/reviews',
+ {
+ data: {
+ product_id: sunglasses.id,
+ rating: 1,
+ review: 'These are way too expensive.',
+ reviewer: 'Tim Frugalman',
+ reviewer_email: 'timmyfrufru@example.com',
+ },
+ }
+ );
+ const review3JSON = await review3.json();
+
+ await request.post(
+ `/wp-json/wc/v3/products/reviews/${ review3JSON.id }`,
+ {
+ data: {},
+ }
+ );
+
+ return [ review1JSON.id, review2JSON.id, review3JSON.id ];
+ };
+
+ const createSampleProductOrders = async ( simpleProducts ) => {
+ const single = simpleProducts.find(
+ ( p ) => p.name === 'Single oxo'
+ );
+ const beanie = simpleProducts.find(
+ ( p ) => p.name === 'Beanie with Logo oxo'
+ );
+ const shirt = simpleProducts.find(
+ ( p ) => p.name === 'T-Shirt oxo'
+ );
+
+ const order1 = await request.post( '/wp-json/wc/v3/orders', {
+ data: {
+ set_paid: true,
+ status: 'completed',
+ line_items: [
+ {
+ product_id: single.id,
+ quantity: 2,
+ },
+ {
+ product_id: beanie.id,
+ quantity: 3,
+ },
+ {
+ product_id: shirt.id,
+ quantity: 1,
+ },
+ ],
+ },
+ } );
+ const orderJSON = await order1.json();
+
+ return [ orderJSON ];
+ };
+
+ const productsTestSetupCreateSampleData = async () => {
+ const categories = await createSampleCategories();
+
+ const attributes = await createSampleAttributes();
+
+ const tags = await createSampleTags();
+
+ const shippingClasses = await createSampleShippingClasses();
+
+ const taxClasses = await createSampleTaxClasses();
+
+ const simpleProducts = await createSampleSimpleProducts(
+ categories,
+ attributes,
+ tags
+ );
+
+ const externalProducts = await createSampleExternalProducts(
+ categories
+ );
+
+ const groupedProducts = await createSampleGroupedProduct(
+ categories
+ );
+
+ const variableProducts = await createSampleVariableProducts(
+ categories,
+ attributes
+ );
+
+ const hierarchicalProducts =
+ await createSampleHierarchicalProducts();
+
+ const reviewIds = await createSampleProductReviews(
+ simpleProducts
+ );
+
+ const orders = await createSampleProductOrders(
+ simpleProducts
+ );
+
+ return {
+ categories,
+ attributes,
+ tags,
+ shippingClasses,
+ taxClasses,
+ simpleProducts,
+ externalProducts,
+ groupedProducts,
+ variableProducts,
+ hierarchicalProducts,
+ reviewIds,
+ orders,
+ };
+ };
+
+ // create Sample Data function
+ const createSampleData = async () => {
+ const testProductData =
+ await productsTestSetupCreateSampleData();
+ const orderedProducts = {
+ pocketHoodie: testProductData.simpleProducts.find(
+ ( p ) => p.name === 'Hoodie with Pocket oxo'
),
- pennant: testProductData.externalProducts[ 0 ],
- };
+ sunglasses: testProductData.simpleProducts.find(
+ ( p ) => p.name === 'Sunglasses oxo'
+ ),
+ beanie: testProductData.simpleProducts.find(
+ ( p ) => p.name === 'Beanie oxo'
+ ),
+ blueVneck:
+ testProductData.variableProducts.vneckVariations.find(
+ ( p ) => p.sku === 'woo-vneck-tee-blue'
+ ),
+ pennant: testProductData.externalProducts[ 0 ],
+ };
- const johnAddress = {
- first_name: 'John',
- last_name: 'Doe',
- company: 'Automattic',
- country: 'US',
- address_1: '60 29th Street',
- address_2: '#343',
- city: 'San Francisco',
- state: 'CA',
- postcode: '94110',
- phone: '123456789',
- };
- const tinaAddress = {
- first_name: 'Tina',
- last_name: 'Clark',
- company: 'Automattic',
- country: 'US',
- address_1: 'Oxford Ave',
- address_2: '',
- city: 'Buffalo',
- state: 'NY',
- postcode: '14201',
- phone: '123456789',
- };
- const guestShippingAddress = {
- first_name: 'Ano',
- last_name: 'Nymous',
- company: '',
- country: 'US',
- address_1: '0 Incognito St',
- address_2: '',
- city: 'Erie',
- state: 'PA',
- postcode: '16515',
- phone: '123456789',
- };
- const guestBillingAddress = {
- first_name: 'Ben',
- last_name: 'Efactor',
- company: '',
- country: 'US',
- address_1: '200 W University Avenue',
- address_2: '',
- city: 'Gainesville',
- state: 'FL',
- postcode: '32601',
- phone: '123456789',
- email: 'ben.efactor@email.net',
- };
-
- const john = await request.post( '/wp-json/wc/v3/customers', {
- data: {
+ const johnAddress = {
first_name: 'John',
last_name: 'Doe',
- username: 'john.doe',
- email: 'john.doe@example.com',
- billing: {
- ...johnAddress,
- email: 'john.doe@example.com',
- },
- shipping: johnAddress,
- },
- } );
- const johnJSON = await john.json();
-
- const tina = await request.post( '/wp-json/wc/v3/customers', {
- data: {
+ company: 'Automattic',
+ country: 'US',
+ address_1: '60 29th Street',
+ address_2: '#343',
+ city: 'San Francisco',
+ state: 'CA',
+ postcode: '94110',
+ phone: '123456789',
+ };
+ const tinaAddress = {
first_name: 'Tina',
last_name: 'Clark',
- username: 'tina.clark',
- email: 'tina.clark@example.com',
- billing: {
- ...tinaAddress,
- email: 'tina.clark@example.com',
- },
- shipping: tinaAddress,
- },
- } );
- const tinaJSON = await tina.json();
+ company: 'Automattic',
+ country: 'US',
+ address_1: 'Oxford Ave',
+ address_2: '',
+ city: 'Buffalo',
+ state: 'NY',
+ postcode: '14201',
+ phone: '123456789',
+ };
+ const guestShippingAddress = {
+ first_name: 'Ano',
+ last_name: 'Nymous',
+ company: '',
+ country: 'US',
+ address_1: '0 Incognito St',
+ address_2: '',
+ city: 'Erie',
+ state: 'PA',
+ postcode: '16515',
+ phone: '123456789',
+ };
+ const guestBillingAddress = {
+ first_name: 'Ben',
+ last_name: 'Efactor',
+ company: '',
+ country: 'US',
+ address_1: '200 W University Avenue',
+ address_2: '',
+ city: 'Gainesville',
+ state: 'FL',
+ postcode: '32601',
+ phone: '123456789',
+ email: 'ben.efactor@email.net',
+ };
- const orderBaseData = {
- payment_method: 'cod',
- payment_method_title: 'Cash on Delivery',
- status: 'processing',
- set_paid: false,
- currency: 'USD',
- customer_id: 0,
- };
-
- const orders = [];
- // Have "John" order all products.
- Object.values( orderedProducts ).forEach( async ( product ) => {
- const order2 = await request.post( '/wp-json/wc/v3/orders', {
+ const john = await request.post( '/wp-json/wc/v3/customers', {
data: {
- ...orderBaseData,
- customer_id: johnJSON.id,
+ first_name: 'John',
+ last_name: 'Doe',
+ username: 'john.doe',
+ email: 'john.doe@example.com',
billing: {
...johnAddress,
email: 'john.doe@example.com',
},
shipping: johnAddress,
- line_items: [
- {
- product_id: product.id,
- quantity: 1,
- },
- ],
},
} );
- const orderJSON = await order2.json();
+ const johnJSON = await john.json();
- orders.push( orderJSON );
- } );
-
- // Have "Tina" order some sunglasses and make a child order.
- // This somewhat resembles a subscription renewal, but we're just testing the `parent` field.
- const order2 = await request.post( '/wp-json/wc/v3/orders', {
- data: {
- ...orderBaseData,
- status: 'completed',
- set_paid: true,
- customer_id: tinaJSON.id,
- billing: {
- ...tinaAddress,
- email: 'tina.clark@example.com',
- },
- shipping: tinaAddress,
- line_items: [
- {
- product_id: orderedProducts.sunglasses.id,
- quantity: 1,
- },
- ],
- },
- } );
- const order2JSON = await order2.json();
-
- orders.push( order2JSON );
-
- // create child order by referencing a parent_id
- const order3 = await request.post( '/wp-json/wc/v3/orders', {
- data: {
- ...orderBaseData,
- parent_id: order2JSON.id,
- customer_id: tinaJSON.id,
- billing: {
- ...tinaAddress,
- email: 'tina.clark@example.com',
- },
- shipping: tinaAddress,
- line_items: [
- {
- product_id: orderedProducts.sunglasses.id,
- quantity: 1,
- },
- ],
- },
- } );
- const order3JSON = await order3.json();
-
- orders.push( order3JSON );
-
- // Guest order.
- const guestOrder = await request.post( '/wp-json/wc/v3/orders', {
- data: {
- ...orderBaseData,
- billing: guestBillingAddress,
- shipping: guestShippingAddress,
- line_items: [
- {
- product_id: orderedProducts.pennant.id,
- quantity: 2,
- },
- {
- product_id: orderedProducts.beanie.id,
- quantity: 1,
- },
- ],
- },
- } );
- const guestOrderJSON = await guestOrder.json();
-
- // Create an order with all possible numerical fields (taxes, fees, refunds, etc).
- await request.put(
- '/wp-json/wc/v3/settings/general/woocommerce_calc_taxes',
- {
+ const tina = await request.post( '/wp-json/wc/v3/customers', {
data: {
- value: 'yes',
+ first_name: 'Tina',
+ last_name: 'Clark',
+ username: 'tina.clark',
+ email: 'tina.clark@example.com',
+ billing: {
+ ...tinaAddress,
+ email: 'tina.clark@example.com',
+ },
+ shipping: tinaAddress,
},
- }
- );
+ } );
+ const tinaJSON = await tina.json();
- await request.post( '/wp-json/wc/v3/taxes', {
- data: {
- country: '*',
- state: '*',
- postcode: '*',
- city: '*',
- name: 'Tax',
- rate: '5.5',
- shipping: true,
- },
- } );
+ const orderBaseData = {
+ payment_method: 'cod',
+ payment_method_title: 'Cash on Delivery',
+ status: 'processing',
+ set_paid: false,
+ currency: 'USD',
+ customer_id: 0,
+ };
- const coupon = await request.post( '/wp-json/wc/v3/coupons', {
- data: {
- code: 'save5',
- amount: '5',
- },
- } );
- const couponJSON = await coupon.json();
-
- const order4 = await request.post( '/wp-json/wc/v3/orders', {
- data: {
- ...orderBaseData,
- line_items: [
+ const orders = [];
+ // Have "John" order all products.
+ Object.values( orderedProducts ).forEach( async ( product ) => {
+ const order2 = await request.post(
+ '/wp-json/wc/v3/orders',
{
- product_id: orderedProducts.blueVneck.id,
- quantity: 1,
- },
- ],
- coupon_lines: [
- {
- code: 'save5',
- },
- ],
- shipping_lines: [
- {
- method_id: 'flat_rate',
- total: '5.00',
- },
- ],
- fee_lines: [
- {
- total: '1.00',
- name: 'Test Fee',
- },
- ],
- },
- } );
- const order4JSON = await order4.json();
-
- await request.post(
- `/wp-json/wc/v3/orders/${ order4JSON.id }/refunds`,
- {
- data: {
- api_refund: false, // Prevent an actual refund request (fails with CoD),
- line_items: [
- {
- id: order4JSON.line_items[ 0 ].id,
- quantity: 1,
- refund_total: order4JSON.line_items[ 0 ].total,
- refund_tax: [
+ data: {
+ ...orderBaseData,
+ customer_id: johnJSON.id,
+ billing: {
+ ...johnAddress,
+ email: 'john.doe@example.com',
+ },
+ shipping: johnAddress,
+ line_items: [
{
- id: order4JSON.line_items[ 0 ]
- .taxes[ 0 ].id,
- refund_total:
- order4JSON.line_items[ 0 ]
- .total_tax,
+ product_id: product.id,
+ quantity: 1,
},
],
},
+ }
+ );
+ const orderJSON = await order2.json();
+
+ orders.push( orderJSON );
+ } );
+
+ // Have "Tina" order some sunglasses and make a child order.
+ // This somewhat resembles a subscription renewal, but we're just testing the `parent` field.
+ const order2 = await request.post( '/wp-json/wc/v3/orders', {
+ data: {
+ ...orderBaseData,
+ status: 'completed',
+ set_paid: true,
+ customer_id: tinaJSON.id,
+ billing: {
+ ...tinaAddress,
+ email: 'tina.clark@example.com',
+ },
+ shipping: tinaAddress,
+ line_items: [
+ {
+ product_id: orderedProducts.sunglasses.id,
+ quantity: 1,
+ },
],
},
- }
- );
- orders.push( order4JSON );
+ } );
+ const order2JSON = await order2.json();
- return {
- customers: {
- johnJSON,
- tinaJSON,
- },
- orders,
- precisionOrder: order4JSON,
- hierarchicalOrders: {
- parent: order2JSON,
- child: order3JSON,
- },
- guestOrderJSON,
- testProductData,
- couponJSON,
+ orders.push( order2JSON );
+
+ // create child order by referencing a parent_id
+ const order3 = await request.post( '/wp-json/wc/v3/orders', {
+ data: {
+ ...orderBaseData,
+ parent_id: order2JSON.id,
+ customer_id: tinaJSON.id,
+ billing: {
+ ...tinaAddress,
+ email: 'tina.clark@example.com',
+ },
+ shipping: tinaAddress,
+ line_items: [
+ {
+ product_id: orderedProducts.sunglasses.id,
+ quantity: 1,
+ },
+ ],
+ },
+ } );
+ const order3JSON = await order3.json();
+
+ orders.push( order3JSON );
+
+ // Guest order.
+ const guestOrder = await request.post(
+ '/wp-json/wc/v3/orders',
+ {
+ data: {
+ ...orderBaseData,
+ billing: guestBillingAddress,
+ shipping: guestShippingAddress,
+ line_items: [
+ {
+ product_id: orderedProducts.pennant.id,
+ quantity: 2,
+ },
+ {
+ product_id: orderedProducts.beanie.id,
+ quantity: 1,
+ },
+ ],
+ },
+ }
+ );
+ const guestOrderJSON = await guestOrder.json();
+
+ // Create an order with all possible numerical fields (taxes, fees, refunds, etc).
+ await request.put(
+ '/wp-json/wc/v3/settings/general/woocommerce_calc_taxes',
+ {
+ data: {
+ value: 'yes',
+ },
+ }
+ );
+
+ await request.post( '/wp-json/wc/v3/taxes', {
+ data: {
+ country: '*',
+ state: '*',
+ postcode: '*',
+ city: '*',
+ name: 'Tax',
+ rate: '5.5',
+ shipping: true,
+ },
+ } );
+
+ const coupon = await request.post( '/wp-json/wc/v3/coupons', {
+ data: {
+ code: 'save5',
+ amount: '5',
+ },
+ } );
+ const couponJSON = await coupon.json();
+
+ const order4 = await request.post( '/wp-json/wc/v3/orders', {
+ data: {
+ ...orderBaseData,
+ line_items: [
+ {
+ product_id: orderedProducts.blueVneck.id,
+ quantity: 1,
+ },
+ ],
+ coupon_lines: [
+ {
+ code: 'save5',
+ },
+ ],
+ shipping_lines: [
+ {
+ method_id: 'flat_rate',
+ total: '5.00',
+ },
+ ],
+ fee_lines: [
+ {
+ total: '1.00',
+ name: 'Test Fee',
+ },
+ ],
+ },
+ } );
+ const order4JSON = await order4.json();
+
+ await request.post(
+ `/wp-json/wc/v3/orders/${ order4JSON.id }/refunds`,
+ {
+ data: {
+ api_refund: false, // Prevent an actual refund request (fails with CoD),
+ line_items: [
+ {
+ id: order4JSON.line_items[ 0 ].id,
+ quantity: 1,
+ refund_total:
+ order4JSON.line_items[ 0 ].total,
+ refund_tax: [
+ {
+ id: order4JSON.line_items[ 0 ]
+ .taxes[ 0 ].id,
+ refund_total:
+ order4JSON.line_items[ 0 ]
+ .total_tax,
+ },
+ ],
+ },
+ ],
+ },
+ }
+ );
+ orders.push( order4JSON );
+
+ return {
+ customers: {
+ johnJSON,
+ tinaJSON,
+ },
+ orders,
+ precisionOrder: order4JSON,
+ hierarchicalOrders: {
+ parent: order2JSON,
+ child: order3JSON,
+ },
+ guestOrderJSON,
+ testProductData,
+ couponJSON,
+ };
};
- };
- sampleData = await createSampleData();
- }, 100000 );
+ sampleData = await createSampleData();
+ }, 100000 );
- test.afterAll( async ( { request } ) => {
- const productsTestSetupDeleteSampleData = async ( _sampleData ) => {
- const {
- categories,
- attributes,
- tags,
- shippingClasses,
- taxClasses,
- simpleProducts,
- externalProducts,
- groupedProducts,
- variableProducts,
- hierarchicalProducts,
- orders,
- } = _sampleData;
+ test.afterAll( async ( { request } ) => {
+ const productsTestSetupDeleteSampleData = async ( _sampleData ) => {
+ const {
+ categories,
+ attributes,
+ tags,
+ shippingClasses,
+ taxClasses,
+ simpleProducts,
+ externalProducts,
+ groupedProducts,
+ variableProducts,
+ hierarchicalProducts,
+ orders,
+ } = _sampleData;
- const productIds = []
- .concat( simpleProducts.map( ( p ) => p.id ) )
- .concat( externalProducts.map( ( p ) => p.id ) )
- .concat( groupedProducts.map( ( p ) => p.id ) )
- .concat( [
- variableProducts.hoodieJSON.id,
- variableProducts.vneckJSON.id,
- ] )
- .concat( [
- hierarchicalProducts.parentJSON.id,
- hierarchicalProducts.childJSON.id,
- ] );
+ const productIds = []
+ .concat( simpleProducts.map( ( p ) => p.id ) )
+ .concat( externalProducts.map( ( p ) => p.id ) )
+ .concat( groupedProducts.map( ( p ) => p.id ) )
+ .concat( [
+ variableProducts.hoodieJSON.id,
+ variableProducts.vneckJSON.id,
+ ] )
+ .concat( [
+ hierarchicalProducts.parentJSON.id,
+ hierarchicalProducts.childJSON.id,
+ ] );
- for ( const _order of orders ) {
- await request.delete( `/wp-json/wc/v3/orders/${ _order.id }`, {
- data: {
- force: true,
- },
- } );
- }
-
- for ( const productId of productIds ) {
- await request.delete(
- `/wp-json/wc/v3/products/${ productId }`,
- {
- data: {
- force: true,
- },
- }
- );
- }
-
- await request.delete(
- `/wp-json/wc/v3/products/attributes/${ attributes.colorJSON.id }`,
- {
- data: {
- force: true,
- },
+ for ( const _order of orders ) {
+ await request.delete(
+ `/wp-json/wc/v3/orders/${ _order.id }`,
+ {
+ data: {
+ force: true,
+ },
+ }
+ );
}
- );
- await request.delete(
- `/wp-json/wc/v3/products/attributes/${ attributes.sizeJSON.id }`,
- {
- data: {
- force: true,
- },
+ for ( const productId of productIds ) {
+ await request.delete(
+ `/wp-json/wc/v3/products/${ productId }`,
+ {
+ data: {
+ force: true,
+ },
+ }
+ );
}
- );
- for ( const category of Object.values( categories ) ) {
await request.delete(
- `/wp-json/wc/v3/products/categories/${ category.id }`,
+ `/wp-json/wc/v3/products/attributes/${ attributes.colorJSON.id }`,
{
data: {
force: true,
},
}
);
- }
- for ( const tag of Object.values( tags ) ) {
await request.delete(
- `/wp-json/wc/v3/products/tags/${ tag.id }`,
+ `/wp-json/wc/v3/products/attributes/${ attributes.sizeJSON.id }`,
{
data: {
force: true,
},
}
);
- }
- for ( const shippingClass of Object.values( shippingClasses ) ) {
- await request.delete(
- `/wp-json/wc/v3/products/shipping_classes/${ shippingClass.id }`,
- {
- data: {
- force: true,
- },
- }
+ for ( const category of Object.values( categories ) ) {
+ await request.delete(
+ `/wp-json/wc/v3/products/categories/${ category.id }`,
+ {
+ data: {
+ force: true,
+ },
+ }
+ );
+ }
+
+ for ( const tag of Object.values( tags ) ) {
+ await request.delete(
+ `/wp-json/wc/v3/products/tags/${ tag.id }`,
+ {
+ data: {
+ force: true,
+ },
+ }
+ );
+ }
+
+ for ( const shippingClass of Object.values(
+ shippingClasses
+ ) ) {
+ await request.delete(
+ `/wp-json/wc/v3/products/shipping_classes/${ shippingClass.id }`,
+ {
+ data: {
+ force: true,
+ },
+ }
+ );
+ }
+
+ for ( const taxClass of Object.values( taxClasses ) ) {
+ await request.delete(
+ `/wp-json/wc/v3/taxes/classes/${ taxClass.slug }`,
+ {
+ data: {
+ force: true,
+ },
+ }
+ );
+ }
+ };
+
+ const deleteSampleData = async ( _sampleData ) => {
+ await productsTestSetupDeleteSampleData(
+ _sampleData.testProductData
);
- }
- for ( const taxClass of Object.values( taxClasses ) ) {
- await request.delete(
- `/wp-json/wc/v3/taxes/classes/${ taxClass.slug }`,
- {
- data: {
- force: true,
- },
- }
- );
- }
- };
+ for ( const _order of _sampleData.orders.concat( [
+ _sampleData.guestOrderJSON,
+ ] ) ) {
+ await request.delete(
+ `/wp-json/wc/v3/orders/${ _order.id }`,
+ {
+ data: {
+ force: true,
+ },
+ }
+ );
+ }
- const deleteSampleData = async ( _sampleData ) => {
- await productsTestSetupDeleteSampleData(
- _sampleData.testProductData
- );
+ for ( const customer of Object.values(
+ _sampleData.customers
+ ) ) {
+ await request.delete(
+ `/wp-json/wc/v3/customers/${ customer.id }`,
+ {
+ data: {
+ force: true,
+ },
+ }
+ );
+ }
+ };
- for ( const _order of _sampleData.orders.concat( [
- _sampleData.guestOrderJSON,
- ] ) ) {
- await request.delete( `/wp-json/wc/v3/orders/${ _order.id }`, {
- data: {
- force: true,
- },
- } );
- }
+ await deleteSampleData( sampleData );
+ }, 10000 );
- for ( const customer of Object.values( _sampleData.customers ) ) {
- await request.delete(
- `/wp-json/wc/v3/customers/${ customer.id }`,
- {
- data: {
- force: true,
- },
- }
- );
- }
- };
-
- await deleteSampleData( sampleData );
- }, 10000 );
-
- test( 'can create an order', async ( { request } ) => {
- const response = await request.post( '/wp-json/wc/v3/orders', {
- data: order,
- } );
- const responseJSON = await response.json();
-
- expect( response.status() ).toEqual( 201 );
- expect( responseJSON.id ).toBeDefined();
- orderId = responseJSON.id;
-
- // Validate the data type and verify the order is in a pending state
- expect( typeof responseJSON.status ).toBe( 'string' );
- expect( responseJSON.status ).toEqual( 'pending' );
- } );
-
- test( 'can retrieve an order', async ( { request } ) => {
- const response = await request.get(
- `/wp-json/wc/v3/orders/${ orderId }`
- );
- const responseJSON = await response.json();
-
- expect( response.status() ).toEqual( 200 );
- expect( responseJSON.id ).toEqual( orderId );
- } );
-
- test( 'can add shipping and billing contacts to an order', async ( {
- request,
- } ) => {
- // Update the billing and shipping fields on the order
- order.billing = updatedCustomerBilling;
- order.shipping = updatedCustomerShipping;
-
- const response = await request.put(
- `/wp-json/wc/v3/orders/${ orderId }`,
- {
+ test( 'can create an order', async ( { request } ) => {
+ const response = await request.post( '/wp-json/wc/v3/orders', {
data: order,
- }
- );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
-
- expect( responseJSON.billing ).toEqual( updatedCustomerBilling );
- expect( responseJSON.shipping ).toEqual( updatedCustomerShipping );
- } );
-
- test( 'can permanently delete an order', async ( { request } ) => {
- const response = await request.delete(
- `/wp-json/wc/v3/orders/${ orderId }`,
- {
- data: {
- force: true,
- },
- }
- );
- expect( response.status() ).toEqual( 200 );
-
- const getOrderResponse = await request.get(
- `/wp-json/wc/v3/orders/${ orderId }`
- );
- expect( getOrderResponse.status() ).toEqual( 404 );
- } );
-
- test.describe( 'List all orders', () => {
- const ORDERS_COUNT = 10;
-
- test( 'pagination', async ( { request } ) => {
- const pageSize = 4;
- const page1 = await request.get( '/wp-json/wc/v3/orders', {
- params: {
- per_page: pageSize,
- search: 'oxo',
- },
} );
- const page1JSON = await page1.json();
+ const responseJSON = await response.json();
- const page2 = await request.get( '/wp-json/wc/v3/orders', {
- params: {
- per_page: pageSize,
- page: 2,
- search: 'oxo',
- },
- } );
- const page2JSON = await page2.json();
+ expect( response.status() ).toEqual( 201 );
+ expect( responseJSON.id ).toBeDefined();
+ orderId = responseJSON.id;
- expect( page1.status() ).toEqual( 200 );
- expect( page2.status() ).toEqual( 200 );
-
- // Verify total page count.
- expect( page1.headers()[ 'x-wp-total' ] ).toEqual(
- ORDERS_COUNT.toString()
- );
- expect( page1.headers()[ 'x-wp-totalpages' ] ).toEqual( '3' );
-
- // Verify we get pageSize'd arrays.
- expect( Array.isArray( page1JSON ) ).toBe( true );
- expect( Array.isArray( page2JSON ) ).toBe( true );
- expect( page1JSON ).toHaveLength( pageSize );
- expect( page2JSON ).toHaveLength( pageSize );
-
- // Ensure all of the order IDs are unique (no page overlap).
- const allOrderIds = page1JSON
- .concat( page2JSON )
- .reduce( ( acc, { id } ) => {
- acc[ id ] = 1;
- return acc;
- }, {} );
- expect( Object.keys( allOrderIds ) ).toHaveLength( pageSize * 2 );
-
- // Verify that offset takes precedent over page number.
- const page2Offset = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- per_page: pageSize,
- page: 2,
- offset: pageSize + 1,
- search: 'oxo',
- },
- } );
- const page2OffsetJSON = await page2Offset.json();
-
- // The offset pushes the result set 1 order past the start of page 2.
- expect( page2OffsetJSON ).toEqual(
- expect.not.arrayContaining( [
- expect.objectContaining( {
- id: page2JSON[ 0 ].id,
- } ),
- ] )
- );
- expect( page2OffsetJSON[ 0 ].id ).toEqual( page2JSON[ 1 ].id );
-
- // Verify the last page only has 1 order as we expect.
- const lastPage = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- per_page: pageSize,
- page: 3,
- search: 'oxo',
- },
- } );
- const lastPageJSON = await lastPage.json();
-
- expect( Array.isArray( lastPageJSON ) ).toBe( true );
- expect( lastPageJSON ).toHaveLength( 2 );
-
- // Verify a page outside the total page count is empty.
- const page6 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- page: 6,
- search: 'oxo',
- },
- } );
- const page6JSON = await page6.json();
-
- expect( Array.isArray( page6JSON ) ).toBe( true );
- expect( page6JSON ).toHaveLength( 0 );
+ // Validate the data type and verify the order is in a pending state
+ expect( typeof responseJSON.status ).toBe( 'string' );
+ expect( responseJSON.status ).toEqual( 'pending' );
} );
- test( 'inclusion / exclusion', async ( { request } ) => {
- const allOrders = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- per_page: 10,
- search: 'oxo',
- },
- } );
- const allOrdersJSON = await allOrders.json();
-
- expect( allOrders.status() ).toEqual( 200 );
- const allOrdersIds = allOrdersJSON.map( ( _order ) => _order.id );
- expect( allOrdersIds ).toHaveLength( ORDERS_COUNT );
-
- const ordersToFilter = [
- allOrdersIds[ 0 ],
- allOrdersIds[ 2 ],
- allOrdersIds[ 4 ],
- allOrdersIds[ 7 ],
- ];
-
- const included = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- per_page: 20,
- include: ordersToFilter.join( ',' ),
- },
- } );
- const includedJSON = await included.json();
-
- expect( included.status() ).toEqual( 200 );
- expect( includedJSON ).toHaveLength( ordersToFilter.length );
- expect( includedJSON ).toEqual(
- expect.arrayContaining(
- ordersToFilter.map( ( id ) =>
- expect.objectContaining( {
- id,
- } )
- )
- )
+ test( 'can retrieve an order', async ( { request } ) => {
+ const response = await request.get(
+ `/wp-json/wc/v3/orders/${ orderId }`
);
+ const responseJSON = await response.json();
- const excluded = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- per_page: 20,
- exclude: ordersToFilter.join( ',' ),
- },
- } );
- const excludedJSON = await excluded.json();
-
- expect( excluded.status() ).toEqual( 200 );
- expect( excludedJSON.length ).toBeGreaterThanOrEqual(
- Number( ORDERS_COUNT - ordersToFilter.length )
- );
- expect( excludedJSON ).toEqual(
- expect.not.arrayContaining(
- ordersToFilter.map( ( id ) =>
- expect.objectContaining( {
- id,
- } )
- )
- )
- );
+ expect( response.status() ).toEqual( 200 );
+ expect( responseJSON.id ).toEqual( orderId );
} );
- test( 'parent', async ( { request } ) => {
- const result1 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- parent: sampleData.hierarchicalOrders.parent.id,
- },
- } );
- const result1JSON = await result1.json();
+ test( 'can add shipping and billing contacts to an order', async ( {
+ request,
+ } ) => {
+ // Update the billing and shipping fields on the order
+ order.billing = updatedCustomerBilling;
+ order.shipping = updatedCustomerShipping;
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength( 1 );
- expect( result1JSON[ 0 ].id ).toBe(
- sampleData.hierarchicalOrders.child.id
+ const response = await request.put(
+ `/wp-json/wc/v3/orders/${ orderId }`,
+ {
+ data: order,
+ }
);
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
- const result2 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- parent_exclude: sampleData.hierarchicalOrders.parent.id,
- },
- } );
- const result2JSON = await result2.json();
-
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toEqual(
- expect.not.arrayContaining( [
- expect.objectContaining( {
- id: sampleData.hierarchicalOrders.child.id,
- } ),
- ] )
- );
+ expect( responseJSON.billing ).toEqual( updatedCustomerBilling );
+ expect( responseJSON.shipping ).toEqual( updatedCustomerShipping );
} );
- test( 'status', async ( { request } ) => {
- const result1 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- status: 'completed',
- search: 'oxo',
- },
- } );
- const result1JSON = await result1.json();
-
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength( 2 );
- expect( result1JSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- status: 'completed',
- customer_id: 0,
- line_items: expect.arrayContaining( [
- expect.objectContaining( {
- name: 'Single oxo',
- quantity: 2,
- } ),
- expect.objectContaining( {
- name: 'Beanie with Logo oxo',
- quantity: 3,
- } ),
- expect.objectContaining( {
- name: 'T-Shirt oxo',
- quantity: 1,
- } ),
- ] ),
- } ),
- expect.objectContaining( {
- status: 'completed',
- customer_id: sampleData.customers.tinaJSON.id,
- line_items: expect.arrayContaining( [
- expect.objectContaining( {
- name: 'Sunglasses oxo',
- quantity: 1,
- } ),
- ] ),
- } ),
- ] )
+ test( 'can permanently delete an order', async ( { request } ) => {
+ const response = await request.delete(
+ `/wp-json/wc/v3/orders/${ orderId }`,
+ {
+ data: {
+ force: true,
+ },
+ }
);
+ expect( response.status() ).toEqual( 200 );
- const result2 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- status: 'processing',
- search: 'oxo',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toHaveLength( 8 );
- expect( result2JSON ).toEqual(
- expect.not.arrayContaining(
- result1JSON.map( ( { id } ) =>
- expect.objectContaining( {
- id,
- } )
- )
- )
+ const getOrderResponse = await request.get(
+ `/wp-json/wc/v3/orders/${ orderId }`
);
+ expect( getOrderResponse.status() ).toEqual( 404 );
} );
- test( 'customer', async ( { request } ) => {
- const result1 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- customer: sampleData.customers.johnJSON.id,
- },
- } );
- const result1JSON = await result1.json();
+ test.describe( 'List all orders', () => {
+ const ORDERS_COUNT = 10;
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength( 5 );
- result1JSON.forEach( ( _order ) =>
- expect( _order ).toEqual(
- expect.objectContaining( {
- customer_id: sampleData.customers.johnJSON.id,
- } )
- )
- );
+ test( 'pagination', async ( { request } ) => {
+ const pageSize = 4;
+ const page1 = await request.get( '/wp-json/wc/v3/orders', {
+ params: {
+ per_page: pageSize,
+ search: 'oxo',
+ },
+ } );
+ const page1JSON = await page1.json();
- const result2 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- customer: 0,
- search: 'oxo',
- },
- } );
- const result2JSON = await result2.json();
+ const page2 = await request.get( '/wp-json/wc/v3/orders', {
+ params: {
+ per_page: pageSize,
+ page: 2,
+ search: 'oxo',
+ },
+ } );
+ const page2JSON = await page2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toHaveLength( 3 );
- result2JSON.forEach( ( _order ) =>
- expect( _order ).toEqual(
- expect.objectContaining( {
- customer_id: 0,
- } )
- )
- );
- } );
+ expect( page1.status() ).toEqual( 200 );
+ expect( page2.status() ).toEqual( 200 );
- test( 'product', async ( { request } ) => {
- const beanie = sampleData.testProductData.simpleProducts.find(
- ( p ) => p.name === 'Beanie oxo'
- );
- const result1 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- product: beanie.id,
- },
- } );
- const result1JSON = await result1.json();
-
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength( 2 );
- result1JSON.forEach( ( _order ) =>
- expect( _order ).toEqual(
- expect.objectContaining( {
- line_items: expect.arrayContaining( [
- expect.objectContaining( {
- name: 'Beanie oxo',
- } ),
- ] ),
- } )
- )
- );
- } );
-
- // NOTE: This does not verify the `taxes` array nested in line items.
- // While the precision parameter doesn't affect those values, after some
- // discussion it seems `dp` may not be supported in v4 of the API.
- test( 'dp (precision)', async ( { request } ) => {
- const expectPrecisionToMatch = ( value, dp ) => {
- expect( value ).toEqual(
- Number.parseFloat( value ).toFixed( dp )
+ // Verify total page count.
+ expect( page1.headers()[ 'x-wp-total' ] ).toEqual(
+ ORDERS_COUNT.toString()
);
- };
+ expect( page1.headers()[ 'x-wp-totalpages' ] ).toEqual( '3' );
- const verifyOrderPrecision = ( _order, dp ) => {
- expectPrecisionToMatch( _order.discount_total, dp );
- expectPrecisionToMatch( _order.discount_tax, dp );
- expectPrecisionToMatch( _order.shipping_total, dp );
- expectPrecisionToMatch( _order.shipping_tax, dp );
- expectPrecisionToMatch( _order.cart_tax, dp );
- expectPrecisionToMatch( _order.total, dp );
- expectPrecisionToMatch( _order.total_tax, dp );
+ // Verify we get pageSize'd arrays.
+ expect( Array.isArray( page1JSON ) ).toBe( true );
+ expect( Array.isArray( page2JSON ) ).toBe( true );
+ expect( page1JSON ).toHaveLength( pageSize );
+ expect( page2JSON ).toHaveLength( pageSize );
- _order.line_items.forEach( ( lineItem ) => {
- expectPrecisionToMatch( lineItem.total, dp );
- expectPrecisionToMatch( lineItem.total_tax, dp );
- } );
+ // Ensure all of the order IDs are unique (no page overlap).
+ const allOrderIds = page1JSON
+ .concat( page2JSON )
+ .reduce( ( acc, { id } ) => {
+ acc[ id ] = 1;
+ return acc;
+ }, {} );
+ expect( Object.keys( allOrderIds ) ).toHaveLength(
+ pageSize * 2
+ );
- _order.tax_lines.forEach( ( taxLine ) => {
- expectPrecisionToMatch( taxLine.tax_total, dp );
- expectPrecisionToMatch( taxLine.shipping_tax_total, dp );
- } );
-
- _order.shipping_lines.forEach( ( shippingLine ) => {
- expectPrecisionToMatch( shippingLine.total, dp );
- expectPrecisionToMatch( shippingLine.total_tax, dp );
- } );
-
- _order.fee_lines.forEach( ( feeLine ) => {
- expectPrecisionToMatch( feeLine.total, dp );
- expectPrecisionToMatch( feeLine.total_tax, dp );
- } );
-
- _order.refunds.forEach( ( refund ) => {
- expectPrecisionToMatch( refund.total, dp );
- } );
- };
-
- const result1 = await request.get(
- `wp-json/wc/v3/orders/${ sampleData.precisionOrder.id }`,
- {
+ // Verify that offset takes precedent over page number.
+ const page2Offset = await request.get( 'wp-json/wc/v3/orders', {
params: {
- dp: 1,
+ per_page: pageSize,
+ page: 2,
+ offset: pageSize + 1,
+ search: 'oxo',
},
- }
- );
- const result1JSON = await result1.json();
+ } );
+ const page2OffsetJSON = await page2Offset.json();
- expect( result1.status() ).toEqual( 200 );
- verifyOrderPrecision( result1JSON, 1 );
+ // The offset pushes the result set 1 order past the start of page 2.
+ expect( page2OffsetJSON ).toEqual(
+ expect.not.arrayContaining( [
+ expect.objectContaining( {
+ id: page2JSON[ 0 ].id,
+ } ),
+ ] )
+ );
+ expect( page2OffsetJSON[ 0 ].id ).toEqual( page2JSON[ 1 ].id );
- const result2 = await request.get(
- `wp-json/wc/v3/orders/${ sampleData.precisionOrder.id }`,
- {
+ // Verify the last page only has 1 order as we expect.
+ const lastPage = await request.get( 'wp-json/wc/v3/orders', {
params: {
- dp: 3,
+ per_page: pageSize,
+ page: 3,
+ search: 'oxo',
},
- }
- );
- const result2JSON = await result2.json();
+ } );
+ const lastPageJSON = await lastPage.json();
- expect( result2.status() ).toEqual( 200 );
- verifyOrderPrecision( result2JSON, 3 );
+ expect( Array.isArray( lastPageJSON ) ).toBe( true );
+ expect( lastPageJSON ).toHaveLength( 2 );
- const result3 = await request.get(
- `wp-json/wc/v3/orders/${ sampleData.precisionOrder.id }`
- );
- const result3JSON = await result3.json();
+ // Verify a page outside the total page count is empty.
+ const page6 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ page: 6,
+ search: 'oxo',
+ },
+ } );
+ const page6JSON = await page6.json();
- expect( result3.status() ).toEqual( 200 );
- verifyOrderPrecision( result3JSON, 2 ); // The default value for 'dp' is 2.
- } );
-
- test( 'search', async ( { request } ) => {
- // By default, 'search' looks in:
- // - _billing_address_index
- // - _shipping_address_index
- // - _billing_last_name
- // - _billing_email
- // - order_item_name
-
- // Test billing email.
- const result1 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- search: 'example.com',
- },
+ expect( Array.isArray( page6JSON ) ).toBe( true );
+ expect( page6JSON ).toHaveLength( 0 );
} );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON.length ).toBeGreaterThanOrEqual( 1 );
- result1JSON.forEach( ( _order ) =>
- expect( _order.billing.email ).toContain( 'example.com' )
- );
+ test( 'inclusion / exclusion', async ( { request } ) => {
+ const allOrders = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ per_page: 10,
+ search: 'oxo',
+ },
+ } );
+ const allOrdersJSON = await allOrders.json();
- // Test billing address.
- const result2 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- search: 'gainesville',
- },
- } );
- const result2JSON = await result2.json();
+ expect( allOrders.status() ).toEqual( 200 );
+ const allOrdersIds = allOrdersJSON.map(
+ ( _order ) => _order.id
+ );
+ expect( allOrdersIds ).toHaveLength( ORDERS_COUNT );
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toHaveLength( 1 );
- expect( result2JSON[ 0 ].id ).toEqual(
- sampleData.guestOrderJSON.id
- );
+ const ordersToFilter = [
+ allOrdersIds[ 0 ],
+ allOrdersIds[ 2 ],
+ allOrdersIds[ 4 ],
+ allOrdersIds[ 7 ],
+ ];
- // Test shipping address.
- const result3 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- search: 'Incognito',
- },
- } );
- const result3JSON = await result3.json();
+ const included = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ per_page: 20,
+ include: ordersToFilter.join( ',' ),
+ },
+ } );
+ const includedJSON = await included.json();
- expect( result3.status() ).toEqual( 200 );
- expect( result3JSON ).toHaveLength( 1 );
- expect( result3JSON[ 0 ].id ).toEqual(
- sampleData.guestOrderJSON.id
- );
-
- // Test billing last name.
- const result4 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- search: 'Doe',
- },
- } );
- const result4JSON = await result4.json();
-
- expect( result4.status() ).toEqual( 200 );
- expect( result4JSON.length ).toBeGreaterThanOrEqual( 1 );
- result4JSON.forEach( ( _order ) =>
- expect( _order.billing.last_name ).toEqual( 'Doe' )
- );
-
- // Test order item name.
- const result5 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- search: 'Pennant oxo',
- },
- } );
- const result5JSON = await result5.json();
-
- expect( result5.status() ).toEqual( 200 );
- expect( result5JSON ).toHaveLength( 2 );
- result5JSON.forEach( ( _order ) =>
- expect( _order ).toEqual(
- expect.objectContaining( {
- line_items: expect.arrayContaining( [
+ expect( included.status() ).toEqual( 200 );
+ expect( includedJSON ).toHaveLength( ordersToFilter.length );
+ expect( includedJSON ).toEqual(
+ expect.arrayContaining(
+ ordersToFilter.map( ( id ) =>
expect.objectContaining( {
- name: 'WordPress Pennant oxo',
- } ),
- ] ),
- } )
- )
- );
- } );
- } );
+ id,
+ } )
+ )
+ )
+ );
- test.describe( 'orderby', () => {
- // The orders endpoint `orderby` parameter uses WP_Query, so our tests won't
- // include slug and title, since they are programmatically generated.
- test( 'default', async ( { request } ) => {
- // Default = date desc.
- const result = await request.get( 'wp-json/wc/v3/orders' );
- const resultJSON = await result.json();
- expect( result.status() ).toEqual( 200 );
+ const excluded = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ per_page: 20,
+ exclude: ordersToFilter.join( ',' ),
+ },
+ } );
+ const excludedJSON = await excluded.json();
- // Verify all dates are in descending order.
- let lastDate = Date.now();
- resultJSON.forEach( ( { date_created } ) => {
- const created = Date.parse( date_created + '.000Z' );
- expect( lastDate ).toBeGreaterThanOrEqual( created );
- lastDate = created;
+ expect( excluded.status() ).toEqual( 200 );
+ expect( excludedJSON.length ).toBeGreaterThanOrEqual(
+ Number( ORDERS_COUNT - ordersToFilter.length )
+ );
+ expect( excludedJSON ).toEqual(
+ expect.not.arrayContaining(
+ ordersToFilter.map( ( id ) =>
+ expect.objectContaining( {
+ id,
+ } )
+ )
+ )
+ );
+ } );
+
+ test( 'parent', async ( { request } ) => {
+ const result1 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ parent: sampleData.hierarchicalOrders.parent.id,
+ },
+ } );
+ const result1JSON = await result1.json();
+
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength( 1 );
+ expect( result1JSON[ 0 ].id ).toBe(
+ sampleData.hierarchicalOrders.child.id
+ );
+
+ const result2 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ parent_exclude: sampleData.hierarchicalOrders.parent.id,
+ },
+ } );
+ const result2JSON = await result2.json();
+
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toEqual(
+ expect.not.arrayContaining( [
+ expect.objectContaining( {
+ id: sampleData.hierarchicalOrders.child.id,
+ } ),
+ ] )
+ );
+ } );
+
+ test( 'status', async ( { request } ) => {
+ const result1 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ status: 'completed',
+ search: 'oxo',
+ },
+ } );
+ const result1JSON = await result1.json();
+
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength( 2 );
+ expect( result1JSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ status: 'completed',
+ customer_id: 0,
+ line_items: expect.arrayContaining( [
+ expect.objectContaining( {
+ name: 'Single oxo',
+ quantity: 2,
+ } ),
+ expect.objectContaining( {
+ name: 'Beanie with Logo oxo',
+ quantity: 3,
+ } ),
+ expect.objectContaining( {
+ name: 'T-Shirt oxo',
+ quantity: 1,
+ } ),
+ ] ),
+ } ),
+ expect.objectContaining( {
+ status: 'completed',
+ customer_id: sampleData.customers.tinaJSON.id,
+ line_items: expect.arrayContaining( [
+ expect.objectContaining( {
+ name: 'Sunglasses oxo',
+ quantity: 1,
+ } ),
+ ] ),
+ } ),
+ ] )
+ );
+
+ const result2 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ status: 'processing',
+ search: 'oxo',
+ },
+ } );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toHaveLength( 8 );
+ expect( result2JSON ).toEqual(
+ expect.not.arrayContaining(
+ result1JSON.map( ( { id } ) =>
+ expect.objectContaining( {
+ id,
+ } )
+ )
+ )
+ );
+ } );
+
+ test( 'customer', async ( { request } ) => {
+ const result1 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ customer: sampleData.customers.johnJSON.id,
+ },
+ } );
+ const result1JSON = await result1.json();
+
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength( 5 );
+ result1JSON.forEach( ( _order ) =>
+ expect( _order ).toEqual(
+ expect.objectContaining( {
+ customer_id: sampleData.customers.johnJSON.id,
+ } )
+ )
+ );
+
+ const result2 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ customer: 0,
+ search: 'oxo',
+ },
+ } );
+ const result2JSON = await result2.json();
+
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toHaveLength( 3 );
+ result2JSON.forEach( ( _order ) =>
+ expect( _order ).toEqual(
+ expect.objectContaining( {
+ customer_id: 0,
+ } )
+ )
+ );
+ } );
+
+ test( 'product', async ( { request } ) => {
+ const beanie = sampleData.testProductData.simpleProducts.find(
+ ( p ) => p.name === 'Beanie oxo'
+ );
+ const result1 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ product: beanie.id,
+ },
+ } );
+ const result1JSON = await result1.json();
+
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength( 2 );
+ result1JSON.forEach( ( _order ) =>
+ expect( _order ).toEqual(
+ expect.objectContaining( {
+ line_items: expect.arrayContaining( [
+ expect.objectContaining( {
+ name: 'Beanie oxo',
+ } ),
+ ] ),
+ } )
+ )
+ );
+ } );
+
+ // NOTE: This does not verify the `taxes` array nested in line items.
+ // While the precision parameter doesn't affect those values, after some
+ // discussion it seems `dp` may not be supported in v4 of the API.
+ test( 'dp (precision)', async ( { request } ) => {
+ const expectPrecisionToMatch = ( value, dp ) => {
+ expect( value ).toEqual(
+ Number.parseFloat( value ).toFixed( dp )
+ );
+ };
+
+ const verifyOrderPrecision = ( _order, dp ) => {
+ expectPrecisionToMatch( _order.discount_total, dp );
+ expectPrecisionToMatch( _order.discount_tax, dp );
+ expectPrecisionToMatch( _order.shipping_total, dp );
+ expectPrecisionToMatch( _order.shipping_tax, dp );
+ expectPrecisionToMatch( _order.cart_tax, dp );
+ expectPrecisionToMatch( _order.total, dp );
+ expectPrecisionToMatch( _order.total_tax, dp );
+
+ _order.line_items.forEach( ( lineItem ) => {
+ expectPrecisionToMatch( lineItem.total, dp );
+ expectPrecisionToMatch( lineItem.total_tax, dp );
+ } );
+
+ _order.tax_lines.forEach( ( taxLine ) => {
+ expectPrecisionToMatch( taxLine.tax_total, dp );
+ expectPrecisionToMatch(
+ taxLine.shipping_tax_total,
+ dp
+ );
+ } );
+
+ _order.shipping_lines.forEach( ( shippingLine ) => {
+ expectPrecisionToMatch( shippingLine.total, dp );
+ expectPrecisionToMatch( shippingLine.total_tax, dp );
+ } );
+
+ _order.fee_lines.forEach( ( feeLine ) => {
+ expectPrecisionToMatch( feeLine.total, dp );
+ expectPrecisionToMatch( feeLine.total_tax, dp );
+ } );
+
+ _order.refunds.forEach( ( refund ) => {
+ expectPrecisionToMatch( refund.total, dp );
+ } );
+ };
+
+ const result1 = await request.get(
+ `wp-json/wc/v3/orders/${ sampleData.precisionOrder.id }`,
+ {
+ params: {
+ dp: 1,
+ },
+ }
+ );
+ const result1JSON = await result1.json();
+
+ expect( result1.status() ).toEqual( 200 );
+ verifyOrderPrecision( result1JSON, 1 );
+
+ const result2 = await request.get(
+ `wp-json/wc/v3/orders/${ sampleData.precisionOrder.id }`,
+ {
+ params: {
+ dp: 3,
+ },
+ }
+ );
+ const result2JSON = await result2.json();
+
+ expect( result2.status() ).toEqual( 200 );
+ verifyOrderPrecision( result2JSON, 3 );
+
+ const result3 = await request.get(
+ `wp-json/wc/v3/orders/${ sampleData.precisionOrder.id }`
+ );
+ const result3JSON = await result3.json();
+
+ expect( result3.status() ).toEqual( 200 );
+ verifyOrderPrecision( result3JSON, 2 ); // The default value for 'dp' is 2.
+ } );
+
+ test( 'search', async ( { request } ) => {
+ // By default, 'search' looks in:
+ // - _billing_address_index
+ // - _shipping_address_index
+ // - _billing_last_name
+ // - _billing_email
+ // - order_item_name
+
+ // Test billing email.
+ const result1 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ search: 'example.com',
+ },
+ } );
+ const result1JSON = await result1.json();
+
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON.length ).toBeGreaterThanOrEqual( 1 );
+ result1JSON.forEach( ( _order ) =>
+ expect( _order.billing.email ).toContain( 'example.com' )
+ );
+
+ // Test billing address.
+ const result2 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ search: 'gainesville',
+ },
+ } );
+ const result2JSON = await result2.json();
+
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toHaveLength( 1 );
+ expect( result2JSON[ 0 ].id ).toEqual(
+ sampleData.guestOrderJSON.id
+ );
+
+ // Test shipping address.
+ const result3 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ search: 'Incognito',
+ },
+ } );
+ const result3JSON = await result3.json();
+
+ expect( result3.status() ).toEqual( 200 );
+ expect( result3JSON ).toHaveLength( 1 );
+ expect( result3JSON[ 0 ].id ).toEqual(
+ sampleData.guestOrderJSON.id
+ );
+
+ // Test billing last name.
+ const result4 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ search: 'Doe',
+ },
+ } );
+ const result4JSON = await result4.json();
+
+ expect( result4.status() ).toEqual( 200 );
+ expect( result4JSON.length ).toBeGreaterThanOrEqual( 1 );
+ result4JSON.forEach( ( _order ) =>
+ expect( _order.billing.last_name ).toEqual( 'Doe' )
+ );
+
+ // Test order item name.
+ const result5 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ search: 'Pennant oxo',
+ },
+ } );
+ const result5JSON = await result5.json();
+
+ expect( result5.status() ).toEqual( 200 );
+ expect( result5JSON ).toHaveLength( 2 );
+ result5JSON.forEach( ( _order ) =>
+ expect( _order ).toEqual(
+ expect.objectContaining( {
+ line_items: expect.arrayContaining( [
+ expect.objectContaining( {
+ name: 'WordPress Pennant oxo',
+ } ),
+ ] ),
+ } )
+ )
+ );
} );
} );
- test( 'date', async ( { request } ) => {
- const result = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- order: 'asc',
- orderby: 'date',
- },
+ test.describe( 'orderby', () => {
+ // The orders endpoint `orderby` parameter uses WP_Query, so our tests won't
+ // include slug and title, since they are programmatically generated.
+ test( 'default', async ( { request } ) => {
+ // Default = date desc.
+ const result = await request.get( 'wp-json/wc/v3/orders' );
+ const resultJSON = await result.json();
+ expect( result.status() ).toEqual( 200 );
+
+ // Verify all dates are in descending order.
+ let lastDate = Date.now();
+ resultJSON.forEach( ( { date_created } ) => {
+ const created = Date.parse( date_created + '.000Z' );
+ expect( lastDate ).toBeGreaterThanOrEqual( created );
+ lastDate = created;
+ } );
} );
- const resultJSON = await result.json();
- expect( result.status() ).toEqual( 200 );
+ test( 'date', async ( { request } ) => {
+ const result = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ order: 'asc',
+ orderby: 'date',
+ },
+ } );
+ const resultJSON = await result.json();
- // Verify all dates are in ascending order.
- let lastDate = 0;
- resultJSON.forEach( ( { date_created } ) => {
- const created = Date.parse( date_created + '.000Z' );
- expect( created ).toBeGreaterThanOrEqual( lastDate );
- lastDate = created;
+ expect( result.status() ).toEqual( 200 );
+
+ // Verify all dates are in ascending order.
+ let lastDate = 0;
+ resultJSON.forEach( ( { date_created } ) => {
+ const created = Date.parse( date_created + '.000Z' );
+ expect( created ).toBeGreaterThanOrEqual( lastDate );
+ lastDate = created;
+ } );
+ } );
+
+ test( 'id', async ( { request } ) => {
+ const result1 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ order: 'asc',
+ orderby: 'id',
+ },
+ } );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+
+ // Verify all results are in ascending order.
+ let lastId = 0;
+ result1JSON.forEach( ( { id } ) => {
+ expect( id ).toBeGreaterThan( lastId );
+ lastId = id;
+ } );
+
+ const result2 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ order: 'desc',
+ orderby: 'id',
+ },
+ } );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+
+ // Verify all results are in descending order.
+ lastId = Number.MAX_SAFE_INTEGER;
+ result2JSON.forEach( ( { id } ) => {
+ expect( lastId ).toBeGreaterThan( id );
+ lastId = id;
+ } );
+ } );
+
+ test( 'include', async ( { request } ) => {
+ const includeIds = [
+ sampleData.precisionOrder.id,
+ sampleData.hierarchicalOrders.parent.id,
+ sampleData.guestOrderJSON.id,
+ ];
+
+ const result1 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ order: 'asc',
+ orderby: 'include',
+ include: includeIds.join( ',' ),
+ },
+ } );
+ const result1JSON = await result1.json();
+
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength( includeIds.length );
+
+ // Verify all results are in proper order.
+ result1JSON.forEach( ( { id }, idx ) => {
+ expect( id ).toBe( includeIds[ idx ] );
+ } );
+
+ const result2 = await request.get( 'wp-json/wc/v3/orders', {
+ params: {
+ order: 'desc',
+ orderby: 'include',
+ include: includeIds.join( ',' ),
+ },
+ } );
+ const result2JSON = await result2.json();
+
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toHaveLength( includeIds.length );
+
+ // Verify all results are in proper order.
+ result2JSON.forEach( ( { id }, idx ) => {
+ expect( id ).toBe( includeIds[ idx ] );
+ } );
} );
} );
-
- test( 'id', async ( { request } ) => {
- const result1 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- order: 'asc',
- orderby: 'id',
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
-
- // Verify all results are in ascending order.
- let lastId = 0;
- result1JSON.forEach( ( { id } ) => {
- expect( id ).toBeGreaterThan( lastId );
- lastId = id;
- } );
-
- const result2 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- order: 'desc',
- orderby: 'id',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
-
- // Verify all results are in descending order.
- lastId = Number.MAX_SAFE_INTEGER;
- result2JSON.forEach( ( { id } ) => {
- expect( lastId ).toBeGreaterThan( id );
- lastId = id;
- } );
- } );
-
- test( 'include', async ( { request } ) => {
- const includeIds = [
- sampleData.precisionOrder.id,
- sampleData.hierarchicalOrders.parent.id,
- sampleData.guestOrderJSON.id,
- ];
-
- const result1 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- order: 'asc',
- orderby: 'include',
- include: includeIds.join( ',' ),
- },
- } );
- const result1JSON = await result1.json();
-
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength( includeIds.length );
-
- // Verify all results are in proper order.
- result1JSON.forEach( ( { id }, idx ) => {
- expect( id ).toBe( includeIds[ idx ] );
- } );
-
- const result2 = await request.get( 'wp-json/wc/v3/orders', {
- params: {
- order: 'desc',
- orderby: 'include',
- include: includeIds.join( ',' ),
- },
- } );
- const result2JSON = await result2.json();
-
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toHaveLength( includeIds.length );
-
- // Verify all results are in proper order.
- result2JSON.forEach( ( { id }, idx ) => {
- expect( id ).toBe( includeIds[ idx ] );
- } );
- } );
- } );
-} );
+ }
+);
diff --git a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/payment-gateways/payment-gateways-crud.test.js b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/payment-gateways/payment-gateways-crud.test.js
index c4d021c65f5..a0cd439f3e4 100644
--- a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/payment-gateways/payment-gateways-crud.test.js
+++ b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/payment-gateways/payment-gateways-crud.test.js
@@ -1,170 +1,176 @@
const { test, expect } = require( '../../../fixtures/api-tests-fixtures' );
test.describe( 'Payment Gateways API tests', () => {
- test( 'can view all payment gateways', async ( { request } ) => {
- // call API to retrieve the payment gateways
- const response = await request.get( '/wp-json/wc/v3/payment_gateways' );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( Array.isArray( responseJSON ) ).toBe( true );
+ test(
+ 'can view all payment gateways',
+ { tag: [ '@skip-on-default-pressable', '@skip-on-default-wpcom' ] },
+ async ( { request } ) => {
+ // call API to retrieve the payment gateways
+ const response = await request.get(
+ '/wp-json/wc/v3/payment_gateways'
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( Array.isArray( responseJSON ) ).toBe( true );
- const localPickupKey =
- // eslint-disable-next-line playwright/no-conditional-in-test
- process.env.BASE_URL &&
- ! process.env.BASE_URL.includes( 'localhost' )
- ? 'pickup_location'
- : 'local_pickup';
- console.log( 'localPickupKey=', localPickupKey );
+ const localPickupKey =
+ // eslint-disable-next-line playwright/no-conditional-in-test
+ process.env.BASE_URL &&
+ ! process.env.BASE_URL.includes( 'localhost' )
+ ? 'pickup_location'
+ : 'local_pickup';
+ console.log( 'localPickupKey=', localPickupKey );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'bacs',
- title: 'Direct bank transfer',
- description:
- 'Make your payment directly into our bank account. Please use your Order ID as the payment reference. Your order will not be shipped until the funds have cleared in our account.',
- order: '',
- enabled: false,
- method_title: 'Direct bank transfer',
- method_description:
- 'Take payments in person via BACS. More commonly known as direct bank/wire transfer.',
- method_supports: [ 'products' ],
- settings: {
- title: {
- id: 'title',
- label: 'Title',
- description:
- 'This controls the title which the user sees during checkout.',
- type: 'safe_text',
- value: 'Direct bank transfer',
- default: 'Direct bank transfer',
- tip: 'This controls the title which the user sees during checkout.',
- placeholder: '',
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'bacs',
+ title: 'Direct bank transfer',
+ description:
+ 'Make your payment directly into our bank account. Please use your Order ID as the payment reference. Your order will not be shipped until the funds have cleared in our account.',
+ order: '',
+ enabled: false,
+ method_title: 'Direct bank transfer',
+ method_description:
+ 'Take payments in person via BACS. More commonly known as direct bank/wire transfer.',
+ method_supports: [ 'products' ],
+ settings: {
+ title: {
+ id: 'title',
+ label: 'Title',
+ description:
+ 'This controls the title which the user sees during checkout.',
+ type: 'safe_text',
+ value: 'Direct bank transfer',
+ default: 'Direct bank transfer',
+ tip: 'This controls the title which the user sees during checkout.',
+ placeholder: '',
+ },
+ instructions: {
+ id: 'instructions',
+ label: 'Instructions',
+ description:
+ 'Instructions that will be added to the thank you page and emails.',
+ type: 'textarea',
+ value: '',
+ default: '',
+ tip: 'Instructions that will be added to the thank you page and emails.',
+ placeholder: '',
+ },
},
- instructions: {
- id: 'instructions',
- label: 'Instructions',
- description:
- 'Instructions that will be added to the thank you page and emails.',
- type: 'textarea',
- value: '',
- default: '',
- tip: 'Instructions that will be added to the thank you page and emails.',
- placeholder: '',
- },
- },
- } ),
+ } ),
- expect.objectContaining( {
- id: 'cheque',
- title: 'Check payments',
- description:
- 'Please send a check to Store Name, Store Street, Store Town, Store State / County, Store Postcode.',
- order: '',
- enabled: false,
- method_title: 'Check payments',
- method_description:
- 'Take payments in person via checks. This offline gateway can also be useful to test purchases.',
- method_supports: [ 'products' ],
- settings: {
- title: {
- id: 'title',
- label: 'Title',
- description:
- 'This controls the title which the user sees during checkout.',
- type: 'safe_text',
- value: 'Check payments',
- default: 'Check payments',
- tip: 'This controls the title which the user sees during checkout.',
- placeholder: '',
+ expect.objectContaining( {
+ id: 'cheque',
+ title: 'Check payments',
+ description:
+ 'Please send a check to Store Name, Store Street, Store Town, Store State / County, Store Postcode.',
+ order: '',
+ enabled: false,
+ method_title: 'Check payments',
+ method_description:
+ 'Take payments in person via checks. This offline gateway can also be useful to test purchases.',
+ method_supports: [ 'products' ],
+ settings: {
+ title: {
+ id: 'title',
+ label: 'Title',
+ description:
+ 'This controls the title which the user sees during checkout.',
+ type: 'safe_text',
+ value: 'Check payments',
+ default: 'Check payments',
+ tip: 'This controls the title which the user sees during checkout.',
+ placeholder: '',
+ },
+ instructions: {
+ id: 'instructions',
+ label: 'Instructions',
+ description:
+ 'Instructions that will be added to the thank you page and emails.',
+ type: 'textarea',
+ value: '',
+ default: '',
+ tip: 'Instructions that will be added to the thank you page and emails.',
+ placeholder: '',
+ },
},
- instructions: {
- id: 'instructions',
- label: 'Instructions',
- description:
- 'Instructions that will be added to the thank you page and emails.',
- type: 'textarea',
- value: '',
- default: '',
- tip: 'Instructions that will be added to the thank you page and emails.',
- placeholder: '',
- },
- },
- } ),
+ } ),
- expect.objectContaining( {
- id: 'cod',
- title: 'Cash on delivery',
- description: 'Pay with cash upon delivery.',
- order: '',
- enabled: false,
- method_title: 'Cash on delivery',
- method_description:
- 'Have your customers pay with cash (or by other means) upon delivery.',
- method_supports: [ 'products' ],
- settings: {
- title: {
- id: 'title',
- label: 'Title',
- description:
- 'Payment method description that the customer will see on your checkout.',
- type: 'safe_text',
- value: 'Cash on delivery',
- default: 'Cash on delivery',
- tip: 'Payment method description that the customer will see on your checkout.',
- placeholder: '',
- },
- instructions: {
- id: 'instructions',
- label: 'Instructions',
- description:
- 'Instructions that will be added to the thank you page.',
- type: 'textarea',
- value: 'Pay with cash upon delivery.',
- default: 'Pay with cash upon delivery.',
- tip: 'Instructions that will be added to the thank you page.',
- placeholder: '',
- },
- enable_for_methods: {
- id: 'enable_for_methods',
- label: 'Enable for shipping methods',
- description:
- 'If COD is only available for certain methods, set it up here. Leave blank to enable for all methods.',
- type: 'multiselect',
- value: '',
- default: '',
- tip: 'If COD is only available for certain methods, set it up here. Leave blank to enable for all methods.',
- placeholder: '',
- options: expect.objectContaining( {
- 'Flat rate': {
- flat_rate:
- 'Any "Flat rate" method',
- },
- 'Free shipping': {
- free_shipping:
- 'Any "Free shipping" method',
- },
- 'Local pickup': expect.objectContaining( {
- [ localPickupKey ]:
- 'Any "Local pickup" method',
+ expect.objectContaining( {
+ id: 'cod',
+ title: 'Cash on delivery',
+ description: 'Pay with cash upon delivery.',
+ order: '',
+ enabled: false,
+ method_title: 'Cash on delivery',
+ method_description:
+ 'Have your customers pay with cash (or by other means) upon delivery.',
+ method_supports: [ 'products' ],
+ settings: {
+ title: {
+ id: 'title',
+ label: 'Title',
+ description:
+ 'Payment method description that the customer will see on your checkout.',
+ type: 'safe_text',
+ value: 'Cash on delivery',
+ default: 'Cash on delivery',
+ tip: 'Payment method description that the customer will see on your checkout.',
+ placeholder: '',
+ },
+ instructions: {
+ id: 'instructions',
+ label: 'Instructions',
+ description:
+ 'Instructions that will be added to the thank you page.',
+ type: 'textarea',
+ value: 'Pay with cash upon delivery.',
+ default: 'Pay with cash upon delivery.',
+ tip: 'Instructions that will be added to the thank you page.',
+ placeholder: '',
+ },
+ enable_for_methods: {
+ id: 'enable_for_methods',
+ label: 'Enable for shipping methods',
+ description:
+ 'If COD is only available for certain methods, set it up here. Leave blank to enable for all methods.',
+ type: 'multiselect',
+ value: '',
+ default: '',
+ tip: 'If COD is only available for certain methods, set it up here. Leave blank to enable for all methods.',
+ placeholder: '',
+ options: expect.objectContaining( {
+ 'Flat rate': {
+ flat_rate:
+ 'Any "Flat rate" method',
+ },
+ 'Free shipping': {
+ free_shipping:
+ 'Any "Free shipping" method',
+ },
+ 'Local pickup': expect.objectContaining( {
+ [ localPickupKey ]:
+ 'Any "Local pickup" method',
+ } ),
} ),
- } ),
+ },
+ enable_for_virtual: {
+ id: 'enable_for_virtual',
+ label: 'Accept COD if the order is virtual',
+ description: '',
+ type: 'checkbox',
+ value: 'yes',
+ default: 'yes',
+ tip: '',
+ placeholder: '',
+ },
},
- enable_for_virtual: {
- id: 'enable_for_virtual',
- label: 'Accept COD if the order is virtual',
- description: '',
- type: 'checkbox',
- value: 'yes',
- default: 'yes',
- tip: '',
- placeholder: '',
- },
- },
- } ),
- ] )
- );
- } );
+ } ),
+ ] )
+ );
+ }
+ );
test( 'can view a payment gateway', async ( { request } ) => {
// call API to retrieve a single payment gateway
diff --git a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/products/product-list.test.js b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/products/product-list.test.js
index 03f51112b37..d9faf15633c 100644
--- a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/products/product-list.test.js
+++ b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/products/product-list.test.js
@@ -2230,1077 +2230,1170 @@ test.describe( 'Products API tests: List All Products', () => {
await deleteSampleData( sampleData );
}, 10000 );
- test.describe( 'List all products', () => {
- test( 'defaults', async ( { request } ) => {
- const result = await request.get( 'wp-json/wc/v3/products', {
- params: {
- search: 'xxx',
- },
+ test.describe(
+ 'List all products',
+ { tag: [ '@skip-on-default-pressable', '@skip-on-default-wpcom' ] },
+ () => {
+ test( 'defaults', async ( { request } ) => {
+ const result = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ search: 'xxx',
+ },
+ } );
+
+ expect( result.status() ).toEqual( 200 );
+ expect( result.headers()[ 'x-wp-total' ] ).toEqual(
+ PRODUCTS_COUNT.toString()
+ );
+ expect( result.headers()[ 'x-wp-totalpages' ] ).toEqual( '2' );
} );
- expect( result.status() ).toEqual( 200 );
- expect( result.headers()[ 'x-wp-total' ] ).toEqual(
- PRODUCTS_COUNT.toString()
- );
- expect( result.headers()[ 'x-wp-totalpages' ] ).toEqual( '2' );
- } );
+ test( 'pagination', async ( { request } ) => {
+ const pageSize = 6;
+ const page1 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ per_page: pageSize,
+ search: 'xxx',
+ },
+ } );
+ const page1JSON = await page1.json();
+ const page2 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ per_page: pageSize,
+ page: 2,
+ search: 'xxx',
+ },
+ } );
+ const page2JSON = await page2.json();
+ expect( page1.status() ).toEqual( 200 );
+ expect( page2.status() ).toEqual( 200 );
- test( 'pagination', async ( { request } ) => {
- const pageSize = 6;
- const page1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- per_page: pageSize,
- search: 'xxx',
- },
- } );
- const page1JSON = await page1.json();
- const page2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- per_page: pageSize,
- page: 2,
- search: 'xxx',
- },
- } );
- const page2JSON = await page2.json();
- expect( page1.status() ).toEqual( 200 );
- expect( page2.status() ).toEqual( 200 );
+ // Verify total page count.
+ expect( page1.headers()[ 'x-wp-total' ] ).toEqual(
+ PRODUCTS_COUNT.toString()
+ );
+ expect( page1.headers()[ 'x-wp-totalpages' ] ).toEqual( '4' );
- // Verify total page count.
- expect( page1.headers()[ 'x-wp-total' ] ).toEqual(
- PRODUCTS_COUNT.toString()
- );
- expect( page1.headers()[ 'x-wp-totalpages' ] ).toEqual( '4' );
+ // Verify we get pageSize'd arrays.
+ expect( Array.isArray( page1JSON ) ).toBe( true );
+ expect( Array.isArray( page2JSON ) ).toBe( true );
+ expect( page1JSON ).toHaveLength( pageSize );
+ expect( page2JSON ).toHaveLength( pageSize );
- // Verify we get pageSize'd arrays.
- expect( Array.isArray( page1JSON ) ).toBe( true );
- expect( Array.isArray( page2JSON ) ).toBe( true );
- expect( page1JSON ).toHaveLength( pageSize );
- expect( page2JSON ).toHaveLength( pageSize );
+ // Ensure all of the product IDs are unique (no page overlap).
+ const allProductIds = page1JSON
+ .concat( page2JSON )
+ .reduce( ( acc, product ) => {
+ acc[ product.id ] = 1;
+ return acc;
+ }, {} );
+ expect( Object.keys( allProductIds ) ).toHaveLength(
+ pageSize * 2
+ );
- // Ensure all of the product IDs are unique (no page overlap).
- const allProductIds = page1JSON
- .concat( page2JSON )
- .reduce( ( acc, product ) => {
- acc[ product.id ] = 1;
- return acc;
- }, {} );
- expect( Object.keys( allProductIds ) ).toHaveLength( pageSize * 2 );
-
- // Verify that offset takes precedent over page number.
- const page2Offset = await request.get( 'wp-json/wc/v3/products', {
- params: {
- per_page: pageSize,
- page: 2,
- offset: pageSize + 1,
- search: 'xxx',
- },
- } );
- const page2OffsetJSON = await page2Offset.json();
- // The offset pushes the result set 1 product past the start of page 2.
- expect( page2OffsetJSON ).toEqual(
- expect.not.arrayContaining( [
- expect.objectContaining( {
- id: page2JSON[ 0 ].id,
- } ),
- ] )
- );
- expect( page2OffsetJSON[ 0 ].id ).toEqual( page2JSON[ 1 ].id );
-
- // Verify the last page only has 2 products as we expect.
- const lastPage = await request.get( 'wp-json/wc/v3/products', {
- params: {
- per_page: pageSize,
- page: 4,
- search: 'xxx',
- },
- } );
- const lastPageJSON = await lastPage.json();
- expect( Array.isArray( lastPageJSON ) ).toBe( true );
- expect( lastPageJSON ).toHaveLength( 2 );
-
- // Verify a page outside the total page count is empty.
- const page6 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- per_page: pageSize,
- page: 6,
- search: 'xxx',
- },
- } );
- const page6JSON = await page6.json();
- expect( Array.isArray( page6JSON ) ).toBe( true );
- expect( page6JSON ).toHaveLength( 0 );
- } );
-
- test( 'search', async ( { request } ) => {
- // Match in the short description.
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- search: 'external',
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON.length ).toBeGreaterThanOrEqual( 1 );
- expect( result1JSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- name: 'WordPress Pennant xxx',
- } ),
- ] )
- );
-
- // Match in the product name.
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- search: 'pocket xxx',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toHaveLength( 1 );
- expect( result2JSON[ 0 ].name ).toBe( 'Hoodie with Pocket xxx' );
- } );
-
- test( 'inclusion / exclusion', async ( { request } ) => {
- const allProducts = await request.get( 'wp-json/wc/v3/products', {
- params: {
- per_page: 20,
- search: 'xxx',
- },
- } );
- const allProductsJSON = await allProducts.json();
- expect( allProducts.status() ).toEqual( 200 );
- const allProductIds = allProductsJSON.map(
- ( product ) => product.id
- );
- expect( allProductIds ).toHaveLength( PRODUCTS_COUNT );
-
- const productsToFilter = [
- allProductIds[ 2 ],
- allProductIds[ 4 ],
- allProductIds[ 7 ],
- allProductIds[ 13 ],
- ];
-
- const included = await request.get( 'wp-json/wc/v3/products', {
- params: {
- per_page: 20,
- include: productsToFilter.join( ',' ),
- },
- } );
- const includedJSON = await included.json();
- expect( included.status() ).toEqual( 200 );
- expect( includedJSON ).toHaveLength( productsToFilter.length );
- expect( includedJSON ).toEqual(
- expect.arrayContaining(
- productsToFilter.map( ( id ) =>
+ // Verify that offset takes precedent over page number.
+ const page2Offset = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ per_page: pageSize,
+ page: 2,
+ offset: pageSize + 1,
+ search: 'xxx',
+ },
+ }
+ );
+ const page2OffsetJSON = await page2Offset.json();
+ // The offset pushes the result set 1 product past the start of page 2.
+ expect( page2OffsetJSON ).toEqual(
+ expect.not.arrayContaining( [
expect.objectContaining( {
- id,
- } )
- )
- )
- );
+ id: page2JSON[ 0 ].id,
+ } ),
+ ] )
+ );
+ expect( page2OffsetJSON[ 0 ].id ).toEqual( page2JSON[ 1 ].id );
- const excluded = await request.get( 'wp-json/wc/v3/products', {
- params: {
- per_page: 20,
- exclude: productsToFilter.join( ',' ),
- },
+ // Verify the last page only has 2 products as we expect.
+ const lastPage = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ per_page: pageSize,
+ page: 4,
+ search: 'xxx',
+ },
+ } );
+ const lastPageJSON = await lastPage.json();
+ expect( Array.isArray( lastPageJSON ) ).toBe( true );
+ expect( lastPageJSON ).toHaveLength( 2 );
+
+ // Verify a page outside the total page count is empty.
+ const page6 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ per_page: pageSize,
+ page: 6,
+ search: 'xxx',
+ },
+ } );
+ const page6JSON = await page6.json();
+ expect( Array.isArray( page6JSON ) ).toBe( true );
+ expect( page6JSON ).toHaveLength( 0 );
} );
- const excludedJSON = await excluded.json();
- expect( excluded.status() ).toEqual( 200 );
- expect( excludedJSON.length ).toBeGreaterThanOrEqual(
- Number( PRODUCTS_COUNT - productsToFilter.length )
- );
- expect( excludedJSON ).toEqual(
- expect.not.arrayContaining(
- productsToFilter.map( ( id ) =>
+
+ test( 'search', async ( { request } ) => {
+ // Match in the short description.
+ const result1 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ search: 'external',
+ },
+ } );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON.length ).toBeGreaterThanOrEqual( 1 );
+ expect( result1JSON ).toEqual(
+ expect.arrayContaining( [
expect.objectContaining( {
- id,
- } )
+ name: 'WordPress Pennant xxx',
+ } ),
+ ] )
+ );
+
+ // Match in the product name.
+ const result2 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ search: 'pocket xxx',
+ },
+ } );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toHaveLength( 1 );
+ expect( result2JSON[ 0 ].name ).toBe(
+ 'Hoodie with Pocket xxx'
+ );
+ } );
+
+ test( 'inclusion / exclusion', async ( { request } ) => {
+ const allProducts = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ per_page: 20,
+ search: 'xxx',
+ },
+ }
+ );
+ const allProductsJSON = await allProducts.json();
+ expect( allProducts.status() ).toEqual( 200 );
+ const allProductIds = allProductsJSON.map(
+ ( product ) => product.id
+ );
+ expect( allProductIds ).toHaveLength( PRODUCTS_COUNT );
+
+ const productsToFilter = [
+ allProductIds[ 2 ],
+ allProductIds[ 4 ],
+ allProductIds[ 7 ],
+ allProductIds[ 13 ],
+ ];
+
+ const included = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ per_page: 20,
+ include: productsToFilter.join( ',' ),
+ },
+ } );
+ const includedJSON = await included.json();
+ expect( included.status() ).toEqual( 200 );
+ expect( includedJSON ).toHaveLength( productsToFilter.length );
+ expect( includedJSON ).toEqual(
+ expect.arrayContaining(
+ productsToFilter.map( ( id ) =>
+ expect.objectContaining( {
+ id,
+ } )
+ )
)
- )
+ );
+
+ const excluded = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ per_page: 20,
+ exclude: productsToFilter.join( ',' ),
+ },
+ } );
+ const excludedJSON = await excluded.json();
+ expect( excluded.status() ).toEqual( 200 );
+ expect( excludedJSON.length ).toBeGreaterThanOrEqual(
+ Number( PRODUCTS_COUNT - productsToFilter.length )
+ );
+ expect( excludedJSON ).toEqual(
+ expect.not.arrayContaining(
+ productsToFilter.map( ( id ) =>
+ expect.objectContaining( {
+ id,
+ } )
+ )
+ )
+ );
+ } );
+
+ test( 'slug', async ( { request } ) => {
+ // Match by slug.
+ const result1 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ slug: 't-shirt-with-logo-xxx',
+ },
+ } );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength( 1 );
+ expect( result1JSON[ 0 ].slug ).toBe( 't-shirt-with-logo-xxx' );
+
+ // No matches
+ const result2 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ slug: 'no-product-with-this-slug',
+ },
+ } );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toHaveLength( 0 );
+ } );
+
+ test( 'sku', async ( { request } ) => {
+ // Match by SKU.
+ const result1 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ sku: 'woo-sunglasses-product',
+ },
+ } );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength( 1 );
+ expect( result1JSON[ 0 ].sku ).toBe( 'woo-sunglasses-product' );
+
+ // No matches
+ const result2 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ sku: 'no-product-with-this-sku',
+ },
+ } );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toHaveLength( 0 );
+ } );
+
+ test( 'type', async ( { request } ) => {
+ const result1 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ type: 'simple',
+ search: 'xxx',
+ },
+ } );
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1.headers()[ 'x-wp-total' ] ).toEqual( '16' );
+
+ const result2 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ type: 'external',
+ search: 'xxx',
+ },
+ } );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toHaveLength( 1 );
+ expect( result2JSON[ 0 ].name ).toBe( 'WordPress Pennant xxx' );
+
+ const result3 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ type: 'variable',
+ search: 'xxx',
+ },
+ } );
+ const result3JSON = await result3.json();
+ expect( result3.status() ).toEqual( 200 );
+ expect( result3JSON ).toHaveLength( 2 );
+
+ const result4 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ type: 'grouped',
+ search: 'xxx',
+ },
+ } );
+ const result4JSON = await result4.json();
+ expect( result4.status() ).toEqual( 200 );
+ expect( result4JSON ).toHaveLength( 1 );
+ expect( result4JSON[ 0 ].name ).toBe( 'Logo Collection xxx' );
+ } );
+
+ test( 'featured', async ( { request } ) => {
+ const featured = [
+ expect.objectContaining( {
+ name: 'Hoodie with Zipper xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Hoodie with Pocket xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Sunglasses xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Cap xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'V-Neck T-Shirt xxx',
+ } ),
+ ];
+
+ const result1 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ featured: true,
+ search: 'xxx',
+ },
+ } );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength( featured.length );
+ expect( result1JSON ).toEqual(
+ expect.arrayContaining( featured )
+ );
+
+ const result2 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ featured: false,
+ search: 'xxx',
+ },
+ } );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toEqual(
+ expect.not.arrayContaining( featured )
+ );
+ } );
+
+ test(
+ 'categories',
+ { tag: '@skip-on-default-wpcom' },
+ async ( { request } ) => {
+ const accessory = [
+ expect.objectContaining( {
+ name: 'Beanie xxx',
+ } ),
+ ];
+ const hoodies = [
+ expect.objectContaining( {
+ name: 'Hoodie with Zipper xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Hoodie with Pocket xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Hoodie with Logo xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Hoodie xxx',
+ } ),
+ ];
+
+ // Verify that subcategories are included.
+ const result1 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ per_page: 20,
+ category: sampleData.categories.clothingJSON.id,
+ },
+ }
+ );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toEqual(
+ expect.arrayContaining( accessory )
+ );
+ expect( result1JSON ).toEqual(
+ expect.arrayContaining( hoodies )
+ );
+
+ // Verify sibling categories are not.
+ const result2 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ category: sampleData.categories.hoodiesJSON.id,
+ },
+ }
+ );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toEqual(
+ expect.not.arrayContaining( accessory )
+ );
+ expect( result2JSON ).toEqual(
+ expect.arrayContaining( hoodies )
+ );
+ }
);
- } );
- test( 'slug', async ( { request } ) => {
- // Match by slug.
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- slug: 't-shirt-with-logo-xxx',
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength( 1 );
- expect( result1JSON[ 0 ].slug ).toBe( 't-shirt-with-logo-xxx' );
-
- // No matches
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- slug: 'no-product-with-this-slug',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toHaveLength( 0 );
- } );
-
- test( 'sku', async ( { request } ) => {
- // Match by SKU.
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- sku: 'woo-sunglasses-product',
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength( 1 );
- expect( result1JSON[ 0 ].sku ).toBe( 'woo-sunglasses-product' );
-
- // No matches
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- sku: 'no-product-with-this-sku',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toHaveLength( 0 );
- } );
-
- test( 'type', async ( { request } ) => {
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- type: 'simple',
- search: 'xxx',
- },
- } );
- expect( result1.status() ).toEqual( 200 );
- expect( result1.headers()[ 'x-wp-total' ] ).toEqual( '16' );
-
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- type: 'external',
- search: 'xxx',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toHaveLength( 1 );
- expect( result2JSON[ 0 ].name ).toBe( 'WordPress Pennant xxx' );
-
- const result3 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- type: 'variable',
- search: 'xxx',
- },
- } );
- const result3JSON = await result3.json();
- expect( result3.status() ).toEqual( 200 );
- expect( result3JSON ).toHaveLength( 2 );
-
- const result4 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- type: 'grouped',
- search: 'xxx',
- },
- } );
- const result4JSON = await result4.json();
- expect( result4.status() ).toEqual( 200 );
- expect( result4JSON ).toHaveLength( 1 );
- expect( result4JSON[ 0 ].name ).toBe( 'Logo Collection xxx' );
- } );
-
- test( 'featured', async ( { request } ) => {
- const featured = [
- expect.objectContaining( {
- name: 'Hoodie with Zipper xxx',
- } ),
- expect.objectContaining( {
- name: 'Hoodie with Pocket xxx',
- } ),
- expect.objectContaining( {
- name: 'Sunglasses xxx',
- } ),
- expect.objectContaining( {
- name: 'Cap xxx',
- } ),
- expect.objectContaining( {
- name: 'V-Neck T-Shirt xxx',
- } ),
- ];
-
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- featured: true,
- search: 'xxx',
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength( featured.length );
- expect( result1JSON ).toEqual( expect.arrayContaining( featured ) );
-
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- featured: false,
- search: 'xxx',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toEqual(
- expect.not.arrayContaining( featured )
- );
- } );
-
- test( 'categories', async ( { request } ) => {
- const accessory = [
- expect.objectContaining( {
- name: 'Beanie xxx',
- } ),
- ];
- const hoodies = [
- expect.objectContaining( {
- name: 'Hoodie with Zipper xxx',
- } ),
- expect.objectContaining( {
- name: 'Hoodie with Pocket xxx',
- } ),
- expect.objectContaining( {
- name: 'Hoodie with Logo xxx',
- } ),
- expect.objectContaining( {
- name: 'Hoodie xxx',
- } ),
- ];
-
- // Verify that subcategories are included.
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- per_page: 20,
- category: sampleData.categories.clothingJSON.id,
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toEqual(
- expect.arrayContaining( accessory )
- );
- expect( result1JSON ).toEqual( expect.arrayContaining( hoodies ) );
-
- // Verify sibling categories are not.
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- category: sampleData.categories.hoodiesJSON.id,
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toEqual(
- expect.not.arrayContaining( accessory )
- );
- expect( result2JSON ).toEqual( expect.arrayContaining( hoodies ) );
- } );
-
- test( 'on sale', async ( { request } ) => {
- const onSale = [
- expect.objectContaining( {
- name: 'Beanie with Logo xxx',
- } ),
- expect.objectContaining( {
- name: 'Hoodie with Pocket xxx',
- } ),
- expect.objectContaining( {
- name: 'Single xxx',
- } ),
- expect.objectContaining( {
- name: 'Cap xxx',
- } ),
- expect.objectContaining( {
- name: 'Belt xxx',
- } ),
- expect.objectContaining( {
- name: 'Beanie xxx',
- } ),
- expect.objectContaining( {
- name: 'Hoodie xxx',
- } ),
- ];
-
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- on_sale: true,
- search: 'xxx',
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength( onSale.length );
- expect( result1JSON ).toEqual( expect.arrayContaining( onSale ) );
-
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- on_sale: false,
- search: 'xxx',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toEqual(
- expect.not.arrayContaining( onSale )
- );
- } );
-
- test( 'price', async ( { request } ) => {
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- min_price: 21,
- max_price: 28,
- search: 'xxx',
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength( 1 );
- expect( result1JSON[ 0 ].name ).toBe( 'Long Sleeve Tee xxx' );
- expect( result1JSON[ 0 ].price ).toBe( '25' );
-
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- max_price: 5,
- search: 'xxx',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toHaveLength( 1 );
- expect( result2JSON[ 0 ].name ).toBe( 'Single xxx' );
- expect( result2JSON[ 0 ].price ).toBe( '2' );
-
- const result3 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- min_price: 5,
- order: 'asc',
- orderby: 'price',
- search: 'xxx',
- },
- } );
- const result3JSON = await result3.json();
- expect( result3.status() ).toEqual( 200 );
- expect( result3JSON ).toEqual(
- expect.not.arrayContaining( [
+ test( 'on sale', async ( { request } ) => {
+ const onSale = [
+ expect.objectContaining( {
+ name: 'Beanie with Logo xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Hoodie with Pocket xxx',
+ } ),
expect.objectContaining( {
name: 'Single xxx',
} ),
- ] )
- );
- } );
+ expect.objectContaining( {
+ name: 'Cap xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Belt xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Beanie xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Hoodie xxx',
+ } ),
+ ];
- test( 'before / after', async ( { request } ) => {
- const before = [
- expect.objectContaining( {
- name: 'Album xxx',
- } ),
- expect.objectContaining( {
- name: 'Single xxx',
- } ),
- expect.objectContaining( {
- name: 'T-Shirt with Logo xxx',
- } ),
- expect.objectContaining( {
- name: 'Beanie with Logo xxx',
- } ),
- ];
- const after = [
- expect.objectContaining( {
- name: 'Hoodie xxx',
- } ),
- expect.objectContaining( {
- name: 'V-Neck T-Shirt xxx',
- } ),
- expect.objectContaining( {
- name: 'Parent Product xxx',
- } ),
- expect.objectContaining( {
- name: 'Child Product xxx',
- } ),
- ];
+ const result1 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ on_sale: true,
+ search: 'xxx',
+ },
+ } );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength( onSale.length );
+ expect( result1JSON ).toEqual(
+ expect.arrayContaining( onSale )
+ );
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- before: '2021-09-05T15:50:19',
- search: 'xxx',
- },
+ const result2 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ on_sale: false,
+ search: 'xxx',
+ },
+ } );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toEqual(
+ expect.not.arrayContaining( onSale )
+ );
} );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength( before.length );
- expect( result1JSON ).toEqual( expect.arrayContaining( before ) );
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- after: '2021-09-18T15:50:18',
- search: 'xxx',
- },
+ test( 'price', async ( { request } ) => {
+ const result1 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ min_price: 21,
+ max_price: 28,
+ search: 'xxx',
+ },
+ } );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength( 1 );
+ expect( result1JSON[ 0 ].name ).toBe( 'Long Sleeve Tee xxx' );
+ expect( result1JSON[ 0 ].price ).toBe( '25' );
+
+ const result2 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ max_price: 5,
+ search: 'xxx',
+ },
+ } );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toHaveLength( 1 );
+ expect( result2JSON[ 0 ].name ).toBe( 'Single xxx' );
+ expect( result2JSON[ 0 ].price ).toBe( '2' );
+
+ const result3 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ min_price: 5,
+ order: 'asc',
+ orderby: 'price',
+ search: 'xxx',
+ },
+ } );
+ const result3JSON = await result3.json();
+ expect( result3.status() ).toEqual( 200 );
+ expect( result3JSON ).toEqual(
+ expect.not.arrayContaining( [
+ expect.objectContaining( {
+ name: 'Single xxx',
+ } ),
+ ] )
+ );
} );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toEqual(
- expect.not.arrayContaining( before )
- );
- expect( result2JSON ).toHaveLength( after.length );
- expect( result2JSON ).toEqual( expect.arrayContaining( after ) );
- } );
- test( 'attributes', async ( { request } ) => {
- const red = sampleData.attributes.colors.find(
- ( term ) => term.name === 'Red'
- );
-
- const redProducts = [
- expect.objectContaining( {
- name: 'V-Neck T-Shirt xxx',
- } ),
- expect.objectContaining( {
- name: 'Hoodie xxx',
- } ),
- expect.objectContaining( {
- name: 'Beanie xxx',
- } ),
- expect.objectContaining( {
- name: 'Beanie with Logo xxx',
- } ),
- ];
-
- const result = await request.get( 'wp-json/wc/v3/products', {
- params: {
- attribute: 'pa_colorxxx',
- attribute_term: red.id,
- },
- } );
- const resultJSON = await result.json();
-
- expect( result.status() ).toEqual( 200 );
- expect( resultJSON ).toHaveLength( redProducts.length );
- expect( resultJSON ).toEqual(
- expect.arrayContaining( redProducts )
- );
- } );
-
- test( 'status', async ( { request } ) => {
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- status: 'pending',
- search: 'xxx',
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength( 1 );
- expect( result1JSON[ 0 ].name ).toBe( 'Polo xxx' );
-
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- status: 'draft',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toHaveLength( 0 );
- } );
-
- test( 'shipping class', async ( { request } ) => {
- const result = await request.get( 'wp-json/wc/v3/products', {
- params: {
- shipping_class: sampleData.shippingClasses.freightJSON.id,
- },
- } );
- const resultJSON = await result.json();
- expect( result.status() ).toEqual( 200 );
- expect( resultJSON ).toHaveLength( 1 );
- expect( resultJSON[ 0 ].name ).toBe( 'Long Sleeve Tee xxx' );
- } );
-
- test( 'tax class', async ( { request } ) => {
- const result = await request.get( 'wp-json/wc/v3/products', {
- params: {
- tax_class: 'reduced-rate',
- search: 'xxx',
- },
- } );
- const resultJSON = await result.json();
- expect( result.status() ).toEqual( 200 );
- expect( resultJSON ).toHaveLength( 1 );
- expect( resultJSON[ 0 ].name ).toBe( 'Sunglasses xxx' );
- } );
-
- test( 'stock status', async ( { request } ) => {
- const result = await request.get( 'wp-json/wc/v3/products', {
- params: {
- stock_status: 'onbackorder',
- search: 'xxx',
- },
- } );
- const resultJSON = await result.json();
- expect( result.status() ).toEqual( 200 );
- expect( resultJSON ).toHaveLength( 1 );
- expect( resultJSON[ 0 ].name ).toBe( 'T-Shirt xxx' );
- } );
-
- test( 'tags', async ( { request } ) => {
- const coolProducts = [
- expect.objectContaining( {
- name: 'Sunglasses xxx',
- } ),
- expect.objectContaining( {
- name: 'Hoodie with Pocket xxx',
- } ),
- expect.objectContaining( {
- name: 'Beanie xxx',
- } ),
- ];
-
- const result = await request.get( 'wp-json/wc/v3/products', {
- params: {
- tag: sampleData.tags.coolJSON.id,
- },
- } );
- const resultJSON = await result.json();
-
- expect( result.status() ).toEqual( 200 );
- expect( resultJSON ).toHaveLength( coolProducts.length );
- expect( resultJSON ).toEqual(
- expect.arrayContaining( coolProducts )
- );
- } );
-
- test( 'parent', async ( { request } ) => {
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- parent: sampleData.hierarchicalProducts.parentJSON.id,
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength( 1 );
- expect( result1JSON[ 0 ].name ).toBe( 'Child Product xxx' );
-
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- parent_exclude:
- sampleData.hierarchicalProducts.parentJSON.id,
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toEqual(
- expect.not.arrayContaining( [
+ test( 'before / after', async ( { request } ) => {
+ const before = [
+ expect.objectContaining( {
+ name: 'Album xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Single xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'T-Shirt with Logo xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Beanie with Logo xxx',
+ } ),
+ ];
+ const after = [
+ expect.objectContaining( {
+ name: 'Hoodie xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'V-Neck T-Shirt xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Parent Product xxx',
+ } ),
expect.objectContaining( {
name: 'Child Product xxx',
} ),
- ] )
- );
- } );
-
- test.describe( 'orderby', () => {
- const productNamesAsc = [
- 'Album xxx',
- 'Beanie with Logo xxx',
- 'Beanie xxx',
- 'Belt xxx',
- 'Cap xxx',
- 'Child Product xxx',
- 'Hoodie with Logo xxx',
- 'Hoodie with Pocket xxx',
- 'Hoodie with Zipper xxx',
- 'Hoodie xxx',
- 'Logo Collection xxx',
- 'Long Sleeve Tee xxx',
- 'Parent Product xxx',
- 'Polo xxx',
- 'Single xxx',
- 'Sunglasses xxx',
- 'T-Shirt with Logo xxx',
- 'T-Shirt xxx',
- 'V-Neck T-Shirt xxx',
- 'WordPress Pennant xxx',
- ];
- const productNamesDesc = [ ...productNamesAsc ].reverse();
- const productNamesByRatingAsc = [
- 'Sunglasses xxx',
- 'Cap xxx',
- 'T-Shirt xxx',
- ];
- const productNamesByRatingDesc = [
- ...productNamesByRatingAsc,
- ].reverse();
- const productNamesByPopularityDesc = [
- 'Beanie with Logo xxx',
- 'Single xxx',
- 'T-Shirt xxx',
- ];
- const productNamesByPopularityAsc = [
- ...productNamesByPopularityDesc,
- ].reverse();
-
- test( 'default', async ( { request } ) => {
- // Default = date desc.
- const result = await request.get( 'wp-json/wc/v3/products', {
- params: {
- search: 'xxx',
- },
- } );
- const resultJSON = await result.json();
- expect( result.status() ).toEqual( 200 );
-
- // Verify all dates are in descending order.
- let lastDate = Date.now();
- resultJSON.forEach( ( { date_created_gmt } ) => {
- const created = Date.parse( date_created_gmt + '.000Z' );
- expect( lastDate ).toBeGreaterThan( created );
- lastDate = created;
- } );
- } );
-
- test( 'date', async ( { request } ) => {
- const result = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'asc',
- orderby: 'date',
- search: 'xxx',
- },
- } );
- const resultJSON = await result.json();
- expect( result.status() ).toEqual( 200 );
-
- // Verify all dates are in ascending order.
- let lastDate = 0;
- resultJSON.forEach( ( { date_created_gmt } ) => {
- const created = Date.parse( date_created_gmt + '.000Z' );
- expect( created ).toBeGreaterThan( lastDate );
- lastDate = created;
- } );
- } );
-
- test( 'id', async ( { request } ) => {
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'asc',
- orderby: 'id',
- search: 'xxx',
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
-
- // Verify all results are in ascending order.
- let lastId = 0;
- result1JSON.forEach( ( { id } ) => {
- expect( id ).toBeGreaterThan( lastId );
- lastId = id;
- } );
-
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'desc',
- orderby: 'id',
- search: 'xxx',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
-
- // Verify all results are in descending order.
- lastId = Number.MAX_SAFE_INTEGER;
- result2JSON.forEach( ( { id } ) => {
- expect( lastId ).toBeGreaterThan( id );
- lastId = id;
- } );
- } );
-
- test( 'title', async ( { request } ) => {
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'asc',
- orderby: 'title',
- per_page: productNamesAsc.length,
- search: 'xxx',
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
-
- // Verify all results are in ascending order.
- result1JSON.forEach( ( { name }, idx ) => {
- expect( name ).toBe( productNamesAsc[ idx ] );
- } );
-
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'desc',
- orderby: 'title',
- per_page: productNamesDesc.length,
- search: 'xxx',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
-
- // Verify all results are in descending order.
- result2JSON.forEach( ( { name }, idx ) => {
- expect( name ).toBe( productNamesDesc[ idx ] );
- } );
- } );
-
- test( 'slug orderby', async ( { request } ) => {
- const productNamesBySlugAsc = [
- 'Polo xxx', // The Polo isn't published so it has an empty slug.
- ...productNamesAsc.filter( ( p ) => p !== 'Polo xxx' ),
];
- const productNamesBySlugDesc = [
- ...productNamesBySlugAsc,
+
+ const result1 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ before: '2021-09-05T15:50:19',
+ search: 'xxx',
+ },
+ } );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength( before.length );
+ expect( result1JSON ).toEqual(
+ expect.arrayContaining( before )
+ );
+
+ const result2 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ after: '2021-09-18T15:50:18',
+ search: 'xxx',
+ },
+ } );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toEqual(
+ expect.not.arrayContaining( before )
+ );
+ expect( result2JSON ).toHaveLength( after.length );
+ expect( result2JSON ).toEqual(
+ expect.arrayContaining( after )
+ );
+ } );
+
+ test( 'attributes', async ( { request } ) => {
+ const red = sampleData.attributes.colors.find(
+ ( term ) => term.name === 'Red'
+ );
+
+ const redProducts = [
+ expect.objectContaining( {
+ name: 'V-Neck T-Shirt xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Hoodie xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Beanie xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Beanie with Logo xxx',
+ } ),
+ ];
+
+ const result = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ attribute: 'pa_colorxxx',
+ attribute_term: red.id,
+ },
+ } );
+ const resultJSON = await result.json();
+
+ expect( result.status() ).toEqual( 200 );
+ expect( resultJSON ).toHaveLength( redProducts.length );
+ expect( resultJSON ).toEqual(
+ expect.arrayContaining( redProducts )
+ );
+ } );
+
+ test( 'status', async ( { request } ) => {
+ const result1 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ status: 'pending',
+ search: 'xxx',
+ },
+ } );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength( 1 );
+ expect( result1JSON[ 0 ].name ).toBe( 'Polo xxx' );
+
+ const result2 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ status: 'draft',
+ },
+ } );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toHaveLength( 0 );
+ } );
+
+ test( 'shipping class', async ( { request } ) => {
+ const result = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ shipping_class:
+ sampleData.shippingClasses.freightJSON.id,
+ },
+ } );
+ const resultJSON = await result.json();
+ expect( result.status() ).toEqual( 200 );
+ expect( resultJSON ).toHaveLength( 1 );
+ expect( resultJSON[ 0 ].name ).toBe( 'Long Sleeve Tee xxx' );
+ } );
+
+ test( 'tax class', async ( { request } ) => {
+ const result = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ tax_class: 'reduced-rate',
+ search: 'xxx',
+ },
+ } );
+ const resultJSON = await result.json();
+ expect( result.status() ).toEqual( 200 );
+ expect( resultJSON ).toHaveLength( 1 );
+ expect( resultJSON[ 0 ].name ).toBe( 'Sunglasses xxx' );
+ } );
+
+ test( 'stock status', async ( { request } ) => {
+ const result = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ stock_status: 'onbackorder',
+ search: 'xxx',
+ },
+ } );
+ const resultJSON = await result.json();
+ expect( result.status() ).toEqual( 200 );
+ expect( resultJSON ).toHaveLength( 1 );
+ expect( resultJSON[ 0 ].name ).toBe( 'T-Shirt xxx' );
+ } );
+
+ test( 'tags', async ( { request } ) => {
+ const coolProducts = [
+ expect.objectContaining( {
+ name: 'Sunglasses xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Hoodie with Pocket xxx',
+ } ),
+ expect.objectContaining( {
+ name: 'Beanie xxx',
+ } ),
+ ];
+
+ const result = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ tag: sampleData.tags.coolJSON.id,
+ },
+ } );
+ const resultJSON = await result.json();
+
+ expect( result.status() ).toEqual( 200 );
+ expect( resultJSON ).toHaveLength( coolProducts.length );
+ expect( resultJSON ).toEqual(
+ expect.arrayContaining( coolProducts )
+ );
+ } );
+
+ test( 'parent', async ( { request } ) => {
+ const result1 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ parent: sampleData.hierarchicalProducts.parentJSON.id,
+ },
+ } );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength( 1 );
+ expect( result1JSON[ 0 ].name ).toBe( 'Child Product xxx' );
+
+ const result2 = await request.get( 'wp-json/wc/v3/products', {
+ params: {
+ parent_exclude:
+ sampleData.hierarchicalProducts.parentJSON.id,
+ },
+ } );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toEqual(
+ expect.not.arrayContaining( [
+ expect.objectContaining( {
+ name: 'Child Product xxx',
+ } ),
+ ] )
+ );
+ } );
+
+ test.describe( 'orderby', () => {
+ const productNamesAsc = [
+ 'Album xxx',
+ 'Beanie with Logo xxx',
+ 'Beanie xxx',
+ 'Belt xxx',
+ 'Cap xxx',
+ 'Child Product xxx',
+ 'Hoodie with Logo xxx',
+ 'Hoodie with Pocket xxx',
+ 'Hoodie with Zipper xxx',
+ 'Hoodie xxx',
+ 'Logo Collection xxx',
+ 'Long Sleeve Tee xxx',
+ 'Parent Product xxx',
+ 'Polo xxx',
+ 'Single xxx',
+ 'Sunglasses xxx',
+ 'T-Shirt with Logo xxx',
+ 'T-Shirt xxx',
+ 'V-Neck T-Shirt xxx',
+ 'WordPress Pennant xxx',
+ ];
+ const productNamesDesc = [ ...productNamesAsc ].reverse();
+ const productNamesByRatingAsc = [
+ 'Sunglasses xxx',
+ 'Cap xxx',
+ 'T-Shirt xxx',
+ ];
+ const productNamesByRatingDesc = [
+ ...productNamesByRatingAsc,
+ ].reverse();
+ const productNamesByPopularityDesc = [
+ 'Beanie with Logo xxx',
+ 'Single xxx',
+ 'T-Shirt xxx',
+ ];
+ const productNamesByPopularityAsc = [
+ ...productNamesByPopularityDesc,
].reverse();
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'asc',
- orderby: 'slug',
- per_page: productNamesBySlugAsc.length,
- search: 'xxx',
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
+ test( 'default', async ( { request } ) => {
+ // Default = date desc.
+ const result = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ search: 'xxx',
+ },
+ }
+ );
+ const resultJSON = await result.json();
+ expect( result.status() ).toEqual( 200 );
- // Verify all results are in ascending order.
- result1JSON.forEach( ( { name }, idx ) => {
- expect( name ).toBe( productNamesBySlugAsc[ idx ] );
+ // Verify all dates are in descending order.
+ let lastDate = Date.now();
+ resultJSON.forEach( ( { date_created_gmt } ) => {
+ const created = Date.parse(
+ date_created_gmt + '.000Z'
+ );
+ expect( lastDate ).toBeGreaterThan( created );
+ lastDate = created;
+ } );
} );
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'desc',
- orderby: 'slug',
- per_page: productNamesBySlugDesc.length,
- search: 'xxx',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
+ test( 'date', async ( { request } ) => {
+ const result = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'asc',
+ orderby: 'date',
+ search: 'xxx',
+ },
+ }
+ );
+ const resultJSON = await result.json();
+ expect( result.status() ).toEqual( 200 );
- // Verify all results are in descending order.
- result2JSON.forEach( ( { name }, idx ) => {
- expect( name ).toBe( productNamesBySlugDesc[ idx ] );
+ // Verify all dates are in ascending order.
+ let lastDate = 0;
+ resultJSON.forEach( ( { date_created_gmt } ) => {
+ const created = Date.parse(
+ date_created_gmt + '.000Z'
+ );
+ expect( created ).toBeGreaterThan( lastDate );
+ lastDate = created;
+ } );
+ } );
+
+ test( 'id', async ( { request } ) => {
+ const result1 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'asc',
+ orderby: 'id',
+ search: 'xxx',
+ },
+ }
+ );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+
+ // Verify all results are in ascending order.
+ let lastId = 0;
+ result1JSON.forEach( ( { id } ) => {
+ expect( id ).toBeGreaterThan( lastId );
+ lastId = id;
+ } );
+
+ const result2 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'desc',
+ orderby: 'id',
+ search: 'xxx',
+ },
+ }
+ );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+
+ // Verify all results are in descending order.
+ lastId = Number.MAX_SAFE_INTEGER;
+ result2JSON.forEach( ( { id } ) => {
+ expect( lastId ).toBeGreaterThan( id );
+ lastId = id;
+ } );
+ } );
+
+ test( 'title', async ( { request } ) => {
+ const result1 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'asc',
+ orderby: 'title',
+ per_page: productNamesAsc.length,
+ search: 'xxx',
+ },
+ }
+ );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+
+ // Verify all results are in ascending order.
+ result1JSON.forEach( ( { name }, idx ) => {
+ expect( name ).toBe( productNamesAsc[ idx ] );
+ } );
+
+ const result2 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'desc',
+ orderby: 'title',
+ per_page: productNamesDesc.length,
+ search: 'xxx',
+ },
+ }
+ );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+
+ // Verify all results are in descending order.
+ result2JSON.forEach( ( { name }, idx ) => {
+ expect( name ).toBe( productNamesDesc[ idx ] );
+ } );
+ } );
+
+ test( 'slug orderby', async ( { request } ) => {
+ const productNamesBySlugAsc = [
+ 'Polo xxx', // The Polo isn't published so it has an empty slug.
+ ...productNamesAsc.filter( ( p ) => p !== 'Polo xxx' ),
+ ];
+ const productNamesBySlugDesc = [
+ ...productNamesBySlugAsc,
+ ].reverse();
+
+ const result1 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'asc',
+ orderby: 'slug',
+ per_page: productNamesBySlugAsc.length,
+ search: 'xxx',
+ },
+ }
+ );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+
+ // Verify all results are in ascending order.
+ result1JSON.forEach( ( { name }, idx ) => {
+ expect( name ).toBe( productNamesBySlugAsc[ idx ] );
+ } );
+
+ const result2 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'desc',
+ orderby: 'slug',
+ per_page: productNamesBySlugDesc.length,
+ search: 'xxx',
+ },
+ }
+ );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+
+ // Verify all results are in descending order.
+ result2JSON.forEach( ( { name }, idx ) => {
+ expect( name ).toBe( productNamesBySlugDesc[ idx ] );
+ } );
+ } );
+
+ test( 'price orderby', async ( { request } ) => {
+ const productNamesMinPriceAsc = [
+ 'Parent Product xxx',
+ 'Child Product xxx',
+ 'Single xxx',
+ 'WordPress Pennant xxx',
+ 'Album xxx',
+ 'V-Neck T-Shirt xxx',
+ 'Cap xxx',
+ 'Beanie with Logo xxx',
+ 'T-Shirt with Logo xxx',
+ 'Beanie xxx',
+ 'T-Shirt xxx',
+ 'Logo Collection xxx',
+ 'Polo xxx',
+ 'Long Sleeve Tee xxx',
+ 'Hoodie with Pocket xxx',
+ 'Hoodie xxx',
+ 'Hoodie with Zipper xxx',
+ 'Hoodie with Logo xxx',
+ 'Belt xxx',
+ 'Sunglasses xxx',
+ ];
+ const result1 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'asc',
+ orderby: 'price',
+ per_page: productNamesMinPriceAsc.length,
+ search: 'xxx',
+ },
+ }
+ );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength(
+ productNamesMinPriceAsc.length
+ );
+
+ // Verify all results are in ascending order.
+ // The query uses the min price calculated in the product meta lookup table,
+ // so we can't just check the price property of the response.
+ result1JSON.forEach( ( { name }, idx ) => {
+ expect( name ).toBe( productNamesMinPriceAsc[ idx ] );
+ } );
+
+ const productNamesMaxPriceDesc = [
+ 'Sunglasses xxx',
+ 'Belt xxx',
+ 'Hoodie xxx',
+ 'Logo Collection xxx',
+ 'Hoodie with Logo xxx',
+ 'Hoodie with Zipper xxx',
+ 'Hoodie with Pocket xxx',
+ 'Long Sleeve Tee xxx',
+ 'V-Neck T-Shirt xxx',
+ 'Polo xxx',
+ 'T-Shirt xxx',
+ 'Beanie xxx',
+ 'T-Shirt with Logo xxx',
+ 'Beanie with Logo xxx',
+ 'Cap xxx',
+ 'Album xxx',
+ 'WordPress Pennant xxx',
+ 'Single xxx',
+ 'Child Product xxx',
+ 'Parent Product xxx',
+ ];
+
+ const result2 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'desc',
+ orderby: 'price',
+ per_page: productNamesMaxPriceDesc.length,
+ search: 'xxx',
+ },
+ }
+ );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toHaveLength(
+ productNamesMaxPriceDesc.length
+ );
+
+ // Verify all results are in descending order.
+ // The query uses the max price calculated in the product meta lookup table,
+ // so we can't just check the price property of the response.
+ result2JSON.forEach( ( { name }, idx ) => {
+ expect( name ).toBe( productNamesMaxPriceDesc[ idx ] );
+ } );
+ } );
+
+ test( 'include', async ( { request } ) => {
+ const includeIds = [
+ sampleData.groupedProducts[ 0 ].id,
+ sampleData.simpleProducts[ 3 ].id,
+ sampleData.hierarchicalProducts.parentJSON.id,
+ ];
+
+ const result1 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'asc',
+ orderby: 'include',
+ include: includeIds.join( ',' ),
+ },
+ }
+ );
+ const result1JSON = await result1.json();
+
+ expect( result1.status() ).toEqual( 200 );
+ expect( result1JSON ).toHaveLength( includeIds.length );
+
+ // Verify all results are in proper order.
+ result1JSON.forEach( ( { id }, idx ) => {
+ expect( id ).toBe( includeIds[ idx ] );
+ } );
+
+ const result2 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'desc',
+ orderby: 'include',
+ include: includeIds.join( ',' ),
+ },
+ }
+ );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+ expect( result2JSON ).toHaveLength( includeIds.length );
+
+ // Verify all results are in proper order.
+ result2JSON.forEach( ( { id }, idx ) => {
+ expect( id ).toBe( includeIds[ idx ] );
+ } );
+ } );
+
+ test( 'rating (desc)', async ( { request } ) => {
+ const result2 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'desc',
+ orderby: 'rating',
+ per_page: productNamesByRatingDesc.length,
+ search: 'xxx',
+ },
+ }
+ );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+
+ // Verify all results are in descending order.
+ result2JSON.forEach( ( { name }, idx ) => {
+ expect( name ).toBe( productNamesByRatingDesc[ idx ] );
+ } );
+ } );
+
+ // This case will remain skipped until ratings can be sorted ascending.
+ // See: https://github.com/woocommerce/woocommerce/issues/30354#issuecomment-925955099.
+ test.skip( 'rating (asc)', async ( { request } ) => {
+ const result1 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'asc',
+ orderby: 'rating',
+ per_page: productNamesByRatingAsc.length,
+ search: 'xxx',
+ },
+ }
+ );
+ expect( result1.status() ).toEqual( 200 );
+ const result1JSON = await result1.json();
+
+ // Verify all results are in ascending order.
+ result1JSON.forEach( ( { name }, idx ) => {
+ expect( name ).toBe( productNamesByRatingAsc[ idx ] );
+ } );
+ } );
+
+ // This case will remain skipped until popularity can be sorted ascending.
+ // See: https://github.com/woocommerce/woocommerce/issues/30354#issuecomment-925955099.
+ test.skip( 'popularity (asc)', async ( { request } ) => {
+ const result1 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'asc',
+ orderby: 'popularity',
+ per_page: productNamesByPopularityAsc.length,
+ search: 'xxx',
+ },
+ }
+ );
+ const result1JSON = await result1.json();
+ expect( result1.status() ).toEqual( 200 );
+
+ // Verify all results are in ascending order.
+ result1JSON.forEach( ( { name }, idx ) => {
+ expect( name ).toBe(
+ productNamesByPopularityAsc[ idx ]
+ );
+ } );
+ } );
+
+ test( 'popularity (desc)', async ( { request } ) => {
+ const result2 = await request.get(
+ 'wp-json/wc/v3/products',
+ {
+ params: {
+ order: 'desc',
+ orderby: 'popularity',
+ per_page: productNamesByPopularityDesc.length,
+ search: 'xxx',
+ },
+ }
+ );
+ const result2JSON = await result2.json();
+ expect( result2.status() ).toEqual( 200 );
+
+ // Verify all results are in descending order.
+ result2JSON.forEach( ( { name }, idx ) => {
+ expect( name ).toBe(
+ productNamesByPopularityDesc[ idx ]
+ );
+ } );
} );
} );
-
- test( 'price orderby', async ( { request } ) => {
- const productNamesMinPriceAsc = [
- 'Parent Product xxx',
- 'Child Product xxx',
- 'Single xxx',
- 'WordPress Pennant xxx',
- 'Album xxx',
- 'V-Neck T-Shirt xxx',
- 'Cap xxx',
- 'Beanie with Logo xxx',
- 'T-Shirt with Logo xxx',
- 'Beanie xxx',
- 'T-Shirt xxx',
- 'Logo Collection xxx',
- 'Polo xxx',
- 'Long Sleeve Tee xxx',
- 'Hoodie with Pocket xxx',
- 'Hoodie xxx',
- 'Hoodie with Zipper xxx',
- 'Hoodie with Logo xxx',
- 'Belt xxx',
- 'Sunglasses xxx',
- ];
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'asc',
- orderby: 'price',
- per_page: productNamesMinPriceAsc.length,
- search: 'xxx',
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength(
- productNamesMinPriceAsc.length
- );
-
- // Verify all results are in ascending order.
- // The query uses the min price calculated in the product meta lookup table,
- // so we can't just check the price property of the response.
- result1JSON.forEach( ( { name }, idx ) => {
- expect( name ).toBe( productNamesMinPriceAsc[ idx ] );
- } );
-
- const productNamesMaxPriceDesc = [
- 'Sunglasses xxx',
- 'Belt xxx',
- 'Hoodie xxx',
- 'Logo Collection xxx',
- 'Hoodie with Logo xxx',
- 'Hoodie with Zipper xxx',
- 'Hoodie with Pocket xxx',
- 'Long Sleeve Tee xxx',
- 'V-Neck T-Shirt xxx',
- 'Polo xxx',
- 'T-Shirt xxx',
- 'Beanie xxx',
- 'T-Shirt with Logo xxx',
- 'Beanie with Logo xxx',
- 'Cap xxx',
- 'Album xxx',
- 'WordPress Pennant xxx',
- 'Single xxx',
- 'Child Product xxx',
- 'Parent Product xxx',
- ];
-
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'desc',
- orderby: 'price',
- per_page: productNamesMaxPriceDesc.length,
- search: 'xxx',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toHaveLength(
- productNamesMaxPriceDesc.length
- );
-
- // Verify all results are in descending order.
- // The query uses the max price calculated in the product meta lookup table,
- // so we can't just check the price property of the response.
- result2JSON.forEach( ( { name }, idx ) => {
- expect( name ).toBe( productNamesMaxPriceDesc[ idx ] );
- } );
- } );
-
- test( 'include', async ( { request } ) => {
- const includeIds = [
- sampleData.groupedProducts[ 0 ].id,
- sampleData.simpleProducts[ 3 ].id,
- sampleData.hierarchicalProducts.parentJSON.id,
- ];
-
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'asc',
- orderby: 'include',
- include: includeIds.join( ',' ),
- },
- } );
- const result1JSON = await result1.json();
-
- expect( result1.status() ).toEqual( 200 );
- expect( result1JSON ).toHaveLength( includeIds.length );
-
- // Verify all results are in proper order.
- result1JSON.forEach( ( { id }, idx ) => {
- expect( id ).toBe( includeIds[ idx ] );
- } );
-
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'desc',
- orderby: 'include',
- include: includeIds.join( ',' ),
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
- expect( result2JSON ).toHaveLength( includeIds.length );
-
- // Verify all results are in proper order.
- result2JSON.forEach( ( { id }, idx ) => {
- expect( id ).toBe( includeIds[ idx ] );
- } );
- } );
-
- test( 'rating (desc)', async ( { request } ) => {
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'desc',
- orderby: 'rating',
- per_page: productNamesByRatingDesc.length,
- search: 'xxx',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
-
- // Verify all results are in descending order.
- result2JSON.forEach( ( { name }, idx ) => {
- expect( name ).toBe( productNamesByRatingDesc[ idx ] );
- } );
- } );
-
- // This case will remain skipped until ratings can be sorted ascending.
- // See: https://github.com/woocommerce/woocommerce/issues/30354#issuecomment-925955099.
- test.skip( 'rating (asc)', async ( { request } ) => {
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'asc',
- orderby: 'rating',
- per_page: productNamesByRatingAsc.length,
- search: 'xxx',
- },
- } );
- expect( result1.status() ).toEqual( 200 );
- const result1JSON = await result1.json();
-
- // Verify all results are in ascending order.
- result1JSON.forEach( ( { name }, idx ) => {
- expect( name ).toBe( productNamesByRatingAsc[ idx ] );
- } );
- } );
-
- // This case will remain skipped until popularity can be sorted ascending.
- // See: https://github.com/woocommerce/woocommerce/issues/30354#issuecomment-925955099.
- test.skip( 'popularity (asc)', async ( { request } ) => {
- const result1 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'asc',
- orderby: 'popularity',
- per_page: productNamesByPopularityAsc.length,
- search: 'xxx',
- },
- } );
- const result1JSON = await result1.json();
- expect( result1.status() ).toEqual( 200 );
-
- // Verify all results are in ascending order.
- result1JSON.forEach( ( { name }, idx ) => {
- expect( name ).toBe( productNamesByPopularityAsc[ idx ] );
- } );
- } );
-
- test( 'popularity (desc)', async ( { request } ) => {
- const result2 = await request.get( 'wp-json/wc/v3/products', {
- params: {
- order: 'desc',
- orderby: 'popularity',
- per_page: productNamesByPopularityDesc.length,
- search: 'xxx',
- },
- } );
- const result2JSON = await result2.json();
- expect( result2.status() ).toEqual( 200 );
-
- // Verify all results are in descending order.
- result2JSON.forEach( ( { name }, idx ) => {
- expect( name ).toBe( productNamesByPopularityDesc[ idx ] );
- } );
- } );
- } );
- } );
+ }
+ );
} );
diff --git a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/products/products-crud.test.js b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/products/products-crud.test.js
index 64bf5072cfd..cbb39c3aed7 100644
--- a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/products/products-crud.test.js
+++ b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/products/products-crud.test.js
@@ -589,278 +589,301 @@ test.describe( 'Products API tests: CRUD', () => {
} );
} );
- test.describe( 'Product review tests: CRUD', () => {
- let productReviewId;
- let reviewsTestProduct;
+ test.describe(
+ 'Product review tests: CRUD',
+ { tag: '@skip-on-default-wpcom' },
+ () => {
+ let productReviewId;
+ let reviewsTestProduct;
- test.beforeAll( async ( { simpleTestProduct } ) => {
- reviewsTestProduct = simpleTestProduct;
- } );
-
- test( 'can add a product review', async ( { request } ) => {
- const response = await request.post(
- 'wp-json/wc/v3/products/reviews',
- {
- data: {
- product_id: reviewsTestProduct.id,
- review: 'Nice simple product!',
- reviewer: 'John Doe',
- reviewer_email: 'john.doe@example.com',
- rating: 5,
- },
- }
- );
- const responseJSON = await response.json();
- productReviewId = responseJSON.id;
-
- expect( response.status() ).toEqual( 201 );
- expect( typeof productReviewId ).toEqual( 'number' );
- expect( responseJSON.id ).toEqual( productReviewId );
- expect( responseJSON.product_name ).toEqual( 'A Simple Product' );
- expect( responseJSON.status ).toEqual( 'approved' );
- expect( responseJSON.reviewer ).toEqual( 'John Doe' );
- expect( responseJSON.reviewer_email ).toEqual(
- 'john.doe@example.com'
- );
- expect( responseJSON.review ).toEqual( 'Nice simple product!' );
- expect( responseJSON.rating ).toEqual( 5 );
- expect( responseJSON.verified ).toEqual( false );
- } );
-
- test( 'cannot add a product review with invalid product_id', async ( {
- request,
- } ) => {
- const response = await request.post(
- 'wp-json/wc/v3/products/reviews',
- {
- data: {
- product_id: 999,
- review: 'A non existent product!',
- reviewer: 'John Do Not',
- reviewer_email: 'john.do.not@example.com',
- rating: 5,
- },
- }
- );
- const responseJSON = await response.json();
-
- expect( response.status() ).toEqual( 404 );
- expect( responseJSON.code ).toEqual(
- 'woocommerce_rest_product_invalid_id'
- );
- expect( responseJSON.message ).toEqual( 'Invalid product ID.' );
- } );
-
- test( 'cannot add a duplicate product review', async ( {
- request,
- } ) => {
- const response = await request.post(
- 'wp-json/wc/v3/products/reviews',
- {
- data: {
- product_id: reviewsTestProduct.id,
- review: 'Nice simple product!',
- reviewer: 'John Doe',
- reviewer_email: 'john.doe@example.com',
- rating: 5,
- },
- }
- );
- const responseJSON = await response.json();
-
- expect( response.status() ).toEqual( 409 );
- expect( responseJSON.code ).toEqual(
- 'woocommerce_rest_comment_duplicate'
- );
- expect( responseJSON.message ).toEqual(
- 'Duplicate comment detected; it looks as though you’ve already said that!'
- );
- } );
-
- test( 'can retrieve a product review', async ( { request } ) => {
- const response = await request.get(
- `wp-json/wc/v3/products/reviews/${ productReviewId }`
- );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( responseJSON.id ).toEqual( productReviewId );
- expect( responseJSON.product_id ).toEqual( reviewsTestProduct.id );
- expect( responseJSON.product_name ).toEqual( 'A Simple Product' );
- expect( responseJSON.status ).toEqual( 'approved' );
- expect( responseJSON.reviewer ).toEqual( 'John Doe' );
- expect( responseJSON.reviewer_email ).toEqual(
- 'john.doe@example.com'
- );
- expect( responseJSON.review ).toEqual(
- '
Nice simple product!
\n'
- );
- expect( responseJSON.rating ).toEqual( 5 );
- expect( responseJSON.verified ).toEqual( false );
- } );
-
- test( 'can retrieve all product reviews', async ( { request } ) => {
- // call API to retrieve all product reviews
- const response = await request.get(
- '/wp-json/wc/v3/products/reviews'
- );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( Array.isArray( responseJSON ) ).toBe( true );
- expect( responseJSON.length ).toBeGreaterThan( 0 );
- } );
-
- test( 'can update a product review', async ( { request } ) => {
- // call API to retrieve all product reviews
- const response = await request.put(
- `wp-json/wc/v3/products/reviews/${ productReviewId }`,
- {
- data: {
- rating: 1,
- },
- }
- );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( responseJSON.id ).toEqual( productReviewId );
- expect( responseJSON.product_id ).toEqual( reviewsTestProduct.id );
- expect( responseJSON.product_name ).toEqual( 'A Simple Product' );
- expect( responseJSON.status ).toEqual( 'approved' );
- expect( responseJSON.reviewer ).toEqual( 'John Doe' );
- expect( responseJSON.reviewer_email ).toEqual(
- 'john.doe@example.com'
- );
- expect( responseJSON.review ).toEqual( 'Nice simple product!' );
- expect( responseJSON.rating ).toEqual( 1 );
- expect( responseJSON.verified ).toEqual( false );
- } );
-
- test( 'can permanently delete a product review', async ( {
- request,
- } ) => {
- // Delete the product review.
- const response = await request.delete(
- `wp-json/wc/v3/products/reviews/${ productReviewId }`,
- {
- data: {
- force: true,
- },
- }
- );
- expect( response.status() ).toEqual( 200 );
-
- // Verify that the product review can no longer be retrieved.
- const getDeletedProductReviewResponse = await request.get(
- `wp-json/wc/v3/products/reviews/${ productReviewId }`
- );
- expect( getDeletedProductReviewResponse.status() ).toEqual( 404 );
- } );
-
- test( 'can batch update product reviews', async ( { request } ) => {
- // Batch create product reviews.
- const response = await request.post(
- `wp-json/wc/v3/products/reviews/batch`,
- {
- data: {
- create: [
- {
- product_id: reviewsTestProduct.id,
- review: 'Nice product!',
- reviewer: 'John Doe',
- reviewer_email: 'john.doe@example.com',
- rating: 4,
- },
- {
- product_id: reviewsTestProduct.id,
- review: 'I love this thing!',
- reviewer: 'Jane Doe',
- reviewer_email: 'Jane.doe@example.com',
- rating: 5,
- },
- ],
- },
- }
- );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( responseJSON.create[ 0 ].product_id ).toEqual(
- reviewsTestProduct.id
- );
- expect( responseJSON.create[ 0 ].review ).toEqual(
- 'Nice product!'
- );
- expect( responseJSON.create[ 0 ].reviewer ).toEqual( 'John Doe' );
- expect( responseJSON.create[ 0 ].reviewer_email ).toEqual(
- 'john.doe@example.com'
- );
- expect( responseJSON.create[ 0 ].rating ).toEqual( 4 );
-
- expect( responseJSON.create[ 1 ].product_id ).toEqual(
- reviewsTestProduct.id
- );
- expect( responseJSON.create[ 1 ].review ).toEqual(
- 'I love this thing!'
- );
- expect( responseJSON.create[ 1 ].reviewer ).toEqual( 'Jane Doe' );
- expect( responseJSON.create[ 1 ].reviewer_email ).toEqual(
- 'Jane.doe@example.com'
- );
- expect( responseJSON.create[ 1 ].rating ).toEqual( 5 );
- const review1Id = responseJSON.create[ 0 ].id;
- const review2Id = responseJSON.create[ 1 ].id;
-
- // Batch create a new review, update a review and delete another.
- const responseBatchUpdate = await request.post(
- `wp-json/wc/v3/products/reviews/batch`,
- {
- data: {
- create: [
- {
- product_id: reviewsTestProduct.id,
- review: 'Ok product.',
- reviewer: 'Jack Doe',
- reviewer_email: 'jack.doe@example.com',
- rating: 3,
- },
- ],
- update: [
- {
- id: review1Id,
- review: 'On reflection, I hate this thing!',
- rating: 1,
- },
- ],
- delete: [ review2Id ],
- },
- }
- );
- const responseBatchUpdateJSON = await responseBatchUpdate.json();
- const review3Id = responseBatchUpdateJSON.create[ 0 ].id;
- expect( response.status() ).toEqual( 200 );
-
- const responseUpdatedReview = await request.get(
- `wp-json/wc/v3/products/reviews/${ review1Id }`
- );
- const responseUpdatedReviewJSON =
- await responseUpdatedReview.json();
- expect( responseUpdatedReviewJSON.review ).toEqual(
- '
On reflection, I hate this thing!
\n'
- );
- expect( responseUpdatedReviewJSON.rating ).toEqual( 1 );
-
- // Verify that the deleted review can no longer be retrieved.
- const getDeletedProductReviewResponse = await request.get(
- `wp-json/wc/v3/products/reviews/${ review2Id }`
- );
- expect( getDeletedProductReviewResponse.status() ).toEqual( 404 );
-
- // Batch delete the created tags
- await request.post( `wp-json/wc/v3/products/reviews/batch`, {
- data: {
- delete: [ review1Id, review3Id ],
- },
+ test.beforeAll( async ( { simpleTestProduct } ) => {
+ reviewsTestProduct = simpleTestProduct;
} );
- } );
- } );
+
+ test( 'can add a product review', async ( { request } ) => {
+ const response = await request.post(
+ 'wp-json/wc/v3/products/reviews',
+ {
+ data: {
+ product_id: reviewsTestProduct.id,
+ review: 'Nice simple product!',
+ reviewer: 'John Doe',
+ reviewer_email: 'john.doe@example.com',
+ rating: 5,
+ },
+ }
+ );
+ const responseJSON = await response.json();
+ productReviewId = responseJSON.id;
+
+ expect( response.status() ).toEqual( 201 );
+ expect( typeof productReviewId ).toEqual( 'number' );
+ expect( responseJSON.id ).toEqual( productReviewId );
+ expect( responseJSON.product_name ).toEqual(
+ 'A Simple Product'
+ );
+ expect( responseJSON.status ).toEqual( 'approved' );
+ expect( responseJSON.reviewer ).toEqual( 'John Doe' );
+ expect( responseJSON.reviewer_email ).toEqual(
+ 'john.doe@example.com'
+ );
+ expect( responseJSON.review ).toEqual( 'Nice simple product!' );
+ expect( responseJSON.rating ).toEqual( 5 );
+ expect( responseJSON.verified ).toEqual( false );
+ } );
+
+ test( 'cannot add a product review with invalid product_id', async ( {
+ request,
+ } ) => {
+ const response = await request.post(
+ 'wp-json/wc/v3/products/reviews',
+ {
+ data: {
+ product_id: 999,
+ review: 'A non existent product!',
+ reviewer: 'John Do Not',
+ reviewer_email: 'john.do.not@example.com',
+ rating: 5,
+ },
+ }
+ );
+ const responseJSON = await response.json();
+
+ expect( response.status() ).toEqual( 404 );
+ expect( responseJSON.code ).toEqual(
+ 'woocommerce_rest_product_invalid_id'
+ );
+ expect( responseJSON.message ).toEqual( 'Invalid product ID.' );
+ } );
+
+ test( 'cannot add a duplicate product review', async ( {
+ request,
+ } ) => {
+ const response = await request.post(
+ 'wp-json/wc/v3/products/reviews',
+ {
+ data: {
+ product_id: reviewsTestProduct.id,
+ review: 'Nice simple product!',
+ reviewer: 'John Doe',
+ reviewer_email: 'john.doe@example.com',
+ rating: 5,
+ },
+ }
+ );
+ const responseJSON = await response.json();
+
+ expect( response.status() ).toEqual( 409 );
+ expect( responseJSON.code ).toEqual(
+ 'woocommerce_rest_comment_duplicate'
+ );
+ expect( responseJSON.message ).toEqual(
+ 'Duplicate comment detected; it looks as though you’ve already said that!'
+ );
+ } );
+
+ test( 'can retrieve a product review', async ( { request } ) => {
+ const response = await request.get(
+ `wp-json/wc/v3/products/reviews/${ productReviewId }`
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( responseJSON.id ).toEqual( productReviewId );
+ expect( responseJSON.product_id ).toEqual(
+ reviewsTestProduct.id
+ );
+ expect( responseJSON.product_name ).toEqual(
+ 'A Simple Product'
+ );
+ expect( responseJSON.status ).toEqual( 'approved' );
+ expect( responseJSON.reviewer ).toEqual( 'John Doe' );
+ expect( responseJSON.reviewer_email ).toEqual(
+ 'john.doe@example.com'
+ );
+ expect( responseJSON.review ).toEqual(
+ '
Nice simple product!
\n'
+ );
+ expect( responseJSON.rating ).toEqual( 5 );
+ expect( responseJSON.verified ).toEqual( false );
+ } );
+
+ test( 'can retrieve all product reviews', async ( { request } ) => {
+ // call API to retrieve all product reviews
+ const response = await request.get(
+ '/wp-json/wc/v3/products/reviews'
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( Array.isArray( responseJSON ) ).toBe( true );
+ expect( responseJSON.length ).toBeGreaterThan( 0 );
+ } );
+
+ test( 'can update a product review', async ( { request } ) => {
+ // call API to retrieve all product reviews
+ const response = await request.put(
+ `wp-json/wc/v3/products/reviews/${ productReviewId }`,
+ {
+ data: {
+ rating: 1,
+ },
+ }
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( responseJSON.id ).toEqual( productReviewId );
+ expect( responseJSON.product_id ).toEqual(
+ reviewsTestProduct.id
+ );
+ expect( responseJSON.product_name ).toEqual(
+ 'A Simple Product'
+ );
+ expect( responseJSON.status ).toEqual( 'approved' );
+ expect( responseJSON.reviewer ).toEqual( 'John Doe' );
+ expect( responseJSON.reviewer_email ).toEqual(
+ 'john.doe@example.com'
+ );
+ expect( responseJSON.review ).toEqual( 'Nice simple product!' );
+ expect( responseJSON.rating ).toEqual( 1 );
+ expect( responseJSON.verified ).toEqual( false );
+ } );
+
+ test( 'can permanently delete a product review', async ( {
+ request,
+ } ) => {
+ // Delete the product review.
+ const response = await request.delete(
+ `wp-json/wc/v3/products/reviews/${ productReviewId }`,
+ {
+ data: {
+ force: true,
+ },
+ }
+ );
+ expect( response.status() ).toEqual( 200 );
+
+ // Verify that the product review can no longer be retrieved.
+ const getDeletedProductReviewResponse = await request.get(
+ `wp-json/wc/v3/products/reviews/${ productReviewId }`
+ );
+ expect( getDeletedProductReviewResponse.status() ).toEqual(
+ 404
+ );
+ } );
+
+ test( 'can batch update product reviews', async ( { request } ) => {
+ // Batch create product reviews.
+ const response = await request.post(
+ `wp-json/wc/v3/products/reviews/batch`,
+ {
+ data: {
+ create: [
+ {
+ product_id: reviewsTestProduct.id,
+ review: 'Nice product!',
+ reviewer: 'John Doe',
+ reviewer_email: 'john.doe@example.com',
+ rating: 4,
+ },
+ {
+ product_id: reviewsTestProduct.id,
+ review: 'I love this thing!',
+ reviewer: 'Jane Doe',
+ reviewer_email: 'Jane.doe@example.com',
+ rating: 5,
+ },
+ ],
+ },
+ }
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( responseJSON.create[ 0 ].product_id ).toEqual(
+ reviewsTestProduct.id
+ );
+ expect( responseJSON.create[ 0 ].review ).toEqual(
+ 'Nice product!'
+ );
+ expect( responseJSON.create[ 0 ].reviewer ).toEqual(
+ 'John Doe'
+ );
+ expect( responseJSON.create[ 0 ].reviewer_email ).toEqual(
+ 'john.doe@example.com'
+ );
+ expect( responseJSON.create[ 0 ].rating ).toEqual( 4 );
+
+ expect( responseJSON.create[ 1 ].product_id ).toEqual(
+ reviewsTestProduct.id
+ );
+ expect( responseJSON.create[ 1 ].review ).toEqual(
+ 'I love this thing!'
+ );
+ expect( responseJSON.create[ 1 ].reviewer ).toEqual(
+ 'Jane Doe'
+ );
+ expect( responseJSON.create[ 1 ].reviewer_email ).toEqual(
+ 'Jane.doe@example.com'
+ );
+ expect( responseJSON.create[ 1 ].rating ).toEqual( 5 );
+ const review1Id = responseJSON.create[ 0 ].id;
+ const review2Id = responseJSON.create[ 1 ].id;
+
+ // Batch create a new review, update a review and delete another.
+ const responseBatchUpdate = await request.post(
+ `wp-json/wc/v3/products/reviews/batch`,
+ {
+ data: {
+ create: [
+ {
+ product_id: reviewsTestProduct.id,
+ review: 'Ok product.',
+ reviewer: 'Jack Doe',
+ reviewer_email: 'jack.doe@example.com',
+ rating: 3,
+ },
+ ],
+ update: [
+ {
+ id: review1Id,
+ review: 'On reflection, I hate this thing!',
+ rating: 1,
+ },
+ ],
+ delete: [ review2Id ],
+ },
+ }
+ );
+ const responseBatchUpdateJSON =
+ await responseBatchUpdate.json();
+ const review3Id = responseBatchUpdateJSON.create[ 0 ].id;
+ expect( response.status() ).toEqual( 200 );
+
+ const responseUpdatedReview = await request.get(
+ `wp-json/wc/v3/products/reviews/${ review1Id }`
+ );
+ const responseUpdatedReviewJSON =
+ await responseUpdatedReview.json();
+ expect( responseUpdatedReviewJSON.review ).toEqual(
+ '
On reflection, I hate this thing!
\n'
+ );
+ expect( responseUpdatedReviewJSON.rating ).toEqual( 1 );
+
+ // Verify that the deleted review can no longer be retrieved.
+ const getDeletedProductReviewResponse = await request.get(
+ `wp-json/wc/v3/products/reviews/${ review2Id }`
+ );
+ expect( getDeletedProductReviewResponse.status() ).toEqual(
+ 404
+ );
+
+ // Batch delete the created tags
+ await request.post( `wp-json/wc/v3/products/reviews/batch`, {
+ data: {
+ delete: [ review1Id, review3Id ],
+ },
+ } );
+ } );
+ }
+ );
test.describe( 'Product shipping classes tests: CRUD', () => {
let productShippingClassId;
@@ -958,83 +981,91 @@ test.describe( 'Products API tests: CRUD', () => {
);
} );
- test( 'can batch update product shipping classes', async ( {
- request,
- } ) => {
- // Batch create product shipping classes.
- const response = await request.post(
- `wp-json/wc/v3/products/shipping_classes/batch`,
- {
- data: {
- create: [
- {
- name: 'Small Items',
- },
- {
- name: 'Large Items',
- },
- ],
- },
- }
- );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( responseJSON.create[ 0 ].name ).toEqual( 'Small Items' );
- expect( responseJSON.create[ 1 ].name ).toEqual( 'Large Items' );
- const shippingClass1Id = responseJSON.create[ 0 ].id;
- const shippingClass2Id = responseJSON.create[ 1 ].id;
+ test(
+ 'can batch update product shipping classes',
+ { tag: [ '@skip-on-default-pressable', '@skip-on-default-wpcom' ] },
+ async ( { request } ) => {
+ // Batch create product shipping classes.
+ const response = await request.post(
+ `wp-json/wc/v3/products/shipping_classes/batch`,
+ {
+ data: {
+ create: [
+ {
+ name: 'Small Items',
+ },
+ {
+ name: 'Large Items',
+ },
+ ],
+ },
+ }
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( responseJSON.create[ 0 ].name ).toEqual(
+ 'Small Items'
+ );
+ expect( responseJSON.create[ 1 ].name ).toEqual(
+ 'Large Items'
+ );
+ const shippingClass1Id = responseJSON.create[ 0 ].id;
+ const shippingClass2Id = responseJSON.create[ 1 ].id;
- // Batch create a new shipping class, update a shipping class and delete another.
- const responseBatchUpdate = await request.post(
- `wp-json/wc/v3/products/shipping_classes/batch`,
- {
- data: {
- create: [
- {
- name: 'Express',
- },
- ],
- update: [
- {
- id: shippingClass1Id,
- description: 'Priority shipping.',
- },
- ],
- delete: [ shippingClass2Id ],
- },
- }
- );
- const responseBatchUpdateJSON = await responseBatchUpdate.json();
- const shippingClass3Id = responseBatchUpdateJSON.create[ 0 ].id;
- expect( response.status() ).toEqual( 200 );
+ // Batch create a new shipping class, update a shipping class and delete another.
+ const responseBatchUpdate = await request.post(
+ `wp-json/wc/v3/products/shipping_classes/batch`,
+ {
+ data: {
+ create: [
+ {
+ name: 'Express',
+ },
+ ],
+ update: [
+ {
+ id: shippingClass1Id,
+ description: 'Priority shipping.',
+ },
+ ],
+ delete: [ shippingClass2Id ],
+ },
+ }
+ );
+ const responseBatchUpdateJSON =
+ await responseBatchUpdate.json();
+ const shippingClass3Id = responseBatchUpdateJSON.create[ 0 ].id;
+ expect( response.status() ).toEqual( 200 );
- const responseUpdatedShippingClass = await request.get(
- `wp-json/wc/v3/products/shipping_classes/${ shippingClass1Id }`
- );
- const responseUpdatedShippingClassJSON =
- await responseUpdatedShippingClass.json();
- expect( responseUpdatedShippingClassJSON.description ).toEqual(
- 'Priority shipping.'
- );
+ const responseUpdatedShippingClass = await request.get(
+ `wp-json/wc/v3/products/shipping_classes/${ shippingClass1Id }`
+ );
+ const responseUpdatedShippingClassJSON =
+ await responseUpdatedShippingClass.json();
+ expect( responseUpdatedShippingClassJSON.description ).toEqual(
+ 'Priority shipping.'
+ );
- // Verify that the product tag can no longer be retrieved.
- const getDeletedProductShippingClassResponse = await request.get(
- `wp-json/wc/v3/products/shipping_classes/${ shippingClass2Id }`
- );
- expect( getDeletedProductShippingClassResponse.status() ).toEqual(
- 404
- );
+ // Verify that the product tag can no longer be retrieved.
+ const getDeletedProductShippingClassResponse =
+ await request.get(
+ `wp-json/wc/v3/products/shipping_classes/${ shippingClass2Id }`
+ );
+ expect(
+ getDeletedProductShippingClassResponse.status()
+ ).toEqual( 404 );
- // Batch delete the created tags
- await request.post(
- `wp-json/wc/v3/products/shipping_classes/batch`,
- {
- data: {
- delete: [ shippingClass1Id, shippingClass3Id ],
- },
- }
- );
- } );
+ // Batch delete the created tags
+ await request.post(
+ `wp-json/wc/v3/products/shipping_classes/batch`,
+ {
+ data: {
+ delete: [ shippingClass1Id, shippingClass3Id ],
+ },
+ }
+ );
+ }
+ );
} );
test.describe( 'Product tags tests: CRUD', () => {
diff --git a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/settings/settings-crud.test.js b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/settings/settings-crud.test.js
index 376d606c745..e7caee7e0b4 100644
--- a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/settings/settings-crud.test.js
+++ b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/settings/settings-crud.test.js
@@ -280,7 +280,7 @@ test.describe.serial( 'Settings API tests: CRUD', () => {
type: 'text',
default: '',
tip: 'The street address for your business location.',
- value: '',
+ value: expect.any( String ),
} ),
] )
);
@@ -310,7 +310,7 @@ test.describe.serial( 'Settings API tests: CRUD', () => {
type: 'text',
default: '',
tip: 'The city in which your business is located.',
- value: '',
+ value: expect.any( String ),
} ),
] )
);
@@ -341,7 +341,7 @@ test.describe.serial( 'Settings API tests: CRUD', () => {
type: 'text',
default: '',
tip: 'The postal code, if any, in which your business is located.',
- value: '',
+ value: expect.any( String ),
} ),
] )
);
@@ -1019,157 +1019,164 @@ test.describe.serial( 'Settings API tests: CRUD', () => {
} );
test.describe( 'List all Tax settings options', () => {
- test( 'can retrieve all tax settings', async ( { request } ) => {
- // call API to retrieve all settings options
- const response = await request.get( '/wp-json/wc/v3/settings/tax' );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( Array.isArray( responseJSON ) ).toBe( true );
- expect( responseJSON.length ).toBeGreaterThan( 0 );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_prices_include_tax',
- label: 'Prices entered with tax',
- description: '',
- type: 'radio',
- default: 'no',
- options: {
- yes: 'Yes, I will enter prices inclusive of tax',
- no: 'No, I will enter prices exclusive of tax',
- },
- tip: 'This option is important as it will affect how you input prices. Changing it will not update existing products.',
- value: 'no',
- } ),
- ] )
- );
+ test(
+ 'can retrieve all tax settings',
+ { tag: [ '@skip-on-default-pressable', '@skip-on-default-wpcom' ] },
+ async ( { request } ) => {
+ // call API to retrieve all settings options
+ const response = await request.get(
+ '/wp-json/wc/v3/settings/tax'
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( Array.isArray( responseJSON ) ).toBe( true );
+ expect( responseJSON.length ).toBeGreaterThan( 0 );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_prices_include_tax',
+ label: 'Prices entered with tax',
+ description: '',
+ type: 'radio',
+ default: 'no',
+ options: {
+ yes: 'Yes, I will enter prices inclusive of tax',
+ no: 'No, I will enter prices exclusive of tax',
+ },
+ tip: 'This option is important as it will affect how you input prices. Changing it will not update existing products.',
+ value: 'no',
+ } ),
+ ] )
+ );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_tax_based_on',
- label: 'Calculate tax based on',
- description: '',
- type: 'select',
- default: 'shipping',
- options: {
- shipping: 'Customer shipping address',
- billing: 'Customer billing address',
- base: 'Shop base address',
- },
- tip: 'This option determines which address is used to calculate tax.',
- value: 'shipping',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_shipping_tax_class',
- label: 'Shipping tax class',
- description:
- 'Optionally control which tax class shipping gets, or leave it so shipping tax is based on the cart items themselves.',
- type: 'select',
- default: 'inherit',
- options: {
- inherit: 'Shipping tax class based on cart items',
- '': 'Standard',
- 'reduced-rate': 'Reduced rate',
- 'zero-rate': 'Zero rate',
- },
- tip: 'Optionally control which tax class shipping gets, or leave it so shipping tax is based on the cart items themselves.',
- value: 'inherit',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_tax_round_at_subtotal',
- label: 'Rounding',
- description:
- 'Round tax at subtotal level, instead of rounding per line',
- type: 'checkbox',
- default: 'no',
- value: 'no',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_tax_classes',
- label: 'Additional tax classes',
- description: '',
- type: 'textarea',
- default: '',
- tip: 'List additional tax classes you need below (1 per line, e.g. Reduced Rates). These are in addition to "Standard rate" which exists by default.',
- value: '',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_tax_display_shop',
- label: 'Display prices in the shop',
- description: '',
- type: 'select',
- default: 'excl',
- options: {
- incl: 'Including tax',
- excl: 'Excluding tax',
- },
- value: 'excl',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_tax_display_cart',
- label: 'Display prices during cart and checkout',
- description: '',
- type: 'select',
- default: 'excl',
- options: {
- incl: 'Including tax',
- excl: 'Excluding tax',
- },
- value: 'excl',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_price_display_suffix',
- label: 'Price display suffix',
- description: '',
- type: 'text',
- default: '',
- tip: 'Define text to show after your product prices. This could be, for example, "inc. Vat" to explain your pricing. You can also have prices substituted here using one of the following: {price_including_tax}, {price_excluding_tax}.',
- value: '',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_tax_total_display',
- label: 'Display tax totals',
- description: '',
- type: 'select',
- default: 'itemized',
- options: {
- single: 'As a single total',
- itemized: 'Itemized',
- },
- value: 'itemized',
- } ),
- ] )
- );
- } );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_tax_based_on',
+ label: 'Calculate tax based on',
+ description: '',
+ type: 'select',
+ default: 'shipping',
+ options: {
+ shipping: 'Customer shipping address',
+ billing: 'Customer billing address',
+ base: 'Shop base address',
+ },
+ tip: 'This option determines which address is used to calculate tax.',
+ value: 'shipping',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_shipping_tax_class',
+ label: 'Shipping tax class',
+ description:
+ 'Optionally control which tax class shipping gets, or leave it so shipping tax is based on the cart items themselves.',
+ type: 'select',
+ default: 'inherit',
+ options: {
+ inherit:
+ 'Shipping tax class based on cart items',
+ '': 'Standard',
+ 'reduced-rate': 'Reduced rate',
+ 'zero-rate': 'Zero rate',
+ },
+ tip: 'Optionally control which tax class shipping gets, or leave it so shipping tax is based on the cart items themselves.',
+ value: 'inherit',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_tax_round_at_subtotal',
+ label: 'Rounding',
+ description:
+ 'Round tax at subtotal level, instead of rounding per line',
+ type: 'checkbox',
+ default: 'no',
+ value: 'no',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_tax_classes',
+ label: 'Additional tax classes',
+ description: '',
+ type: 'textarea',
+ default: '',
+ tip: 'List additional tax classes you need below (1 per line, e.g. Reduced Rates). These are in addition to "Standard rate" which exists by default.',
+ value: '',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_tax_display_shop',
+ label: 'Display prices in the shop',
+ description: '',
+ type: 'select',
+ default: 'excl',
+ options: {
+ incl: 'Including tax',
+ excl: 'Excluding tax',
+ },
+ value: 'excl',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_tax_display_cart',
+ label: 'Display prices during cart and checkout',
+ description: '',
+ type: 'select',
+ default: 'excl',
+ options: {
+ incl: 'Including tax',
+ excl: 'Excluding tax',
+ },
+ value: 'excl',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_price_display_suffix',
+ label: 'Price display suffix',
+ description: '',
+ type: 'text',
+ default: '',
+ tip: 'Define text to show after your product prices. This could be, for example, "inc. Vat" to explain your pricing. You can also have prices substituted here using one of the following: {price_including_tax}, {price_excluding_tax}.',
+ value: '',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_tax_total_display',
+ label: 'Display tax totals',
+ description: '',
+ type: 'select',
+ default: 'itemized',
+ options: {
+ single: 'As a single total',
+ itemized: 'Itemized',
+ },
+ value: 'itemized',
+ } ),
+ ] )
+ );
+ }
+ );
} );
test.describe( 'List all Shipping settings options', () => {
@@ -1613,286 +1620,294 @@ test.describe.serial( 'Settings API tests: CRUD', () => {
} );
} );
- test.describe( 'List all Advanced settings options', () => {
- test( 'can retrieve all advanced settings', async ( { request } ) => {
- // call API to retrieve all settings options
- const response = await request.get(
- '/wp-json/wc/v3/settings/advanced'
- );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( Array.isArray( responseJSON ) ).toBe( true );
+ test.describe(
+ 'List all Advanced settings options',
+ { tag: '@skip-on-default-wpcom' },
+ () => {
+ test( 'can retrieve all advanced settings', async ( {
+ request,
+ } ) => {
+ // call API to retrieve all settings options
+ const response = await request.get(
+ '/wp-json/wc/v3/settings/advanced'
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( Array.isArray( responseJSON ) ).toBe( true );
+
+ // not present in external host
+ // eslint-disable-next-line playwright/no-conditional-in-test
+ if ( ! shouldSkip ) {
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_cart_page_id',
+ label: 'Cart page',
+ description:
+ 'Page where shoppers review their shopping cart',
+ type: 'select',
+ default: '',
+ tip: 'Page where shoppers review their shopping cart',
+ value: expect.any( String ),
+ options: expect.any( Object ),
+ } ),
+ ] )
+ );
+ }
+
+ // not present in external host
+ // eslint-disable-next-line playwright/no-conditional-in-test
+ if ( ! shouldSkip ) {
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_checkout_page_id',
+ label: 'Checkout page',
+ description:
+ 'Page where shoppers go to finalize their purchase',
+ type: 'select',
+ default: expect.any( Number ),
+ tip: 'Page where shoppers go to finalize their purchase',
+ value: expect.any( String ),
+ options: expect.any( Object ),
+ } ),
+ ] )
+ );
+ }
- // not present in external host
- // eslint-disable-next-line playwright/no-conditional-in-test
- if ( ! shouldSkip ) {
expect( responseJSON ).toEqual(
expect.arrayContaining( [
expect.objectContaining( {
- id: 'woocommerce_cart_page_id',
- label: 'Cart page',
+ id: 'woocommerce_myaccount_page_id',
+ label: 'My account page',
description:
- 'Page where shoppers review their shopping cart',
+ 'Page contents: [woocommerce_my_account]',
type: 'select',
default: '',
- tip: 'Page where shoppers review their shopping cart',
+ tip: 'Page contents: [woocommerce_my_account]',
value: expect.any( String ),
options: expect.any( Object ),
} ),
] )
);
- }
-
- // not present in external host
- // eslint-disable-next-line playwright/no-conditional-in-test
- if ( ! shouldSkip ) {
expect( responseJSON ).toEqual(
expect.arrayContaining( [
expect.objectContaining( {
- id: 'woocommerce_checkout_page_id',
- label: 'Checkout page',
+ id: 'woocommerce_checkout_pay_endpoint',
+ label: 'Pay',
description:
- 'Page where shoppers go to finalize their purchase',
- type: 'select',
- default: expect.any( Number ),
- tip: 'Page where shoppers go to finalize their purchase',
- value: expect.any( String ),
- options: expect.any( Object ),
+ 'Endpoint for the "Checkout → Pay" page.',
+ type: 'text',
+ default: 'order-pay',
+ tip: 'Endpoint for the "Checkout → Pay" page.',
+ value: 'order-pay',
} ),
] )
);
- }
-
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_myaccount_page_id',
- label: 'My account page',
- description: 'Page contents: [woocommerce_my_account]',
- type: 'select',
- default: '',
- tip: 'Page contents: [woocommerce_my_account]',
- value: expect.any( String ),
- options: expect.any( Object ),
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_checkout_pay_endpoint',
- label: 'Pay',
- description:
- 'Endpoint for the "Checkout → Pay" page.',
- type: 'text',
- default: 'order-pay',
- tip: 'Endpoint for the "Checkout → Pay" page.',
- value: 'order-pay',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_checkout_order_received_endpoint',
- label: 'Order received',
- description:
- 'Endpoint for the "Checkout → Order received" page.',
- type: 'text',
- default: 'order-received',
- tip: 'Endpoint for the "Checkout → Order received" page.',
- value: 'order-received',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_myaccount_add_payment_method_endpoint',
- label: 'Add payment method',
- description:
- 'Endpoint for the "Checkout → Add payment method" page.',
- type: 'text',
- default: 'add-payment-method',
- tip: 'Endpoint for the "Checkout → Add payment method" page.',
- value: 'add-payment-method',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_myaccount_delete_payment_method_endpoint',
- label: 'Delete payment method',
- description:
- 'Endpoint for the delete payment method page.',
- type: 'text',
- default: 'delete-payment-method',
- tip: 'Endpoint for the delete payment method page.',
- value: 'delete-payment-method',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_myaccount_orders_endpoint',
- label: 'Orders',
- description:
- 'Endpoint for the "My account → Orders" page.',
- type: 'text',
- default: 'orders',
- tip: 'Endpoint for the "My account → Orders" page.',
- value: 'orders',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_myaccount_view_order_endpoint',
- label: 'View order',
- description:
- 'Endpoint for the "My account → View order" page.',
- type: 'text',
- default: 'view-order',
- tip: 'Endpoint for the "My account → View order" page.',
- value: 'view-order',
- } ),
- ] )
- );
-
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_myaccount_downloads_endpoint',
- label: 'Downloads',
- description:
- 'Endpoint for the "My account → Downloads" page.',
- type: 'text',
- default: 'downloads',
- tip: 'Endpoint for the "My account → Downloads" page.',
- value: 'downloads',
- } ),
- ] )
- );
-
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_myaccount_edit_account_endpoint',
- label: 'Edit account',
- description:
- 'Endpoint for the "My account → Edit account" page.',
- type: 'text',
- default: 'edit-account',
- tip: 'Endpoint for the "My account → Edit account" page.',
- value: 'edit-account',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_myaccount_edit_address_endpoint',
- label: 'Addresses',
- description:
- 'Endpoint for the "My account → Addresses" page.',
- type: 'text',
- default: 'edit-address',
- tip: 'Endpoint for the "My account → Addresses" page.',
- value: 'edit-address',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_myaccount_payment_methods_endpoint',
- label: 'Payment methods',
- description:
- 'Endpoint for the "My account → Payment methods" page.',
- type: 'text',
- default: 'payment-methods',
- tip: 'Endpoint for the "My account → Payment methods" page.',
- value: 'payment-methods',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_myaccount_lost_password_endpoint',
- label: 'Lost password',
- description:
- 'Endpoint for the "My account → Lost password" page.',
- type: 'text',
- default: 'lost-password',
- tip: 'Endpoint for the "My account → Lost password" page.',
- value: 'lost-password',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_logout_endpoint',
- label: 'Logout',
- description:
- 'Endpoint for the triggering logout. You can add this to your menus via a custom link: yoursite.com/?customer-logout=true',
- type: 'text',
- default: 'customer-logout',
- tip: 'Endpoint for the triggering logout. You can add this to your menus via a custom link: yoursite.com/?customer-logout=true',
- value: 'customer-logout',
- } ),
- ] )
- );
- // eslint-disable-next-line playwright/no-conditional-in-test
- if ( ! shouldSkip ) {
expect( responseJSON ).toEqual(
expect.arrayContaining( [
expect.objectContaining( {
- id: 'woocommerce_allow_tracking',
- label: 'Enable tracking',
+ id: 'woocommerce_checkout_order_received_endpoint',
+ label: 'Order received',
description:
- 'Allow usage of WooCommerce to be tracked',
+ 'Endpoint for the "Checkout → Order received" page.',
+ type: 'text',
+ default: 'order-received',
+ tip: 'Endpoint for the "Checkout → Order received" page.',
+ value: 'order-received',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_myaccount_add_payment_method_endpoint',
+ label: 'Add payment method',
+ description:
+ 'Endpoint for the "Checkout → Add payment method" page.',
+ type: 'text',
+ default: 'add-payment-method',
+ tip: 'Endpoint for the "Checkout → Add payment method" page.',
+ value: 'add-payment-method',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_myaccount_delete_payment_method_endpoint',
+ label: 'Delete payment method',
+ description:
+ 'Endpoint for the delete payment method page.',
+ type: 'text',
+ default: 'delete-payment-method',
+ tip: 'Endpoint for the delete payment method page.',
+ value: 'delete-payment-method',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_myaccount_orders_endpoint',
+ label: 'Orders',
+ description:
+ 'Endpoint for the "My account → Orders" page.',
+ type: 'text',
+ default: 'orders',
+ tip: 'Endpoint for the "My account → Orders" page.',
+ value: 'orders',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_myaccount_view_order_endpoint',
+ label: 'View order',
+ description:
+ 'Endpoint for the "My account → View order" page.',
+ type: 'text',
+ default: 'view-order',
+ tip: 'Endpoint for the "My account → View order" page.',
+ value: 'view-order',
+ } ),
+ ] )
+ );
+
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_myaccount_downloads_endpoint',
+ label: 'Downloads',
+ description:
+ 'Endpoint for the "My account → Downloads" page.',
+ type: 'text',
+ default: 'downloads',
+ tip: 'Endpoint for the "My account → Downloads" page.',
+ value: 'downloads',
+ } ),
+ ] )
+ );
+
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_myaccount_edit_account_endpoint',
+ label: 'Edit account',
+ description:
+ 'Endpoint for the "My account → Edit account" page.',
+ type: 'text',
+ default: 'edit-account',
+ tip: 'Endpoint for the "My account → Edit account" page.',
+ value: 'edit-account',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_myaccount_edit_address_endpoint',
+ label: 'Addresses',
+ description:
+ 'Endpoint for the "My account → Addresses" page.',
+ type: 'text',
+ default: 'edit-address',
+ tip: 'Endpoint for the "My account → Addresses" page.',
+ value: 'edit-address',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_myaccount_payment_methods_endpoint',
+ label: 'Payment methods',
+ description:
+ 'Endpoint for the "My account → Payment methods" page.',
+ type: 'text',
+ default: 'payment-methods',
+ tip: 'Endpoint for the "My account → Payment methods" page.',
+ value: 'payment-methods',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_myaccount_lost_password_endpoint',
+ label: 'Lost password',
+ description:
+ 'Endpoint for the "My account → Lost password" page.',
+ type: 'text',
+ default: 'lost-password',
+ tip: 'Endpoint for the "My account → Lost password" page.',
+ value: 'lost-password',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_logout_endpoint',
+ label: 'Logout',
+ description:
+ 'Endpoint for the triggering logout. You can add this to your menus via a custom link: yoursite.com/?customer-logout=true',
+ type: 'text',
+ default: 'customer-logout',
+ tip: 'Endpoint for the triggering logout. You can add this to your menus via a custom link: yoursite.com/?customer-logout=true',
+ value: 'customer-logout',
+ } ),
+ ] )
+ );
+ // eslint-disable-next-line playwright/no-conditional-in-test
+ if ( ! shouldSkip ) {
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_allow_tracking',
+ label: 'Enable tracking',
+ description:
+ 'Allow usage of WooCommerce to be tracked',
+ type: 'checkbox',
+ default: 'no',
+ tip: 'To opt out, leave this box unticked. Your store remains untracked, and no data will be collected. Read about what usage data is tracked at:
WooCommerce.com Usage Tracking Documentation.',
+ value: 'no',
+ } ),
+ ] )
+ );
+ } else {
+ // Test is failing on external hosts
+ }
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_show_marketplace_suggestions',
+ label: 'Show Suggestions',
+ description:
+ 'Display suggestions within WooCommerce',
type: 'checkbox',
- default: 'no',
- tip: 'To opt out, leave this box unticked. Your store remains untracked, and no data will be collected. Read about what usage data is tracked at:
WooCommerce.com Usage Tracking Documentation.',
- value: 'no',
+ default: 'yes',
+ tip: 'Leave this box unchecked if you do not want to pull suggested extensions from WooCommerce.com. You will see a static list of extensions instead.',
+ value: 'yes',
} ),
] )
);
- } else {
- // Test is failing on external hosts
- }
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_show_marketplace_suggestions',
- label: 'Show Suggestions',
- description: 'Display suggestions within WooCommerce',
- type: 'checkbox',
- default: 'yes',
- tip: 'Leave this box unchecked if you do not want to pull suggested extensions from WooCommerce.com. You will see a static list of extensions instead.',
- value: 'yes',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'woocommerce_analytics_enabled',
- label: 'Analytics',
- description: 'Enable WooCommerce Analytics',
- type: 'checkbox',
- default: 'yes',
- value: 'yes',
- } ),
- ] )
- );
- } );
- } );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'woocommerce_analytics_enabled',
+ label: 'Analytics',
+ description: 'Enable WooCommerce Analytics',
+ type: 'checkbox',
+ default: 'yes',
+ value: 'yes',
+ } ),
+ ] )
+ );
+ } );
+ }
+ );
test.describe( 'List all Email New Order settings', () => {
test( 'can retrieve all email new order settings', async ( {
@@ -1930,7 +1945,7 @@ test.describe.serial( 'Settings API tests: CRUD', () => {
tip: expect.stringContaining(
'Enter recipients (comma separated) for this email. Defaults to'
),
- value: '',
+ value: expect.any( String ),
} ),
] )
);
@@ -1998,107 +2013,110 @@ test.describe.serial( 'Settings API tests: CRUD', () => {
} );
test.describe( 'List all Email Failed Order settings', () => {
- test( 'can retrieve all email failed order settings', async ( {
- request,
- } ) => {
- // call API to retrieve all settings options
- const response = await request.get(
- '/wp-json/wc/v3/settings/email_failed_order'
- );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
- expect( Array.isArray( responseJSON ) ).toBe( true );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'enabled',
- label: 'Enable/Disable',
- description: '',
- type: 'checkbox',
- default: 'yes',
- value: 'yes',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'recipient',
- label: 'Recipient(s)',
- description: expect.stringContaining(
- 'Enter recipients (comma separated) for this email. Defaults to'
- ),
- type: 'text',
- default: '',
- tip: expect.stringContaining(
- 'Enter recipients (comma separated) for this email. Defaults to'
- ),
- value: '',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'subject',
- label: 'Subject',
- description:
- 'Available placeholders:
{site_title}</code>, <code>{site_address}</code>, <code>{site_url}</code>, <code>{order_date}</code>, <code>{order_number}
',
- type: 'text',
- default: '',
- tip: 'Available placeholders:
{site_title}</code>, <code>{site_address}</code>, <code>{site_url}</code>, <code>{order_date}</code>, <code>{order_number}
',
- value: '',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'heading',
- label: 'Email heading',
- description:
- 'Available placeholders:
{site_title}</code>, <code>{site_address}</code>, <code>{site_url}</code>, <code>{order_date}</code>, <code>{order_number}
',
- type: 'text',
- default: '',
- tip: 'Available placeholders:
{site_title}</code>, <code>{site_address}</code>, <code>{site_url}</code>, <code>{order_date}</code>, <code>{order_number}
',
- value: '',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'additional_content',
- label: 'Additional content',
- description:
- 'Text to appear below the main email content. Available placeholders:
{site_title}</code>, <code>{site_address}</code>, <code>{site_url}</code>, <code>{order_date}</code>, <code>{order_number}
',
- type: 'textarea',
- default:
- 'Hopefully they’ll be back. Read more about
troubleshooting failed payments.',
- tip: 'Text to appear below the main email content. Available placeholders:
{site_title}</code>, <code>{site_address}</code>, <code>{site_url}</code>, <code>{order_date}</code>, <code>{order_number}
',
- value: 'Hopefully they’ll be back. Read more about
troubleshooting failed payments.',
- } ),
- ] )
- );
- expect( responseJSON ).toEqual(
- expect.arrayContaining( [
- expect.objectContaining( {
- id: 'email_type',
- label: 'Email type',
- description: 'Choose which format of email to send.',
- type: 'select',
- default: 'html',
- options: {
- plain: 'Plain text',
- html: 'HTML',
- multipart: 'Multipart',
- },
- tip: 'Choose which format of email to send.',
- value: 'html',
- } ),
- ] )
- );
- } );
+ test(
+ 'can retrieve all email failed order settings',
+ { tag: '@skip-on-default-pressable' },
+ async ( { request } ) => {
+ // call API to retrieve all settings options
+ const response = await request.get(
+ '/wp-json/wc/v3/settings/email_failed_order'
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+ expect( Array.isArray( responseJSON ) ).toBe( true );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'enabled',
+ label: 'Enable/Disable',
+ description: '',
+ type: 'checkbox',
+ default: 'yes',
+ value: 'yes',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'recipient',
+ label: 'Recipient(s)',
+ description: expect.stringContaining(
+ 'Enter recipients (comma separated) for this email. Defaults to'
+ ),
+ type: 'text',
+ default: '',
+ tip: expect.stringContaining(
+ 'Enter recipients (comma separated) for this email. Defaults to'
+ ),
+ value: '',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'subject',
+ label: 'Subject',
+ description:
+ 'Available placeholders:
{site_title}</code>, <code>{site_address}</code>, <code>{site_url}</code>, <code>{order_date}</code>, <code>{order_number}
',
+ type: 'text',
+ default: '',
+ tip: 'Available placeholders:
{site_title}</code>, <code>{site_address}</code>, <code>{site_url}</code>, <code>{order_date}</code>, <code>{order_number}
',
+ value: '',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'heading',
+ label: 'Email heading',
+ description:
+ 'Available placeholders:
{site_title}</code>, <code>{site_address}</code>, <code>{site_url}</code>, <code>{order_date}</code>, <code>{order_number}
',
+ type: 'text',
+ default: '',
+ tip: 'Available placeholders:
{site_title}</code>, <code>{site_address}</code>, <code>{site_url}</code>, <code>{order_date}</code>, <code>{order_number}
',
+ value: '',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'additional_content',
+ label: 'Additional content',
+ description:
+ 'Text to appear below the main email content. Available placeholders:
{site_title}</code>, <code>{site_address}</code>, <code>{site_url}</code>, <code>{order_date}</code>, <code>{order_number}
',
+ type: 'textarea',
+ default:
+ 'Hopefully they’ll be back. Read more about
troubleshooting failed payments.',
+ tip: 'Text to appear below the main email content. Available placeholders:
{site_title}</code>, <code>{site_address}</code>, <code>{site_url}</code>, <code>{order_date}</code>, <code>{order_number}
',
+ value: 'Hopefully they’ll be back. Read more about
troubleshooting failed payments.',
+ } ),
+ ] )
+ );
+ expect( responseJSON ).toEqual(
+ expect.arrayContaining( [
+ expect.objectContaining( {
+ id: 'email_type',
+ label: 'Email type',
+ description:
+ 'Choose which format of email to send.',
+ type: 'select',
+ default: 'html',
+ options: {
+ plain: 'Plain text',
+ html: 'HTML',
+ multipart: 'Multipart',
+ },
+ tip: 'Choose which format of email to send.',
+ value: 'html',
+ } ),
+ ] )
+ );
+ }
+ );
} );
test.describe( 'List all Email Customer On Hold Order settings', () => {
diff --git a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/system-status/system-status-crud.test.js b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/system-status/system-status-crud.test.js
index 65d56a07196..005c48a99cd 100644
--- a/plugins/woocommerce/tests/e2e-pw/tests/api-tests/system-status/system-status-crud.test.js
+++ b/plugins/woocommerce/tests/e2e-pw/tests/api-tests/system-status/system-status-crud.test.js
@@ -3,582 +3,590 @@ const { BASE_URL } = process.env;
const shouldSkip = BASE_URL !== undefined && ! BASE_URL.includes( 'localhost' );
test.describe( 'System Status API tests', () => {
- test( 'can view all system status items', async ( { request } ) => {
- // call API to view all system status items
- const response = await request.get( '/wp-json/wc/v3/system_status' );
- const responseJSON = await response.json();
- expect( response.status() ).toEqual( 200 );
+ test(
+ 'can view all system status items',
+ { tag: '@skip-on-default-wpcom' },
+ async ( { request } ) => {
+ // call API to view all system status items
+ const response = await request.get(
+ '/wp-json/wc/v3/system_status'
+ );
+ const responseJSON = await response.json();
+ expect( response.status() ).toEqual( 200 );
+
+ // local environment differs from external hosts. Local listed first.
+ // eslint-disable-next-line playwright/no-conditional-in-test
+ if ( ! shouldSkip ) {
+ expect( responseJSON ).toEqual(
+ expect.objectContaining( {
+ environment: expect.objectContaining( {
+ home_url: expect.any( String ),
+ site_url: expect.any( String ),
+ version: expect.any( String ),
+ log_directory: expect.any( String ),
+ log_directory_writable: expect.any( Boolean ),
+ wp_version: expect.any( String ),
+ wp_multisite: expect.any( Boolean ),
+ wp_memory_limit: expect.any( Number ),
+ wp_debug_mode: expect.any( Boolean ),
+ wp_cron: expect.any( Boolean ),
+ language: expect.any( String ),
+ external_object_cache: null,
+ server_info: expect.any( String ),
+ php_version: expect.any( String ),
+ php_post_max_size: expect.any( Number ),
+ php_max_execution_time: expect.any( Number ),
+ php_max_input_vars: expect.any( Number ),
+ curl_version: expect.any( String ),
+ suhosin_installed: expect.any( Boolean ),
+ max_upload_size: expect.any( Number ),
+ mysql_version: expect.any( String ),
+ mysql_version_string: expect.any( String ),
+ default_timezone: expect.any( String ),
+ fsockopen_or_curl_enabled: expect.any( Boolean ),
+ soapclient_enabled: expect.any( Boolean ),
+ domdocument_enabled: expect.any( Boolean ),
+ gzip_enabled: expect.any( Boolean ),
+ mbstring_enabled: expect.any( Boolean ),
+ remote_post_successful: expect.any( Boolean ),
+ remote_post_response: expect.any( String ),
+ remote_get_successful: expect.any( Boolean ),
+ remote_get_response: expect.any( String ),
+ } ),
+ } )
+ );
+ } else {
+ expect( responseJSON ).toEqual(
+ expect.objectContaining( {
+ environment: expect.objectContaining( {
+ home_url: expect.any( String ),
+ site_url: expect.any( String ),
+ version: expect.any( String ),
+ log_directory: expect.any( String ),
+ log_directory_writable: expect.any( Boolean ),
+ wp_version: expect.any( String ),
+ wp_multisite: expect.any( Boolean ),
+ wp_memory_limit: expect.any( Number ),
+ wp_debug_mode: expect.any( Boolean ),
+ wp_cron: expect.any( Boolean ),
+ language: expect.any( String ),
+ external_object_cache: expect.any( Boolean ),
+ server_info: expect.any( String ),
+ php_version: expect.any( String ),
+ php_post_max_size: expect.any( Number ),
+ php_max_execution_time: expect.any( Number ),
+ php_max_input_vars: expect.any( Number ),
+ curl_version: expect.any( String ),
+ suhosin_installed: expect.any( Boolean ),
+ max_upload_size: expect.any( Number ),
+ mysql_version: expect.any( String ),
+ mysql_version_string: expect.any( String ),
+ default_timezone: expect.any( String ),
+ fsockopen_or_curl_enabled: expect.any( Boolean ),
+ soapclient_enabled: expect.any( Boolean ),
+ domdocument_enabled: expect.any( Boolean ),
+ gzip_enabled: expect.any( Boolean ),
+ mbstring_enabled: expect.any( Boolean ),
+ remote_post_successful: expect.any( Boolean ),
+ remote_post_response: expect.any( Number ),
+ remote_get_successful: expect.any( Boolean ),
+ remote_get_response: expect.any( Number ),
+ } ),
+ } )
+ );
+ }
- // local environment differs from external hosts. Local listed first.
- // eslint-disable-next-line playwright/no-conditional-in-test
- if ( ! shouldSkip ) {
expect( responseJSON ).toEqual(
expect.objectContaining( {
- environment: expect.objectContaining( {
- home_url: expect.any( String ),
- site_url: expect.any( String ),
- version: expect.any( String ),
- log_directory: expect.any( String ),
- log_directory_writable: expect.any( Boolean ),
- wp_version: expect.any( String ),
- wp_multisite: expect.any( Boolean ),
- wp_memory_limit: expect.any( Number ),
- wp_debug_mode: expect.any( Boolean ),
- wp_cron: expect.any( Boolean ),
- language: expect.any( String ),
- external_object_cache: null,
- server_info: expect.any( String ),
- php_version: expect.any( String ),
- php_post_max_size: expect.any( Number ),
- php_max_execution_time: expect.any( Number ),
- php_max_input_vars: expect.any( Number ),
- curl_version: expect.any( String ),
- suhosin_installed: expect.any( Boolean ),
- max_upload_size: expect.any( Number ),
- mysql_version: expect.any( String ),
- mysql_version_string: expect.any( String ),
- default_timezone: expect.any( String ),
- fsockopen_or_curl_enabled: expect.any( Boolean ),
- soapclient_enabled: expect.any( Boolean ),
- domdocument_enabled: expect.any( Boolean ),
- gzip_enabled: expect.any( Boolean ),
- mbstring_enabled: expect.any( Boolean ),
- remote_post_successful: expect.any( Boolean ),
- remote_post_response: expect.any( String ),
- remote_get_successful: expect.any( Boolean ),
- remote_get_response: expect.any( String ),
- } ),
- } )
- );
- } else {
- expect( responseJSON ).toEqual(
- expect.objectContaining( {
- environment: expect.objectContaining( {
- home_url: expect.any( String ),
- site_url: expect.any( String ),
- version: expect.any( String ),
- log_directory: expect.any( String ),
- log_directory_writable: expect.any( Boolean ),
- wp_version: expect.any( String ),
- wp_multisite: expect.any( Boolean ),
- wp_memory_limit: expect.any( Number ),
- wp_debug_mode: expect.any( Boolean ),
- wp_cron: expect.any( Boolean ),
- language: expect.any( String ),
- external_object_cache: expect.any( Boolean ),
- server_info: expect.any( String ),
- php_version: expect.any( String ),
- php_post_max_size: expect.any( Number ),
- php_max_execution_time: expect.any( Number ),
- php_max_input_vars: expect.any( Number ),
- curl_version: expect.any( String ),
- suhosin_installed: expect.any( Boolean ),
- max_upload_size: expect.any( Number ),
- mysql_version: expect.any( String ),
- mysql_version_string: expect.any( String ),
- default_timezone: expect.any( String ),
- fsockopen_or_curl_enabled: expect.any( Boolean ),
- soapclient_enabled: expect.any( Boolean ),
- domdocument_enabled: expect.any( Boolean ),
- gzip_enabled: expect.any( Boolean ),
- mbstring_enabled: expect.any( Boolean ),
- remote_post_successful: expect.any( Boolean ),
- remote_post_response: expect.any( Number ),
- remote_get_successful: expect.any( Boolean ),
- remote_get_response: expect.any( Number ),
- } ),
- } )
- );
- }
-
- expect( responseJSON ).toEqual(
- expect.objectContaining( {
- database: expect.objectContaining( {
- wc_database_version: expect.any( String ),
- database_prefix: expect.any( String ),
- maxmind_geoip_database: expect.any( String ),
- database_tables: expect.objectContaining( {
- woocommerce: expect.objectContaining( {
- wp_woocommerce_sessions: expect.objectContaining( {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- } ),
- wp_woocommerce_api_keys: expect.objectContaining( {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- } ),
- wp_woocommerce_attribute_taxonomies:
- expect.objectContaining( {
+ database: expect.objectContaining( {
+ wc_database_version: expect.any( String ),
+ database_prefix: expect.any( String ),
+ maxmind_geoip_database: expect.any( String ),
+ database_tables: expect.objectContaining( {
+ woocommerce: expect.objectContaining( {
+ wp_woocommerce_sessions:
+ expect.objectContaining( {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ } ),
+ wp_woocommerce_api_keys:
+ expect.objectContaining( {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ } ),
+ wp_woocommerce_attribute_taxonomies:
+ expect.objectContaining( {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ } ),
+ wp_woocommerce_downloadable_product_permissions:
+ expect.objectContaining( {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ } ),
+ wp_woocommerce_order_items:
+ expect.objectContaining( {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ } ),
+ wp_woocommerce_order_itemmeta:
+ expect.objectContaining( {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ } ),
+ wp_woocommerce_tax_rates:
+ expect.objectContaining( {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ } ),
+ wp_woocommerce_tax_rate_locations:
+ expect.objectContaining( {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ } ),
+ wp_woocommerce_shipping_zones:
+ expect.objectContaining( {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ } ),
+ wp_woocommerce_shipping_zone_locations:
+ expect.objectContaining( {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ } ),
+ wp_woocommerce_shipping_zone_methods:
+ expect.objectContaining( {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ } ),
+ wp_woocommerce_payment_tokens:
+ expect.objectContaining( {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ } ),
+ wp_woocommerce_payment_tokenmeta:
+ expect.objectContaining( {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ } ),
+ wp_woocommerce_log: expect.objectContaining( {
data: expect.any( String ),
index: expect.any( String ),
engine: expect.any( String ),
} ),
- wp_woocommerce_downloadable_product_permissions:
- expect.objectContaining( {
+ } ),
+ other: expect.objectContaining( {
+ wp_actionscheduler_actions: {
data: expect.any( String ),
index: expect.any( String ),
engine: expect.any( String ),
- } ),
- wp_woocommerce_order_items: expect.objectContaining(
+ },
+ wp_actionscheduler_claims: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_actionscheduler_groups: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_actionscheduler_logs: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_commentmeta: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_comments: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_links: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_options: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_postmeta: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_posts: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_termmeta: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_terms: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_term_relationships: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_term_taxonomy: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_usermeta: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_users: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_admin_notes: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_admin_note_actions: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_category_lookup: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_customer_lookup: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_download_log: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_order_coupon_lookup: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_order_product_lookup: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_order_stats: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_order_tax_lookup: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_product_attributes_lookup: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_product_download_directories: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_product_meta_lookup: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_rate_limits: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_reserved_stock: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_tax_rate_classes: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ wp_wc_webhooks: {
+ data: expect.any( String ),
+ index: expect.any( String ),
+ engine: expect.any( String ),
+ },
+ } ),
+ } ),
+ database_size: {
+ data: expect.any( Number ),
+ index: expect.any( Number ),
+ },
+ } ),
+ } )
+ );
+
+ expect( responseJSON ).toEqual(
+ expect.objectContaining( {
+ active_plugins: expect.arrayContaining( [
+ {
+ plugin: expect.any( String ),
+ name: expect.any( String ),
+ version: expect.any( String ),
+ version_latest: expect.any( String ),
+ url: expect.any( String ),
+ author_name: expect.any( String ),
+ author_url: expect.any( String ),
+ network_activated: expect.any( Boolean ),
+ },
+ {
+ plugin: expect.any( String ),
+ name: expect.any( String ),
+ version: expect.any( String ),
+ version_latest: expect.any( String ),
+ url: expect.any( String ),
+ author_name: expect.any( String ),
+ author_url: expect.any( String ),
+ network_activated: expect.any( Boolean ),
+ },
+ {
+ plugin: expect.any( String ),
+ name: expect.any( String ),
+ version: expect.any( String ),
+ version_latest: expect.any( String ),
+ url: expect.any( String ),
+ author_name: expect.any( String ),
+ author_url: expect.any( String ),
+ network_activated: expect.any( Boolean ),
+ },
+ {
+ plugin: expect.any( String ),
+ name: expect.any( String ),
+ version: expect.any( String ),
+ version_latest: expect.any( String ),
+ url: expect.any( String ),
+ author_name: expect.any( String ),
+ author_url: expect.any( String ),
+ network_activated: expect.any( Boolean ),
+ },
+ ] ),
+ } )
+ );
+
+ // local environment differs from external hosts. Local listed first.
+ // eslint-disable-next-line playwright/no-conditional-in-test
+ if ( ! shouldSkip ) {
+ expect( responseJSON ).toEqual(
+ expect.objectContaining( {
+ dropins_mu_plugins: expect.objectContaining( {
+ dropins: expect.arrayContaining( [] ),
+ mu_plugins: expect.arrayContaining( [] ),
+ } ),
+ } )
+ );
+ } else {
+ expect( responseJSON ).toEqual(
+ expect.objectContaining( {
+ dropins_mu_plugins: expect.objectContaining( {
+ dropins: expect.arrayContaining( [
{
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- }
- ),
- wp_woocommerce_order_itemmeta:
- expect.objectContaining( {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- } ),
- wp_woocommerce_tax_rates: expect.objectContaining( {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- } ),
- wp_woocommerce_tax_rate_locations:
- expect.objectContaining( {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- } ),
- wp_woocommerce_shipping_zones:
- expect.objectContaining( {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- } ),
- wp_woocommerce_shipping_zone_locations:
- expect.objectContaining( {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- } ),
- wp_woocommerce_shipping_zone_methods:
- expect.objectContaining( {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- } ),
- wp_woocommerce_payment_tokens:
- expect.objectContaining( {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- } ),
- wp_woocommerce_payment_tokenmeta:
- expect.objectContaining( {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- } ),
- wp_woocommerce_log: expect.objectContaining( {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- } ),
+ name: expect.any( String ),
+ plugin: expect.any( String ),
+ },
+ {
+ name: expect.any( String ),
+ plugin: expect.any( String ),
+ },
+ ] ),
+ mu_plugins: [],
} ),
- other: expect.objectContaining( {
- wp_actionscheduler_actions: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_actionscheduler_claims: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_actionscheduler_groups: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_actionscheduler_logs: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_commentmeta: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_comments: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_links: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_options: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_postmeta: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_posts: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_termmeta: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_terms: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_term_relationships: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_term_taxonomy: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_usermeta: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_users: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_admin_notes: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_admin_note_actions: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_category_lookup: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_customer_lookup: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_download_log: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_order_coupon_lookup: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_order_product_lookup: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_order_stats: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_order_tax_lookup: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_product_attributes_lookup: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_product_download_directories: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_product_meta_lookup: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_rate_limits: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_reserved_stock: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_tax_rate_classes: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- wp_wc_webhooks: {
- data: expect.any( String ),
- index: expect.any( String ),
- engine: expect.any( String ),
- },
- } ),
- } ),
- database_size: {
- data: expect.any( Number ),
- index: expect.any( Number ),
- },
- } ),
- } )
- );
-
- expect( responseJSON ).toEqual(
- expect.objectContaining( {
- active_plugins: expect.arrayContaining( [
- {
- plugin: expect.any( String ),
- name: expect.any( String ),
- version: expect.any( String ),
- version_latest: expect.any( String ),
- url: expect.any( String ),
- author_name: expect.any( String ),
- author_url: expect.any( String ),
- network_activated: expect.any( Boolean ),
- },
- {
- plugin: expect.any( String ),
- name: expect.any( String ),
- version: expect.any( String ),
- version_latest: expect.any( String ),
- url: expect.any( String ),
- author_name: expect.any( String ),
- author_url: expect.any( String ),
- network_activated: expect.any( Boolean ),
- },
- {
- plugin: expect.any( String ),
- name: expect.any( String ),
- version: expect.any( String ),
- version_latest: expect.any( String ),
- url: expect.any( String ),
- author_name: expect.any( String ),
- author_url: expect.any( String ),
- network_activated: expect.any( Boolean ),
- },
- {
- plugin: expect.any( String ),
- name: expect.any( String ),
- version: expect.any( String ),
- version_latest: expect.any( String ),
- url: expect.any( String ),
- author_name: expect.any( String ),
- author_url: expect.any( String ),
- network_activated: expect.any( Boolean ),
- },
- ] ),
- } )
- );
-
- // local environment differs from external hosts. Local listed first.
- // eslint-disable-next-line playwright/no-conditional-in-test
- if ( ! shouldSkip ) {
+ } )
+ );
+ }
expect( responseJSON ).toEqual(
expect.objectContaining( {
- dropins_mu_plugins: expect.objectContaining( {
- dropins: expect.arrayContaining( [] ),
- mu_plugins: expect.arrayContaining( [] ),
+ theme: expect.objectContaining( {
+ name: expect.any( String ),
+ version: expect.any( String ),
+ version_latest: expect.any( String ),
+ author_url: expect.any( String ),
+ is_child_theme: expect.any( Boolean ),
+ has_woocommerce_support: expect.any( Boolean ),
+ has_woocommerce_file: expect.any( Boolean ),
+ has_outdated_templates: expect.any( Boolean ),
+ overrides: expect.any( Array ),
+ parent_name: expect.any( String ),
+ parent_version: expect.any( String ),
+ parent_version_latest: expect.any( String ),
+ parent_author_url: expect.any( String ),
} ),
} )
);
- } else {
expect( responseJSON ).toEqual(
expect.objectContaining( {
- dropins_mu_plugins: expect.objectContaining( {
- dropins: expect.arrayContaining( [
- {
- name: expect.any( String ),
- plugin: expect.any( String ),
- },
- {
- name: expect.any( String ),
- plugin: expect.any( String ),
- },
- ] ),
- mu_plugins: [],
+ settings: expect.objectContaining( {
+ api_enabled: expect.any( Boolean ),
+ force_ssl: expect.any( Boolean ),
+ currency: expect.any( String ),
+ currency_symbol: expect.any( String ),
+ currency_position: expect.any( String ),
+ thousand_separator: expect.any( String ),
+ decimal_separator: expect.any( String ),
+ number_of_decimals: expect.any( Number ),
+ geolocation_enabled: expect.any( Boolean ),
+ taxonomies: {
+ external: expect.any( String ),
+ grouped: expect.any( String ),
+ simple: expect.any( String ),
+ variable: expect.any( String ),
+ },
+ product_visibility_terms: {
+ 'exclude-from-catalog': expect.any( String ),
+ 'exclude-from-search': expect.any( String ),
+ featured: expect.any( String ),
+ outofstock: expect.any( String ),
+ 'rated-1': expect.any( String ),
+ 'rated-2': expect.any( String ),
+ 'rated-3': expect.any( String ),
+ 'rated-4': expect.any( String ),
+ 'rated-5': expect.any( String ),
+ },
+ woocommerce_com_connected: expect.any( String ),
} ),
} )
);
+ expect( responseJSON ).toEqual(
+ expect.objectContaining( {
+ security: expect.objectContaining( {
+ secure_connection: expect.any( Boolean ),
+ hide_errors: expect.any( Boolean ),
+ } ),
+ } )
+ );
+ expect( responseJSON ).toEqual(
+ expect.objectContaining( {
+ pages: expect.arrayContaining( [
+ {
+ page_name: expect.any( String ),
+ page_id: expect.any( String ),
+ page_set: expect.any( Boolean ),
+ page_exists: expect.any( Boolean ),
+ page_visible: expect.any( Boolean ),
+ shortcode: expect.any( String ),
+ block: expect.any( String ),
+ shortcode_required: expect.any( Boolean ),
+ shortcode_present: expect.any( Boolean ),
+ block_present: expect.any( Boolean ),
+ block_required: expect.any( Boolean ),
+ },
+ {
+ page_name: expect.any( String ),
+ page_id: expect.any( String ),
+ page_set: expect.any( Boolean ),
+ page_exists: expect.any( Boolean ),
+ page_visible: expect.any( Boolean ),
+ shortcode: expect.any( String ),
+ block: expect.any( String ),
+ shortcode_required: expect.any( Boolean ),
+ shortcode_present: expect.any( Boolean ),
+ block_present: expect.any( Boolean ),
+ block_required: expect.any( Boolean ),
+ },
+ {
+ page_name: expect.any( String ),
+ page_id: expect.any( String ),
+ page_set: expect.any( Boolean ),
+ page_exists: expect.any( Boolean ),
+ page_visible: expect.any( Boolean ),
+ shortcode: expect.any( String ),
+ block: expect.any( String ),
+ shortcode_required: expect.any( Boolean ),
+ shortcode_present: expect.any( Boolean ),
+ block_present: expect.any( Boolean ),
+ block_required: expect.any( Boolean ),
+ },
+ {
+ page_name: expect.any( String ),
+ page_id: expect.any( String ),
+ page_set: expect.any( Boolean ),
+ page_exists: expect.any( Boolean ),
+ page_visible: expect.any( Boolean ),
+ shortcode: expect.any( String ),
+ block: expect.any( String ),
+ shortcode_required: expect.any( Boolean ),
+ shortcode_present: expect.any( Boolean ),
+ block_present: expect.any( Boolean ),
+ block_required: expect.any( Boolean ),
+ },
+ {
+ page_name: expect.any( String ),
+ page_id: expect.any( String ),
+ page_set: expect.any( Boolean ),
+ page_exists: expect.any( Boolean ),
+ page_visible: expect.any( Boolean ),
+ shortcode: expect.any( String ),
+ block: expect.any( String ),
+ shortcode_required: expect.any( Boolean ),
+ shortcode_present: expect.any( Boolean ),
+ block_present: expect.any( Boolean ),
+ block_required: expect.any( Boolean ),
+ },
+ ] ),
+ } )
+ );
+ expect( responseJSON ).toEqual(
+ expect.objectContaining( {
+ post_type_counts: expect.arrayContaining( [
+ {
+ type: expect.any( String ),
+ count: expect.any( String ),
+ },
+ {
+ type: expect.any( String ),
+ count: expect.any( String ),
+ },
+ {
+ type: expect.any( String ),
+ count: expect.any( String ),
+ },
+ ] ),
+ } )
+ );
}
- expect( responseJSON ).toEqual(
- expect.objectContaining( {
- theme: expect.objectContaining( {
- name: expect.any( String ),
- version: expect.any( String ),
- version_latest: expect.any( String ),
- author_url: expect.any( String ),
- is_child_theme: expect.any( Boolean ),
- has_woocommerce_support: expect.any( Boolean ),
- has_woocommerce_file: expect.any( Boolean ),
- has_outdated_templates: expect.any( Boolean ),
- overrides: expect.any( Array ),
- parent_name: expect.any( String ),
- parent_version: expect.any( String ),
- parent_version_latest: expect.any( String ),
- parent_author_url: expect.any( String ),
- } ),
- } )
- );
- expect( responseJSON ).toEqual(
- expect.objectContaining( {
- settings: expect.objectContaining( {
- api_enabled: expect.any( Boolean ),
- force_ssl: expect.any( Boolean ),
- currency: expect.any( String ),
- currency_symbol: expect.any( String ),
- currency_position: expect.any( String ),
- thousand_separator: expect.any( String ),
- decimal_separator: expect.any( String ),
- number_of_decimals: expect.any( Number ),
- geolocation_enabled: expect.any( Boolean ),
- taxonomies: {
- external: expect.any( String ),
- grouped: expect.any( String ),
- simple: expect.any( String ),
- variable: expect.any( String ),
- },
- product_visibility_terms: {
- 'exclude-from-catalog': expect.any( String ),
- 'exclude-from-search': expect.any( String ),
- featured: expect.any( String ),
- outofstock: expect.any( String ),
- 'rated-1': expect.any( String ),
- 'rated-2': expect.any( String ),
- 'rated-3': expect.any( String ),
- 'rated-4': expect.any( String ),
- 'rated-5': expect.any( String ),
- },
- woocommerce_com_connected: expect.any( String ),
- } ),
- } )
- );
- expect( responseJSON ).toEqual(
- expect.objectContaining( {
- security: expect.objectContaining( {
- secure_connection: expect.any( Boolean ),
- hide_errors: expect.any( Boolean ),
- } ),
- } )
- );
- expect( responseJSON ).toEqual(
- expect.objectContaining( {
- pages: expect.arrayContaining( [
- {
- page_name: expect.any( String ),
- page_id: expect.any( String ),
- page_set: expect.any( Boolean ),
- page_exists: expect.any( Boolean ),
- page_visible: expect.any( Boolean ),
- shortcode: expect.any( String ),
- block: expect.any( String ),
- shortcode_required: expect.any( Boolean ),
- shortcode_present: expect.any( Boolean ),
- block_present: expect.any( Boolean ),
- block_required: expect.any( Boolean ),
- },
- {
- page_name: expect.any( String ),
- page_id: expect.any( String ),
- page_set: expect.any( Boolean ),
- page_exists: expect.any( Boolean ),
- page_visible: expect.any( Boolean ),
- shortcode: expect.any( String ),
- block: expect.any( String ),
- shortcode_required: expect.any( Boolean ),
- shortcode_present: expect.any( Boolean ),
- block_present: expect.any( Boolean ),
- block_required: expect.any( Boolean ),
- },
- {
- page_name: expect.any( String ),
- page_id: expect.any( String ),
- page_set: expect.any( Boolean ),
- page_exists: expect.any( Boolean ),
- page_visible: expect.any( Boolean ),
- shortcode: expect.any( String ),
- block: expect.any( String ),
- shortcode_required: expect.any( Boolean ),
- shortcode_present: expect.any( Boolean ),
- block_present: expect.any( Boolean ),
- block_required: expect.any( Boolean ),
- },
- {
- page_name: expect.any( String ),
- page_id: expect.any( String ),
- page_set: expect.any( Boolean ),
- page_exists: expect.any( Boolean ),
- page_visible: expect.any( Boolean ),
- shortcode: expect.any( String ),
- block: expect.any( String ),
- shortcode_required: expect.any( Boolean ),
- shortcode_present: expect.any( Boolean ),
- block_present: expect.any( Boolean ),
- block_required: expect.any( Boolean ),
- },
- {
- page_name: expect.any( String ),
- page_id: expect.any( String ),
- page_set: expect.any( Boolean ),
- page_exists: expect.any( Boolean ),
- page_visible: expect.any( Boolean ),
- shortcode: expect.any( String ),
- block: expect.any( String ),
- shortcode_required: expect.any( Boolean ),
- shortcode_present: expect.any( Boolean ),
- block_present: expect.any( Boolean ),
- block_required: expect.any( Boolean ),
- },
- ] ),
- } )
- );
- expect( responseJSON ).toEqual(
- expect.objectContaining( {
- post_type_counts: expect.arrayContaining( [
- {
- type: expect.any( String ),
- count: expect.any( String ),
- },
- {
- type: expect.any( String ),
- count: expect.any( String ),
- },
- {
- type: expect.any( String ),
- count: expect.any( String ),
- },
- ] ),
- } )
- );
- } );
+ );
test( 'can view all system status tools', async ( { request } ) => {
// call API to view system status tools
diff --git a/plugins/woocommerce/tests/e2e-pw/tests/merchant/product-import-csv.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/merchant/product-import-csv.spec.js
index 103d50fd8f6..507568812a0 100644
--- a/plugins/woocommerce/tests/e2e-pw/tests/merchant/product-import-csv.spec.js
+++ b/plugins/woocommerce/tests/e2e-pw/tests/merchant/product-import-csv.spec.js
@@ -89,8 +89,7 @@ const productCategories = [
];
const productAttributes = [ 'Color', 'Size' ];
-const errorMessage =
- 'Invalid file type. The importer supports CSV and TXT file formats.';
+const errorMessage = 'File is empty. Please upload something more substantial.';
test.describe.serial(
'Import Products from a CSV file',
diff --git a/plugins/woocommerce/tests/legacy/framework/helpers/class-wc-helper-admin-notes.php b/plugins/woocommerce/tests/legacy/framework/helpers/class-wc-helper-admin-notes.php
index 66f12f2a352..247d3c5fa84 100644
--- a/plugins/woocommerce/tests/legacy/framework/helpers/class-wc-helper-admin-notes.php
+++ b/plugins/woocommerce/tests/legacy/framework/helpers/class-wc-helper-admin-notes.php
@@ -60,7 +60,7 @@ class WC_Helper_Admin_Notes {
$note_2->set_source( 'PHPUNIT_TEST' );
$note_2->set_status( Note::E_WC_ADMIN_NOTE_ACTIONED );
$note_2->set_is_snoozable( true );
- $note_2->set_layout( 'banner' );
+ $note_2->set_layout( 'thumbnail' );
$note_2->set_image( 'https://an-image.jpg' );
// This note has no actions.
$note_2->save();
@@ -100,7 +100,6 @@ class WC_Helper_Admin_Notes {
'?s=PHPUNIT_TEST_NOTE_4_ACTION_2_URL'
);
$note_4->save();
-
}
/**
diff --git a/plugins/woocommerce/tests/legacy/framework/helpers/class-wc-helper-queue.php b/plugins/woocommerce/tests/legacy/framework/helpers/class-wc-helper-queue.php
index a2f4e0acfb8..50f3c8766a4 100644
--- a/plugins/woocommerce/tests/legacy/framework/helpers/class-wc-helper-queue.php
+++ b/plugins/woocommerce/tests/legacy/framework/helpers/class-wc-helper-queue.php
@@ -13,36 +13,42 @@
class WC_Helper_Queue {
/**
* Get all pending queued actions.
- *
+ * @param string|null $group Optionally. Filter the actions by group.
* @return array Pending jobs.
*/
- public static function get_all_pending() {
- $jobs = WC()->queue()->search(
- array(
- 'per_page' => -1,
- 'status' => 'pending',
- 'claimed' => false,
- )
+ public static function get_all_pending( $group = null ) {
+ $args = array(
+ 'per_page' => -1,
+ 'status' => 'pending',
+ 'claimed' => false,
);
- return $jobs;
+ if ( $group ) {
+ $args['group'] = $group;
+ }
+
+ return WC()->queue()->search( $args );
}
+
+
/**
* Run all pending queued actions.
- *
+ * @param string|null $group Optionally. Filter the actions by group.
* @return void
*/
- public static function run_all_pending() {
+ public static function run_all_pending( $group = null ) {
$queue_runner = new ActionScheduler_QueueRunner();
-
- while ( $jobs = self::get_all_pending() ) {
+ $jobs = self::get_all_pending( $group );
+ while ( $jobs ) {
foreach ( $jobs as $job_id => $job ) {
$queue_runner->process_action( $job_id );
}
+ $jobs = self::get_all_pending( $group );
}
}
+
/**
* Cancel all pending actions.
*
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/products-lowinstock.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/products-lowinstock.php
index b85177b3221..489a4d66fc9 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/products-lowinstock.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/products-lowinstock.php
@@ -51,7 +51,7 @@ class WC_Admin_Tests_API_ProductsLowInStock extends WC_REST_Unit_Test_Case {
$order->save();
// Sync analytics data (used for last order date).
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', '/wc-analytics/products/low-in-stock' );
$request->set_param( 'low_in_stock', true );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-categories.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-categories.php
index f5f37b9404d..7b704fc7b4a 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-categories.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-categories.php
@@ -66,7 +66,7 @@ class WC_Admin_Tests_API_Reports_Categories extends WC_REST_Unit_Test_Case {
$order->set_total( 100 ); // $25 x 4.
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$uncategorized_term = get_term_by( 'slug', 'uncategorized', 'product_cat' );
@@ -114,7 +114,7 @@ class WC_Admin_Tests_API_Reports_Categories extends WC_REST_Unit_Test_Case {
$product->set_category_ids( array( $second_category_id ) );
$product->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$uncategorized_term = get_term_by( 'slug', 'uncategorized', 'product_cat' );
@@ -170,7 +170,7 @@ class WC_Admin_Tests_API_Reports_Categories extends WC_REST_Unit_Test_Case {
$order->set_total( 100 ); // $25 x 4.
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Populate all of the data.
$product = new WC_Product_Simple();
@@ -186,7 +186,7 @@ class WC_Admin_Tests_API_Reports_Categories extends WC_REST_Unit_Test_Case {
$order->set_total( 400 ); // $100 x 4.
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$uncategorized_term = get_term_by( 'slug', 'uncategorized', 'product_cat' );
$params = array(
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-coupons-stats.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-coupons-stats.php
index 9ebdcb6db25..86de2a966a4 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-coupons-stats.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-coupons-stats.php
@@ -87,7 +87,7 @@ class WC_Admin_Tests_API_Reports_Coupons_Stats extends WC_REST_Unit_Test_Case {
$order_2c->set_date_created( $time );
$order_2c->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params(
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-coupons.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-coupons.php
index ee8d5271552..b085e3ee690 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-coupons.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-coupons.php
@@ -82,7 +82,7 @@ class WC_Admin_Tests_API_Reports_Coupons extends WC_REST_Unit_Test_Case {
$order_2c->calculate_totals();
$order_2c->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', $this->endpoint ) );
$coupon_reports = $response->get_data();
@@ -132,7 +132,7 @@ class WC_Admin_Tests_API_Reports_Coupons extends WC_REST_Unit_Test_Case {
$order_1c->calculate_totals();
$order_1c->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params(
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-customers-stats.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-customers-stats.php
index 6b2c479bf93..0cc1ccacdc7 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-customers-stats.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-customers-stats.php
@@ -127,7 +127,7 @@ class WC_Admin_Tests_API_Reports_Customers_Stats extends WC_REST_Unit_Test_Case
$order->set_total( 9.12 );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$response = $this->server->dispatch( $request );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-customers.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-customers.php
index 24a3af46ec5..166bf344918 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-customers.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-customers.php
@@ -149,7 +149,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$order->set_total( 100 );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params( array( 'per_page' => 10 ) );
@@ -164,7 +164,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
// Creating a customer should show up regardless of orders.
$customer = WC_Helper_Customer::create_customer( 'customer', 'password', 'customer@example.com' );
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params(
@@ -221,7 +221,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$order->set_total( 100 );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params(
@@ -317,7 +317,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$order->save();
// Ensure order customer data is synced to lookup table.
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$query_params = array(
'force_cache_refresh' => true,
@@ -400,7 +400,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$customer->set_billing_city( '' );
$customer->set_first_name( 'customer_andrei_1' );
$customer->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request->set_query_params(
array(
@@ -433,7 +433,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
// Test filter_empty param by state and postcode non empty.
$customer = WC_Helper_Customer::create_customer( 'customer_2', 'password', 'customer_2@example.com' );
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request->set_query_params(
array(
@@ -498,7 +498,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$order->set_total( 100 );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$response = $this->server->dispatch( $request );
@@ -527,7 +527,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$order->set_total( 100 );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$response = $this->server->dispatch( $request );
@@ -555,7 +555,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$order->set_total( 100 );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$response = $this->server->dispatch( $request );
@@ -584,7 +584,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
// Creating a customer should show up regardless of orders.
$customer = WC_Helper_Customer::create_customer( 'deleteme', 'password', 'deleteme@example.com' );
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params(
@@ -602,7 +602,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
// Delete the user associated with the customer.
wp_delete_user( $customer->get_id() );
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Verify they are gone.
$request = new WP_REST_Request( 'GET', $this->endpoint );
@@ -630,7 +630,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$order->set_total( 100 );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// update order info.
$order->set_billing_city( 'Random' );
@@ -638,11 +638,11 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$order->set_billing_postcode( '54321' );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$result = CustomersDataStore::sync_order_customer( $order->get_id() );
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$this->assertNotEquals( -1, $result );
@@ -671,7 +671,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$order2->set_total( 100 );
$order2->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$customer_id = CustomersDataStore::get_existing_customer_id_from_order( $order );
$customer2_id = CustomersDataStore::get_existing_customer_id_from_order( $order2 );
@@ -682,11 +682,11 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$order->set_billing_postcode( '54321' );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$result = CustomersDataStore::sync_order_customer( $order->get_id() );
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Didn't update anything.
$this->assertTrue( -1 === $result );
@@ -721,7 +721,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$order3->set_billing_email( 'different@example.org' );
$order3->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$customer_id = CustomersDataStore::get_existing_customer_id_from_order( $order );
$customer2_id = CustomersDataStore::get_existing_customer_id_from_order( $order2 );
@@ -734,11 +734,11 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$order3->set_billing_postcode( '54321' );
$order3->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$result = CustomersDataStore::sync_order_customer( $order3->get_id() );
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Didn't update anything.
$this->assertNotEquals( -1, $result );
@@ -780,7 +780,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$order3->set_total( 100 );
$order3->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$customer_id = CustomersDataStore::get_existing_customer_id_from_order( $order );
$customer2_id = CustomersDataStore::get_existing_customer_id_from_order( $order2 );
@@ -794,7 +794,7 @@ class WC_Admin_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
$order->set_date_created( time() + 60 );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$latest_order = CustomersDataStore::get_last_order( $customer_id );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-downloads-stats.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-downloads-stats.php
index 0e098e40b72..8a58da14e7b 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-downloads-stats.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-downloads-stats.php
@@ -152,7 +152,7 @@ class WC_Admin_Tests_API_Reports_Downloads_Stats extends WC_REST_Unit_Test_Case
$order->save();
$order_1 = $order->get_id();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$download = new WC_Customer_Download();
$download->set_user_id( 1 );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-downloads.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-downloads.php
index 3750eaba48c..98b10737888 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-downloads.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-downloads.php
@@ -169,7 +169,7 @@ class WC_Admin_Tests_API_Reports_Downloads extends WC_REST_Unit_Test_Case {
$object->set_timestamp( gmdate( 'Y-m-d H:00:00', $time - ( 2 * DAY_IN_SECONDS ) ) );
$id = $object->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
return array(
'time' => $time,
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-export.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-export.php
index 48494f8fcf0..faae1f452eb 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-export.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-export.php
@@ -119,7 +119,7 @@ class WC_Admin_Tests_API_Reports_Export extends WC_REST_Unit_Test_Case {
$order->calculate_totals();
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Initiate an export of the taxes report.
$response = $this->server->dispatch( new WP_REST_Request( 'POST', '/wc-analytics/reports/taxes/export' ) );
@@ -143,7 +143,7 @@ class WC_Admin_Tests_API_Reports_Export extends WC_REST_Unit_Test_Case {
$this->assertStringMatchesFormat( '%s/wc-analytics/reports/taxes/export/%d/status', $status['_links']['self'][0]['href'] );
// Run the pending export jobs.
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Check that the status shows 100% and includes a download url.
$response = $this->server->dispatch( new WP_REST_Request( 'GET', $status_route ) );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-import.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-import.php
index b40e02390ea..e9cd6edb762 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-import.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-import.php
@@ -119,7 +119,7 @@ class WC_Admin_Tests_API_Reports_Import extends WC_REST_Unit_Test_Case {
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 'success', $report['status'] );
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', '/wc-analytics/reports/customers' );
$response = $this->server->dispatch( $request );
@@ -161,7 +161,7 @@ class WC_Admin_Tests_API_Reports_Import extends WC_REST_Unit_Test_Case {
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 'success', $report['status'] );
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', '/wc-analytics/reports/customers' );
$response = $this->server->dispatch( $request );
@@ -247,7 +247,7 @@ class WC_Admin_Tests_API_Reports_Import extends WC_REST_Unit_Test_Case {
}
// Check that stats exist before deleting.
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', '/wc-analytics/reports/orders' );
$request->set_query_params( array( 'per_page' => 25 ) );
@@ -273,7 +273,7 @@ class WC_Admin_Tests_API_Reports_Import extends WC_REST_Unit_Test_Case {
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 'success', $report['status'] );
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Check that stats have been deleted.
$request = new WP_REST_Request( 'GET', '/wc-analytics/reports/orders' );
@@ -375,7 +375,7 @@ class WC_Admin_Tests_API_Reports_Import extends WC_REST_Unit_Test_Case {
$this->assertEquals( 0, $report['orders']['imported'] );
$this->assertEquals( 4, $report['orders']['total'] );
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Test import status after processing.
$request = new WP_REST_Request( 'GET', $this->endpoint . '/status' );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-orders-stats.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-orders-stats.php
index 18c8b856222..08b2a41cf74 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-orders-stats.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-orders-stats.php
@@ -154,7 +154,7 @@ class WC_Admin_Tests_API_Reports_Orders_Stats extends WC_REST_Unit_Test_Case {
$global_attribute = new WC_Product_Attribute();
$global_attribute->set_id( $size_attr_id );
$global_attribute->set_name( 'pa_size' );
- $global_attribute->set_options( array( $large_term->term_id ) ); // Set to small.
+ $global_attribute->set_options( array( $large_term->term_id ) ); // Set to large.
$global_attribute->set_position( 1 );
$global_attribute->set_visible( true );
$global_attribute->set_variation( false );
@@ -187,7 +187,8 @@ class WC_Admin_Tests_API_Reports_Orders_Stats extends WC_REST_Unit_Test_Case {
$order->save();
}
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
+ WC_Helper_Queue::run_all_pending( 'woocommerce-db-updates' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params( array( 'per_page' => 15 ) );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-orders.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-orders.php
index 38aeb49eed6..2a695b5d9ff 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-orders.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-orders.php
@@ -69,7 +69,7 @@ class WC_Admin_Tests_API_Reports_Orders extends WC_REST_Unit_Test_Case {
$order->set_total( 100 ); // $25 x 4.
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$expected_customer_id = CustomersDataStore::get_customer_id_by_user_id( 1 );
@@ -126,7 +126,7 @@ class WC_Admin_Tests_API_Reports_Orders extends WC_REST_Unit_Test_Case {
)
);
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', $this->endpoint ) );
$reports = $response->get_data();
@@ -238,7 +238,8 @@ class WC_Admin_Tests_API_Reports_Orders extends WC_REST_Unit_Test_Case {
$order->save();
}
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
+ WC_Helper_Queue::run_all_pending( 'woocommerce-db-updates' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params( array( 'per_page' => 15 ) );
@@ -369,7 +370,7 @@ class WC_Admin_Tests_API_Reports_Orders extends WC_REST_Unit_Test_Case {
$order->save();
}
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params( array( 'per_page' => 15 ) );
@@ -438,7 +439,7 @@ class WC_Admin_Tests_API_Reports_Orders extends WC_REST_Unit_Test_Case {
$order_to_be_included->set_status( 'completed' );
$order_to_be_included->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Test product exclusion.
$request = new WP_REST_Request( 'GET', $this->endpoint );
@@ -515,7 +516,7 @@ class WC_Admin_Tests_API_Reports_Orders extends WC_REST_Unit_Test_Case {
$second_order->set_status( 'on-hold' );
$second_order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Get the created orders from REST API.
$request = new WP_REST_Request( 'GET', $this->endpoint );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-performance-indicators.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-performance-indicators.php
index 8cbab9032a1..058a40370a6 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-performance-indicators.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-performance-indicators.php
@@ -90,7 +90,7 @@ class WC_Admin_Tests_API_Reports_Performance_Indicators extends WC_REST_Unit_Tes
$object->set_user_ip_address( '1.2.3.4' );
$object->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$time = time();
$request = new WP_REST_Request( 'GET', $this->endpoint );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-products-stats.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-products-stats.php
index f203a65b84e..49862190354 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-products-stats.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-products-stats.php
@@ -71,7 +71,7 @@ class WC_Admin_Tests_API_Reports_Products_Stats extends WC_REST_Unit_Test_Case {
$order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params(
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-products.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-products.php
index 9e6aade8a16..b332a5047ad 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-products.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-products.php
@@ -67,7 +67,7 @@ class WC_Admin_Tests_API_Reports_Products extends WC_REST_Unit_Test_Case {
$order->set_total( 100 ); // $25 x 4.
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', $this->endpoint ) );
$reports = $response->get_data();
@@ -109,7 +109,7 @@ class WC_Admin_Tests_API_Reports_Products extends WC_REST_Unit_Test_Case {
$order->set_total( 100 ); // $25 x 4.
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params(
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-taxes-stats.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-taxes-stats.php
index 1920b20b029..9ea322b25eb 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-taxes-stats.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-taxes-stats.php
@@ -99,7 +99,7 @@ class WC_Admin_Tests_API_Reports_Taxes_Stats extends WC_REST_Unit_Test_Case {
$wc_refund = wc_create_refund( $refund );
}
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', $this->endpoint ) );
$reports = $response->get_data();
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-taxes.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-taxes.php
index 3f896cc5b78..cfadb1787a8 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-taxes.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-taxes.php
@@ -115,7 +115,7 @@ class WC_Admin_Tests_API_Reports_Taxes extends WC_REST_Unit_Test_Case {
)
);
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', $this->endpoint ) );
$reports = $response->get_data();
@@ -416,6 +416,6 @@ class WC_Admin_Tests_API_Reports_Taxes extends WC_REST_Unit_Test_Case {
)
);
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
}
}
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-variations.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-variations.php
index d8906331c79..2c4a974ad1b 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-variations.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/api/reports-variations.php
@@ -69,7 +69,7 @@ class WC_Admin_Tests_API_Reports_Variations extends WC_REST_Unit_Test_Case {
$order->set_total( 100 ); // $25 x 4.
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', $this->endpoint ) );
$reports = $response->get_data();
@@ -102,7 +102,7 @@ class WC_Admin_Tests_API_Reports_Variations extends WC_REST_Unit_Test_Case {
$order->set_total( 15 );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params(
@@ -146,7 +146,7 @@ class WC_Admin_Tests_API_Reports_Variations extends WC_REST_Unit_Test_Case {
$order->set_total( 100 ); // $25 x 4.
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params(
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/notes/class-wc-tests-notes-note.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/notes/class-wc-tests-notes-note.php
index 700fb702d0e..d4f7d0f8455 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/notes/class-wc-tests-notes-note.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/notes/class-wc-tests-notes-note.php
@@ -53,4 +53,31 @@ class WC_Admin_Tests_Notes_Note extends WC_Unit_Test_Case {
$this->assertEquals( $date_created_from_first_save, $date_created_from_second_save );
}
+ /**
+ * Tests setting date_reminder with various input types.
+ *
+ * @dataProvider date_reminder_provider
+ * @param mixed $input Input date value.
+ * @param int $expected_timestamp Expected timestamp.
+ */
+ public function test_set_date_reminder_with_various_inputs( $input, $expected_timestamp ) {
+ $note = new Note();
+ $note->set_date_reminder( $input );
+ $date_reminder = $note->get_date_reminder();
+ $this->assertEquals( $expected_timestamp, $date_reminder );
+ }
+
+ /**
+ * Data provider for test_set_date_reminder_with_various_inputs.
+ *
+ * @return array
+ */
+ public function date_reminder_provider() {
+ return array(
+ 'timestamp' => array( 1609459200, '2021-01-01T00:00:00+00:00' ),
+ 'timestamp string' => array( '1609459200', '2021-01-01T00:00:00+00:00' ),
+ 'date string' => array( '2021-01-01', '2021-01-01T00:00:00+00:00' ),
+ 'WC_DateTime object' => array( new WC_DateTime( '2021-01-01' ), '2021-01-01T00:00:00+00:00' ),
+ );
+ }
}
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/base-location-country-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/base-location-country-rule-processor.php
similarity index 94%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/base-location-country-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/base-location-country-rule-processor.php
index b49df23970d..031da61b9f2 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/base-location-country-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/base-location-country-rule-processor.php
@@ -2,16 +2,18 @@
/**
* Base Location country rule processor tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\BaseLocationCountryRuleProcessor;
use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_BaseLocationCountryRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_BaseLocationCountryRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_BaseLocationCountryRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_BaseLocationCountryRuleProcessor extends WC_Unit_Test_Case {
/**
* Get the publish_before rule.
*
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/base-location-state-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/base-location-state-rule-processor.php
similarity index 84%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/base-location-state-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/base-location-state-rule-processor.php
index 9135ab0b05d..d69972954c0 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/base-location-state-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/base-location-state-rule-processor.php
@@ -2,16 +2,18 @@
/**
* Base Location state rule processor tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\BaseLocationStateRuleProcessor;
use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_BaseLocationStateRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_BaseLocationStateRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_BaseLocationStateRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_BaseLocationStateRuleProcessor extends WC_Unit_Test_Case {
/**
* Get the base_location_state rule.
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/comparison-operation.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/comparison-operation.php
similarity index 90%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/comparison-operation.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/comparison-operation.php
index 85fa28f8e9f..7ea8bd7dd8b 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/comparison-operation.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/comparison-operation.php
@@ -5,12 +5,14 @@
* @package WooCommerce\Admin\Tests\RemoteInboxNotification
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\ComparisonOperation;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_Comparison_Operation
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_Comparison_Operation
*/
-class WC_Admin_Tests_RemoteInboxNotifications_Comparison_Operation extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_Comparison_Operation extends WC_Unit_Test_Case {
/**
* @var ComparisonOperation $operation
*/
@@ -36,7 +38,6 @@ class WC_Admin_Tests_RemoteInboxNotifications_Comparison_Operation extends WC_Un
$this->assertFalse( $this->operation->compare( 11, array( 1, 10 ), 'range' ) );
$this->assertFalse( $this->operation->compare( 11, array( 1, 10, 2 ), 'range' ) );
$this->assertFalse( $this->operation->compare( 11, 'string', 'range' ) );
-
}
/**
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/evaluate-and-get-status.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/evaluate-and-get-status.php
similarity index 95%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/evaluate-and-get-status.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/evaluate-and-get-status.php
index 7de3b0c6251..7ec67d2f995 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/evaluate-and-get-status.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/evaluate-and-get-status.php
@@ -2,15 +2,17 @@
/**
* Evaluate and get status tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\EvaluateAndGetStatus;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_EvaluateAndGetStatus
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_EvaluateAndGetStatus
*/
-class WC_Admin_Tests_RemoteInboxNotifications_EvaluateAndGetStatus extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_EvaluateAndGetStatus extends WC_Unit_Test_Case {
/**
* Build up a spec given the supplied parameters.
*
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/failing-rule-evaluator.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/failing-rule-evaluator.php
similarity index 58%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/failing-rule-evaluator.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/failing-rule-evaluator.php
index 8d856895e5b..b4c79cffb31 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/failing-rule-evaluator.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/failing-rule-evaluator.php
@@ -2,9 +2,11 @@
/**
* FailingRuleEvaluator
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
/**
* class FailingRuleEvaluator
*/
@@ -16,7 +18,7 @@ class FailingRuleEvaluator {
*
* @return bool The evaluated result.
*/
- public function evaluate( $rules ) {
+ public function evaluate( $rules ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
return false;
}
}
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/get-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/get-rule-processor.php
similarity index 70%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/get-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/get-rule-processor.php
index b5eee559d84..fb2721229eb 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/get-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/get-rule-processor.php
@@ -2,15 +2,17 @@
/**
* Get rule processor tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\GetRuleProcessor;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_GetRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_GetRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_GetRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_GetRuleProcessor extends WC_Unit_Test_Case {
/**
* Tests that an unknown rule processor returns a FailRuleProcessor
*
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/is-woo-express-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/is-woo-express-rule-processor.php
similarity index 91%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/is-woo-express-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/is-woo-express-rule-processor.php
index 5db49ff717f..ba2bca4b7cf 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/is-woo-express-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/is-woo-express-rule-processor.php
@@ -2,15 +2,17 @@
/**
* Is WooExpress rule processor tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\IsWooExpressRuleProcessor;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_IsWooExpressRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_IsWooExpressRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_IsWooExpressRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_IsWooExpressRuleProcessor extends WC_Unit_Test_Case {
/**
* Set Up Before Class.
*/
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-date-time-provider.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-date-time-provider.php
similarity index 87%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-date-time-provider.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-date-time-provider.php
index e250192bb23..cc8c32321c2 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-date-time-provider.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-date-time-provider.php
@@ -2,9 +2,11 @@
/**
* Mock DateTime Provider.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\DateTimeProvider\DateTimeProviderInterface;
/**
@@ -29,4 +31,3 @@ class MockDateTimeProvider implements DateTimeProviderInterface {
return $this->now;
}
}
-
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-get-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-get-rule-processor.php
similarity index 91%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-get-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-get-rule-processor.php
index 5de623920a5..805e6aabca2 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-get-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-get-rule-processor.php
@@ -2,9 +2,11 @@
/**
* MockGetRuleProcessor.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\PublishAfterTimeRuleProcessor;
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\FailRuleProcessor;
@@ -29,4 +31,3 @@ class MockGetRuleProcessor {
return new FailRuleProcessor();
}
}
-
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-plugins-provider.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-plugins-provider.php
similarity index 96%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-plugins-provider.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-plugins-provider.php
index 72e4bc22b62..f9a14565af9 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-plugins-provider.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-plugins-provider.php
@@ -2,9 +2,11 @@
/**
* Mock plugins Provider.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\PluginsProvider\PluginsProviderInterface;
/**
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-product-query.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-product-query.php
similarity index 85%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-product-query.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-product-query.php
index 681309d4045..8b3c0381e77 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-product-query.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-product-query.php
@@ -2,9 +2,11 @@
/**
* Mock product query.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
/**
* Mock product query.
*/
@@ -29,4 +31,3 @@ class MockProductQuery {
);
}
}
-
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-wc-admin-active-for-provider.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-wc-admin-active-for-provider.php
similarity index 80%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-wc-admin-active-for-provider.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-wc-admin-active-for-provider.php
index 37932001686..3f65b3f1030 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/mock-wc-admin-active-for-provider.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/mock-wc-admin-active-for-provider.php
@@ -2,9 +2,11 @@
/**
* Mock WCAdminActiveForProvider
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
/**
* Mock WCAdminActiveForProvider
*/
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/not-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/not-rule-processor.php
similarity index 88%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/not-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/not-rule-processor.php
index 9088cec3242..f2628792362 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/not-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/not-rule-processor.php
@@ -2,16 +2,18 @@
/**
* Not rule processor tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\NotRuleProcessor;
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\RuleEvaluator;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_NotRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_NotRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_NotRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_NotRuleProcessor extends WC_Unit_Test_Case {
/**
* An empty operand evaluates to false, so negating that should
* evaluate to true.
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/onboarding-profile-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/onboarding-profile-rule-processor.php
similarity index 87%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/onboarding-profile-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/onboarding-profile-rule-processor.php
index 097670b0115..9f59c1ab06f 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/onboarding-profile-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/onboarding-profile-rule-processor.php
@@ -2,16 +2,18 @@
/**
* Onboarding profile rule processor tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\OnboardingProfileRuleProcessor;
use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_OnboardingProfileRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_OnboardingProfileRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_OnboardingProfileRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_OnboardingProfileRuleProcessor extends WC_Unit_Test_Case {
/**
* Get the publish_before rule.
*
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/option-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/option-rule-processor.php
similarity index 93%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/option-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/option-rule-processor.php
index 6e062f0ec7a..20f5dccad84 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/option-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/option-rule-processor.php
@@ -2,15 +2,17 @@
/**
* Option rule processor tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\OptionRuleProcessor;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_OptionRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_OptionRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_OptionRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_OptionRuleProcessor extends WC_Unit_Test_Case {
/**
* No default option resolves to false.
*
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/or-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/or-rule-processor.php
similarity index 93%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/or-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/or-rule-processor.php
index 6c93dfd1fb8..90c95605e1a 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/or-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/or-rule-processor.php
@@ -2,16 +2,18 @@
/**
* Or rule processor tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\OrRuleProcessor;
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\RuleEvaluator;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_OrRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_OrRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_OrRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_OrRuleProcessor extends WC_Unit_Test_Case {
/**
* Both operands evaluating to false and ORed together evaluates to false.
*
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/passing-rule-evaluator.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/passing-rule-evaluator.php
similarity index 58%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/passing-rule-evaluator.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/passing-rule-evaluator.php
index 9a504e784cd..f0d730f1ced 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/passing-rule-evaluator.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/passing-rule-evaluator.php
@@ -2,9 +2,11 @@
/**
* PassingRuleEvaluator
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
/**
* class PassingRuleEvaluator
*/
@@ -16,7 +18,7 @@ class PassingRuleEvaluator {
*
* @return bool The evaluated result.
*/
- public function evaluate( $rules ) {
+ public function evaluate( $rules ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
return true;
}
}
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/plugin-version-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/plugin-version-rule-processor.php
similarity index 94%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/plugin-version-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/plugin-version-rule-processor.php
index a38fdbb9a63..cd2d9c5811e 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/plugin-version-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/plugin-version-rule-processor.php
@@ -2,15 +2,17 @@
/**
* Plugin version rule processor tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\PluginVersionRuleProcessor;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_PluginVersionRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_PluginVersionRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_PluginVersionRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_PluginVersionRuleProcessor extends WC_Unit_Test_Case {
/**
* Test that the processor does not pass if the plugin is not activated.
*
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/plugins-activated-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/plugins-activated-rule-processor.php
similarity index 93%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/plugins-activated-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/plugins-activated-rule-processor.php
index 41f478cedce..6250102b9bc 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/plugins-activated-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/plugins-activated-rule-processor.php
@@ -2,16 +2,18 @@
/**
* Plugins activated rule processor tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\PluginsActivatedRuleProcessor;
use Automattic\WooCommerce\Admin\PluginsProvider\PluginsProviderInterface;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_PluginsActivatedRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_PluginsActivatedRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_PluginsActivatedRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_PluginsActivatedRuleProcessor extends WC_Unit_Test_Case {
/**
* Tests that the processor does not pass a plugins_activated rule with
* no plugins to verify.
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/product-count-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/product-count-rule-processor.php
similarity index 81%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/product-count-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/product-count-rule-processor.php
index a3ca1a8cb74..2e4b0e1891f 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/product-count-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/product-count-rule-processor.php
@@ -2,15 +2,17 @@
/**
* Product count rule processor tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\ProductCountRuleProcessor;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_ProductCountRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_ProductCountRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_ProductCountRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_ProductCountRuleProcessor extends WC_Unit_Test_Case {
/**
* Get a product_count rule that passes when the product count is > 5.
*
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/publish-after-time-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/publish-after-time-rule-processor.php
similarity index 90%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/publish-after-time-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/publish-after-time-rule-processor.php
index 9aec0acfcfd..4057a9f1daf 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/publish-after-time-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/publish-after-time-rule-processor.php
@@ -2,16 +2,18 @@
/**
* Publish after time rule processor tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\PublishAfterTimeRuleProcessor;
use Automattic\WooCommerce\Admin\DateTimeProvider\DateTimeProviderInterface;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_PublishAfterTimeRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_PublishAfterTimeRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_PublishAfterTimeRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_PublishAfterTimeRuleProcessor extends WC_Unit_Test_Case {
/**
* Get the publish_after rule.
*
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/publish-before-time-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/publish-before-time-rule-processor.php
similarity index 90%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/publish-before-time-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/publish-before-time-rule-processor.php
index 0234df59c87..60e23fbf5ec 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/publish-before-time-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/publish-before-time-rule-processor.php
@@ -2,16 +2,18 @@
/**
* Publish before time rule processor tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\PublishBeforeTimeRuleProcessor;
use Automattic\WooCommerce\Admin\DateTimeProvider\DateTimeProviderInterface;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_PublishBeforeTimeRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_PublishBeforeTimeRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_PublishBeforeTimeRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_PublishBeforeTimeRuleProcessor extends WC_Unit_Test_Case {
/**
* Get the publish_before rule.
*
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/stored-state-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/stored-state-rule-processor.php
similarity index 97%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/stored-state-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/stored-state-rule-processor.php
index 47567a6627d..ed1f616e67c 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/stored-state-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/stored-state-rule-processor.php
@@ -2,15 +2,17 @@
/**
* Stored state rule processor tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\StoredStateRuleProcessor;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_StoredStateRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_StoredStateRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_StoredStateRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_StoredStateRuleProcessor extends WC_Unit_Test_Case {
/**
* Empty $stored_state evaluates to false.
*
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/total-payments-volume-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/total-payments-volume-processor.php
similarity index 93%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/total-payments-volume-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/total-payments-volume-processor.php
index d177dd8f975..7d11b482a78 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/total-payments-volume-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/total-payments-volume-processor.php
@@ -5,13 +5,15 @@
* @package WooCommerce\Admin\Tests\RemoteInboxNotification
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\TotalPaymentsVolumeProcessor;
use Automattic\WooCommerce\Admin\API\Reports\Revenue\Query as RevenueQuery;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_TotalPaymentsVolumeProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_TotalPaymentsVolumeProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_TotalPaymentsVolumeProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_TotalPaymentsVolumeProcessor extends WC_Unit_Test_Case {
/**
* Greater than 1000 total payments volume evaluates to false.
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/transformer-service.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformer-service.php
similarity index 95%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/transformer-service.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformer-service.php
index 224e7ba86e4..c5e17aee945 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/transformer-service.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformer-service.php
@@ -2,16 +2,18 @@
/**
* TransformerService tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\ArrayKeys;
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\TransformerService;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_TransformerService
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_TransformerService
*/
-class WC_Admin_Tests_RemoteInboxNotifications_TransformerService extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_TransformerService extends WC_Unit_Test_Case {
/**
* Test it creates a transformer with snake case 'use' value
*/
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-column.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-column.php
similarity index 82%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-column.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-column.php
index e5303725b37..bb1ed192b74 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-column.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-column.php
@@ -2,23 +2,25 @@
/**
* ArrayColumn tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\ArrayColumn;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_Transformers_ArrayColumn
+ * class WC_Admin_Tests_RemoteSpecs_Transformers_ArrayColumn
*/
-class WC_Admin_Tests_RemoteInboxNotifications_Transformers_ArrayColumn extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_Transformers_ArrayColumn extends WC_Unit_Test_Case {
/**
* Test validate method returns false when 'key' argument is missing
*/
public function test_validate_returns_false_when_key_argument_is_missing() {
$array_column = new ArrayColumn();
$result = $array_column->validate( (object) array() );
- $this->assertFalse( false, $result );
+ $this->assertFalse( $result );
}
/**
@@ -31,14 +33,14 @@ class WC_Admin_Tests_RemoteInboxNotifications_Transformers_ArrayColumn extends W
'key' => true,
)
);
- $this->assertFalse( false, $result );
+ $this->assertFalse( $result );
$result = $array_column->validate(
(object) array(
'key' => array(),
)
);
- $this->assertFalse( false, $result );
+ $this->assertFalse( $result );
}
/**
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-flatten.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-flatten.php
similarity index 92%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-flatten.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-flatten.php
index b02ba40fff9..5e5d76c2834 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-flatten.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-flatten.php
@@ -2,9 +2,11 @@
/**
* ArrayKeys tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\ArrayFlatten;
/**
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-keys.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-keys.php
similarity index 77%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-keys.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-keys.php
index b8e7d036192..f9e7b5df6c3 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-keys.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-keys.php
@@ -2,15 +2,17 @@
/**
* ArrayKeys tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\ArrayKeys;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_Transformers_ArrayKeys
+ * class WC_Admin_Tests_RemoteSpecs_Transformers_ArrayKeys
*/
-class WC_Admin_Tests_RemoteInboxNotifications_Transformers_ArrayKeys extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_Transformers_ArrayKeys extends WC_Unit_Test_Case {
/**
* Test it returns default value when value is not an array
*/
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-search.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-search.php
similarity index 84%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-search.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-search.php
index 46167d4b93e..17172146021 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-search.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-search.php
@@ -2,22 +2,24 @@
/**
* ArraySearch tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\ArraySearch;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_Transformers_ArraySearch
+ * class WC_Admin_Tests_RemoteSpecs_Transformers_ArraySearch
*/
-class WC_Admin_Tests_RemoteInboxNotifications_Transformers_ArraySearch extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_Transformers_ArraySearch extends WC_Unit_Test_Case {
/**
* Test validate method returns false when 'value' argument is missing
*/
public function test_validate_returns_false_when_value_argument_is_missing() {
$array_column = new ArraySearch();
$result = $array_column->validate( (object) array() );
- $this->assertFalse( false, $result );
+ $this->assertFalse( $result );
}
/**
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-values.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-values.php
similarity index 77%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-values.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-values.php
index efef87142be..18d96425cf4 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/array-values.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/array-values.php
@@ -2,15 +2,17 @@
/**
* ArrayValues tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\ArrayValues;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_Transformers_ArrayValues
+ * class WC_Admin_Tests_RemoteSpecs_Transformers_ArrayValues
*/
-class WC_Admin_Tests_RemoteInboxNotifications_Transformers_ArrayValues extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_Transformers_ArrayValues extends WC_Unit_Test_Case {
/**
* Test it returns default value when value is not an array
*/
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/count.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/count.php
similarity index 76%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/count.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/count.php
index 703a5804909..38f0f65ccb5 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/count.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/count.php
@@ -2,15 +2,17 @@
/**
* ArrayValues tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\Count;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_Transformers_ArrayValues
+ * class WC_Admin_Tests_RemoteSpecs_Transformers_ArrayValues
*/
-class WC_Admin_Tests_RemoteInboxNotifications_Transformers_ArrayCount extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_Transformers_ArrayCount extends WC_Unit_Test_Case {
/**
* Test it returns default value when value is not an array.
*/
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/dot-notation.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/dot-notation.php
similarity index 88%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/dot-notation.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/dot-notation.php
index 1e74188467a..32f76474014 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/dot-notation.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/dot-notation.php
@@ -2,16 +2,18 @@
/**
* DotNotation tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\DotNotation;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_Transformers_DotNotation
+ * class WC_Admin_Tests_RemoteSpecs_Transformers_DotNotation
*/
-class WC_Admin_Tests_RemoteInboxNotifications_Transformers_DotNotation extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_Transformers_DotNotation extends WC_Unit_Test_Case {
/**
* Test validate method returns false when 'path' argument is missing
@@ -19,7 +21,7 @@ class WC_Admin_Tests_RemoteInboxNotifications_Transformers_DotNotation extends W
public function test_validate_returns_false_when_path_argument_is_missing() {
$array_column = new DotNotation();
$result = $array_column->validate( (object) array() );
- $this->assertFalse( false, $result );
+ $this->assertFalse( $result );
}
/**
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/prepare-url.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/prepare-url.php
similarity index 84%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/prepare-url.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/prepare-url.php
index a6f9d42478a..0e8c2145358 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/Transformers/prepare-url.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/transformers/prepare-url.php
@@ -2,15 +2,17 @@
/**
* PrepareUrl tests.
*
- * @package WooCommerce\Admin\Tests\RemoteInboxNotifications
+ * @package WooCommerce\Admin\Tests\RemoteSpecs
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\Transformers\PrepareUrl;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_Transformers_PrepareUrl
+ * class WC_Admin_Tests_RemoteSpecs_Transformers_PrepareUrl
*/
-class WC_Admin_Tests_RemoteInboxNotifications_Transformers_PrepareUrl extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_Transformers_PrepareUrl extends WC_Unit_Test_Case {
/**
* Test it returns default value when url is not string.
*/
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/wcadmin-active-for-rule-processor.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/wcadmin-active-for-rule-processor.php
similarity index 93%
rename from plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/wcadmin-active-for-rule-processor.php
rename to plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/wcadmin-active-for-rule-processor.php
index dca95841a92..8cd0349f66f 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-inbox-notifications/wcadmin-active-for-rule-processor.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/remote-specs/rule-processors/wcadmin-active-for-rule-processor.php
@@ -5,12 +5,14 @@
* @package WooCommerce\Admin\Tests\RemoteInboxNotification
*/
+declare( strict_types = 1 );
+
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\WCAdminActiveForRuleProcessor;
/**
- * class WC_Admin_Tests_RemoteInboxNotifications_WCAdminActiveForRuleProcessor
+ * class WC_Admin_Tests_RemoteSpecs_RuleProcessors_WCAdminActiveForRuleProcessor
*/
-class WC_Admin_Tests_RemoteInboxNotifications_WCAdminActiveForRuleProcessor extends WC_Unit_Test_Case {
+class WC_Admin_Tests_RemoteSpecs_RuleProcessors_WCAdminActiveForRuleProcessor extends WC_Unit_Test_Case {
/**
* Greater than 7 days evaluates to true
*
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-coupons-stats.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-coupons-stats.php
index 04e1c98698d..4abbd68e1cf 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-coupons-stats.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-coupons-stats.php
@@ -57,7 +57,7 @@ class WC_Admin_Tests_Reports_Coupons_Stats extends WC_Unit_Test_Case {
$order_2c->calculate_totals();
$order_2c->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new CouponsStatsDataStore();
$start_time = gmdate( 'Y-m-d 00:00:00', $order->get_date_created()->getOffsetTimestamp() );
@@ -133,7 +133,7 @@ class WC_Admin_Tests_Reports_Coupons_Stats extends WC_Unit_Test_Case {
// Delete the coupon.
$coupon_1->delete( true );
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$start_time = gmdate( 'Y-m-d 00:00:00', $order->get_date_created()->getOffsetTimestamp() );
$end_time = gmdate( 'Y-m-d 23:59:59', $order->get_date_created()->getOffsetTimestamp() );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-coupons.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-coupons.php
index 867de990e28..f7d96278eeb 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-coupons.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-coupons.php
@@ -59,7 +59,7 @@ class WC_Admin_Tests_Reports_Coupons extends WC_Unit_Test_Case {
$order_2c->calculate_totals();
$order_2c->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new CouponsDataStore();
$start_time = gmdate( 'Y-m-d 00:00:00', $order->get_date_created()->getOffsetTimestamp() );
@@ -375,7 +375,7 @@ class WC_Admin_Tests_Reports_Coupons extends WC_Unit_Test_Case {
// Delete the coupons.
$coupon_2->delete( true );
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new CouponsDataStore();
$start_time = gmdate( 'Y-m-d 00:00:00', $order->get_date_created()->getOffsetTimestamp() );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-customers.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-customers.php
index c25c56b1376..bb7283220fe 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-customers.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-customers.php
@@ -29,7 +29,7 @@ class WC_Admin_Tests_Reports_Customer extends WC_Unit_Test_Case {
$product->set_regular_price( 25 );
$product->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$customer_id = DataStore::get_customer_id_by_user_id( $customer->get_id() ); // This is the customer ID from lookup table.
@@ -39,7 +39,7 @@ class WC_Admin_Tests_Reports_Customer extends WC_Unit_Test_Case {
$order->save();
}
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Customer should have 3 orders.
$this->assertSame( 3, DataStore::get_order_count( $customer_id ) );
@@ -75,7 +75,7 @@ class WC_Admin_Tests_Reports_Customer extends WC_Unit_Test_Case {
$product2->set_regular_price( 2 );
$product2->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Create the first order.
$order1 = WC_Helper_Order::create_order( $customer->get_id(), $product1 );
@@ -85,7 +85,7 @@ class WC_Admin_Tests_Reports_Customer extends WC_Unit_Test_Case {
$order2 = WC_Helper_Order::create_order( $customer->get_id(), $product2 );
$order2->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$customer_id = DataStore::get_customer_id_by_user_id( $customer->get_id() ); // This is the customer ID from lookup table.
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders-stats.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders-stats.php
index f19ee7b5dc0..09a1628daad 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders-stats.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders-stats.php
@@ -63,7 +63,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
)
);
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new OrdersStatsDataStore();
@@ -208,7 +208,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
$order->save();
}
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new OrdersStatsDataStore();
@@ -377,7 +377,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
)
);
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new OrdersStatsDataStore();
@@ -666,7 +666,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
$orders[] = $order;
}
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new OrdersStatsDataStore();
@@ -917,7 +917,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
}
}
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new OrdersStatsDataStore();
@@ -3865,7 +3865,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
$order->apply_coupon( $coupon );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Check if lookup tables are populated.
foreach ( $tables as $table ) {
@@ -3996,7 +3996,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
$order_2->calculate_totals();
$order_2->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new OrdersStatsDataStore();
@@ -4544,7 +4544,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
$orders[] = $order;
}
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new OrdersStatsDataStore();
@@ -5328,7 +5328,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
$orders[] = $order;
}
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
global $wpdb;
$res = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wc_order_stats" );
@@ -6094,7 +6094,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
$order_0->set_total( 100 );
$order_0->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$start_time = gmdate( 'Y-m-d H:00:00', $order_0->get_date_created()->getOffsetTimestamp() );
$end_time = gmdate( 'Y-m-d H:59:59', $order_0->get_date_created()->getOffsetTimestamp() );
@@ -6114,7 +6114,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
$order_1->set_total( 100 );
$order_1->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Time frame includes both orders -> customer is a new customer.
$start_time = gmdate( 'Y-m-d H:00:00', $order_0->get_date_created()->getOffsetTimestamp() );
@@ -6153,7 +6153,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
$order_2->set_total( 100 );
$order_2->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Time frame includes second and third order -> there is one returning customer.
$start_time = gmdate( 'Y-m-d H:i:s', $order_0_time + 1 );
@@ -6204,7 +6204,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
$order_0->set_total( 100 );
$order_0->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$start_time = gmdate( 'Y-m-d H:00:00', $order_0->get_date_created()->getOffsetTimestamp() );
$end_time = gmdate( 'Y-m-d H:59:59', $order_0->get_date_created()->getOffsetTimestamp() );
@@ -6224,7 +6224,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
$order_1->set_total( 100 );
$order_1->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Time frame includes both orders -> customer is a new customer.
$start_time = gmdate( 'Y-m-d H:00:00', $order_0->get_date_created()->getOffsetTimestamp() );
@@ -6263,7 +6263,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
$order_2->set_total( 100 );
$order_2->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// Time frame includes second and third order -> there is one returning customer.
$start_time = gmdate( 'Y-m-d H:i:s', $order_0_time + 1 );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders.php
index 078da5f087b..40b50f9a248 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders.php
@@ -64,7 +64,7 @@ class WC_Admin_Tests_Reports_Orders extends WC_Unit_Test_Case {
$order->set_status( 'completed' );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new OrdersDataStore();
$start_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
@@ -143,7 +143,7 @@ class WC_Admin_Tests_Reports_Orders extends WC_Unit_Test_Case {
)
);
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new OrdersDataStore();
$start_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
@@ -255,7 +255,7 @@ class WC_Admin_Tests_Reports_Orders extends WC_Unit_Test_Case {
$order2->set_status( 'completed' );
$order2->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new OrdersDataStore();
$start_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
@@ -310,7 +310,7 @@ class WC_Admin_Tests_Reports_Orders extends WC_Unit_Test_Case {
$order_2->set_status( 'completed' );
$order_2->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$start_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
$end_time = gmdate( 'Y-m-d H:59:59', $order->get_date_created()->getOffsetTimestamp() );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-products.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-products.php
index e088c2f47e4..94e74ab59a3 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-products.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-products.php
@@ -42,7 +42,7 @@ class WC_Admin_Tests_Reports_Products extends WC_Unit_Test_Case {
$order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new ProductsDataStore();
$start_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
@@ -119,7 +119,7 @@ class WC_Admin_Tests_Reports_Products extends WC_Unit_Test_Case {
$order_2->set_date_created( $date_created_2 );
$order_2->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new ProductsDataStore();
$start_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
@@ -220,7 +220,7 @@ class WC_Admin_Tests_Reports_Products extends WC_Unit_Test_Case {
$order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new ProductsDataStore();
$start_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
@@ -301,7 +301,7 @@ class WC_Admin_Tests_Reports_Products extends WC_Unit_Test_Case {
$order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new ProductsDataStore();
$start_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
@@ -383,7 +383,7 @@ class WC_Admin_Tests_Reports_Products extends WC_Unit_Test_Case {
break;
}
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new ProductsDataStore();
$start_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
@@ -441,7 +441,7 @@ class WC_Admin_Tests_Reports_Products extends WC_Unit_Test_Case {
$order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$term = wp_insert_term( 'Unused Category', 'product_cat' );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-revenue-stats.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-revenue-stats.php
index 30a9b0832de..7722921486f 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-revenue-stats.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-revenue-stats.php
@@ -43,7 +43,7 @@ class WC_Admin_Tests_Reports_Revenue_Stats extends WC_Unit_Test_Case {
$order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
// /reports/revenue/stats is mapped to Orders_Data_Store.
$data_store = new OrdersStatsDataStore();
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-variations.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-variations.php
index 66e55d262d1..435600978ca 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-variations.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-variations.php
@@ -42,7 +42,7 @@ class WC_Admin_Tests_Reports_Variations extends WC_Unit_Test_Case {
$order->set_status( 'completed' );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new VariationsDataStore();
$start_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
@@ -111,7 +111,7 @@ class WC_Admin_Tests_Reports_Variations extends WC_Unit_Test_Case {
$order->set_status( 'completed' );
$order->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new VariationsDataStore();
$start_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
@@ -228,7 +228,7 @@ class WC_Admin_Tests_Reports_Variations extends WC_Unit_Test_Case {
$order_3->set_status( 'completed' );
$order_3->save();
- WC_Helper_Queue::run_all_pending();
+ WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
$data_store = new VariationsDataStore();
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-structured-data-test.php b/plugins/woocommerce/tests/php/includes/class-wc-structured-data-test.php
new file mode 100644
index 00000000000..652d1199e92
--- /dev/null
+++ b/plugins/woocommerce/tests/php/includes/class-wc-structured-data-test.php
@@ -0,0 +1,83 @@
+structured_data = new WC_Structured_Data();
+ parent::setUp();
+ }
+
+ /**
+ * Test is_valid_gtin function
+ *
+ * @return void
+ */
+ public function test_is_valid_gtin(): void {
+
+ $valid_gtins = array(
+ '12345678',
+ '123456789012',
+ '1234567890123',
+ '12345678901234',
+ );
+
+ $invalid_gtins = array(
+ '',
+ null,
+ false,
+ 12345678,
+ 123.4e-5,
+ +1234567,
+ 'abcdefgh',
+ '-9999999',
+ '12-45-66',
+ '123',
+ '123456789012345',
+ '123456789',
+ '1234567890',
+ '12 34 56 78',
+ '12 34 56',
+ '+12345678',
+ '123.4e-5',
+ );
+
+ foreach ( $valid_gtins as $valid_gtin ) {
+ $this->assertTrue( $this->structured_data->is_valid_gtin( $valid_gtin ) );
+ }
+
+ foreach ( $invalid_gtins as $invalid_gtin ) {
+ $this->assertFalse( $this->structured_data->is_valid_gtin( $invalid_gtin ) );
+ }
+ }
+
+ /**
+ * Test prepare_gtin function
+ *
+ * @return void
+ */
+ public function test_prepare_gtin(): void {
+ $this->assertEquals( $this->structured_data->prepare_gtin( '123-456-78' ), '12345678' );
+ $this->assertEquals( $this->structured_data->prepare_gtin( '-123-456-78' ), '12345678' );
+ $this->assertEquals( $this->structured_data->prepare_gtin( 'GTIN: 123-456-78' ), '12345678' );
+ $this->assertEquals( $this->structured_data->prepare_gtin( '123 456 78' ), '12345678' );
+ $this->assertEquals( $this->structured_data->prepare_gtin( null ), '' );
+ $this->assertEquals( $this->structured_data->prepare_gtin( 'GTIN' ), '' );
+ $this->assertEquals( $this->structured_data->prepare_gtin( 123 ), '' );
+ $this->assertEquals( $this->structured_data->prepare_gtin( array( '123-456-78', '123-456-78' ) ), '' );
+ $this->assertEquals( $this->structured_data->prepare_gtin( '+12345678' ), '12345678' );
+ $this->assertEquals( $this->structured_data->prepare_gtin( '123.4e-5' ), '12345' );
+ }
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 3f31827f5ef..2a972c8f247 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4658,6 +4658,12 @@ importers:
tools/compare-perf:
dependencies:
+ '@tsconfig/node16':
+ specifier: ^1.0.4
+ version: 1.0.4
+ '@types/node':
+ specifier: ^16.18.68
+ version: 16.18.68
'@wordpress/env':
specifier: ^10.1.0
version: 10.5.0
@@ -4673,6 +4679,12 @@ importers:
simple-git:
specifier: ^3.21.0
version: 3.21.0
+ ts-node:
+ specifier: ^10.9.2
+ version: 10.9.2(@swc/core@1.3.100)(@types/node@16.18.68)(typescript@5.3.3)
+ tslib:
+ specifier: ^2.6.2
+ version: 2.6.3
tools/monorepo-merge:
dependencies:
diff --git a/tools/compare-perf/index.js b/tools/compare-perf/index.js
index d14680f9bf0..beca567b34c 100755
--- a/tools/compare-perf/index.js
+++ b/tools/compare-perf/index.js
@@ -15,12 +15,17 @@ const catchException = ( command ) => {
};
};
-const ciOption = [ '-c, --ci', 'Run in CI (non interactive)' ];
-
program
.command( 'compare-performance [branches...]' )
.alias( 'perf' )
- .option( ...ciOption )
+ .option(
+ '-c, --ci',
+ 'Run in CI (non interactive)'
+ )
+ .option(
+ '--skip-benchmarking',
+ 'Skips benchmarking and gets straight to reporting phase (tests results already available)'
+ )
.option(
'--rounds
',
'Run each test suite this many times for each branch; results are summarized, default = 1'
diff --git a/tools/compare-perf/package.json b/tools/compare-perf/package.json
index 430d64146e5..424decbe36d 100644
--- a/tools/compare-perf/package.json
+++ b/tools/compare-perf/package.json
@@ -7,15 +7,19 @@
"license": "GPLv2",
"repository": "woocommerce/woocommerce",
"scripts": {
- "compare": "node index.js",
+ "compare": "node -r ts-node/register index.js",
"log": "node log-to-codevitals.js"
},
"dependencies": {
+ "@types/node": "^16.18.68",
+ "@tsconfig/node16": "^1.0.4",
"@wordpress/env": "^10.1.0",
"commander": "9.5.0",
"chalk": "^4.1.2",
"inquirer": "^7.1.0",
- "simple-git": "^3.21.0"
+ "simple-git": "^3.21.0",
+ "ts-node": "^10.9.2",
+ "tslib": "^2.6.2"
},
"engines": {
"node": "^20.11.1",
diff --git a/tools/compare-perf/performance.js b/tools/compare-perf/performance.js
index 47315f382ef..527ad2a914e 100644
--- a/tools/compare-perf/performance.js
+++ b/tools/compare-perf/performance.js
@@ -13,71 +13,27 @@ const formats = {
};
const {
runShellScript,
- readJSONFile,
askForConfirmation,
getFilesFromDir,
+ logAtIndent,
+ sanitizeBranchName,
} = require( './utils' );
const config = require( './config' );
+const { processPerformanceReports } = require( './process-reports.ts' );
const ARTIFACTS_PATH =
process.env.WP_ARTIFACTS_PATH || path.join( process.cwd(), 'artifacts' );
-const RESULTS_FILE_SUFFIX = '.performance-results.json';
/**
* @typedef WPPerformanceCommandOptions
*
- * @property {boolean=} ci Run on CI.
- * @property {number=} rounds Run each test suite this many times for each branch.
- * @property {string=} testsBranch The branch whose performance test files will be used for testing.
- * @property {string=} wpVersion The WordPress version to be used as the base install for testing.
+ * @property {boolean=} ci Run on CI.
+ * @property {number=} rounds Run each test suite this many times for each branch.
+ * @property {string=} testsBranch The branch whose performance test files will be used for testing.
+ * @property {boolean=} skipBenchmarking Skip benchmarking and get to report processing (reports supplied from outside).
+ * @property {string=} wpVersion The WordPress version to be used as the base install for testing.
*/
-/**
- * A logging helper for printing steps and their substeps.
- *
- * @param {number} indent Value to indent the log.
- * @param {any} msg Message to log.
- * @param {...any} args Rest of the arguments to pass to console.log.
- */
-function logAtIndent( indent, msg, ...args ) {
- const prefix = indent === 0 ? '▶ ' : '> ';
- const newline = indent === 0 ? '\n' : '';
- return console.log(
- newline + ' '.repeat( indent ) + prefix + msg,
- ...args
- );
-}
-
-/**
- * Sanitizes branch name to be used in a path or a filename.
- *
- * @param {string} branch
- *
- * @return {string} Sanitized branch name.
- */
-function sanitizeBranchName( branch ) {
- return branch.replace( /[^a-zA-Z0-9-]/g, '-' );
-}
-
-/**
- * Computes the median number from an array numbers.
- *
- * @param {number[]} array
- *
- * @return {number|undefined} Median value or undefined if array empty.
- */
-function median( array ) {
- if ( ! array || ! array.length ) return undefined;
-
- const numbers = [ ...array ].sort( ( a, b ) => a - b );
- const middleIndex = Math.floor( numbers.length / 2 );
-
- if ( numbers.length % 2 === 0 ) {
- return ( numbers[ middleIndex - 1 ] + numbers[ middleIndex ] ) / 2;
- }
- return numbers[ middleIndex ];
-}
-
/**
* Runs the performance tests on the current branch.
*
@@ -106,6 +62,7 @@ async function runTestSuite( testSuite, testRunnerDir, runKey ) {
*/
async function runPerformanceTests( branches, options ) {
const runningInCI = !! process.env.CI || !! options.ci;
+ const skipBenchmarking = !! options.skipBenchmarking;
const TEST_ROUNDS = options.rounds || 1;
// The default value doesn't work because commander provides an array.
@@ -129,6 +86,20 @@ async function runPerformanceTests( branches, options ) {
await askForConfirmation( 'Ready to go? ' );
}
+ if ( skipBenchmarking ) {
+ // When benchmarking is skipped, it's expected that artifacts folder contains reports for the branches.
+ // If so, we'll process reports and pick test suites as per current state of codebase.
+ const testSuites = getFilesFromDir(
+ path.resolve( __dirname, '../..' ) + config.testsPath
+ ).map( ( file ) => {
+ logAtIndent( 1, 'Found:', formats.success( file ) );
+ return path.basename( file, '.spec.js' );
+ } );
+
+ await processPerformanceReports( testSuites, branches );
+ return;
+ }
+
logAtIndent( 0, 'Setting up' );
/**
@@ -140,7 +111,6 @@ async function runPerformanceTests( branches, options ) {
}
const baseDir = path.join( os.tmpdir(), 'wp-performance-tests' );
-
if ( fs.existsSync( baseDir ) ) {
logAtIndent( 1, 'Removing existing files' );
fs.rmSync( baseDir, { recursive: true } );
@@ -350,82 +320,7 @@ async function runPerformanceTests( branches, options ) {
}
}
- logAtIndent( 0, 'Calculating results' );
-
- const resultFiles = getFilesFromDir( ARTIFACTS_PATH ).filter( ( file ) =>
- file.endsWith( RESULTS_FILE_SUFFIX )
- );
- /** @type {Record>>} */
- const results = {};
-
- // Calculate medians from all rounds.
- for ( const testSuite of testSuites ) {
- logAtIndent( 1, 'Test suite:', formats.success( testSuite ) );
-
- results[ testSuite ] = {};
- for ( const branch of branches ) {
- const sanitizedBranchName = sanitizeBranchName( branch );
- const resultsRounds = resultFiles
- .filter( ( file ) =>
- file.includes(
- `/${ testSuite }_${ sanitizedBranchName }_round-`
- )
- )
- .map( ( file ) => {
- logAtIndent( 2, 'Reading from:', formats.success( file ) );
- return readJSONFile( file );
- } );
-
- const metrics = Object.keys( resultsRounds[ 0 ] );
- results[ testSuite ][ branch ] = {};
-
- for ( const metric of metrics ) {
- const values = resultsRounds
- .map( ( round ) => round[ metric ] )
- .filter( ( value ) => typeof value === 'number' );
-
- const value = median( values );
- if ( value !== undefined ) {
- results[ testSuite ][ branch ][ metric ] = value;
- }
- }
- }
- const calculatedResultsPath = path.join(
- ARTIFACTS_PATH,
- testSuite + RESULTS_FILE_SUFFIX
- );
-
- logAtIndent(
- 2,
- 'Saving curated results to:',
- formats.success( calculatedResultsPath )
- );
- fs.writeFileSync(
- calculatedResultsPath,
- JSON.stringify( results[ testSuite ], null, 2 )
- );
- }
-
- logAtIndent( 0, 'Printing results' );
-
- for ( const testSuite of testSuites ) {
- logAtIndent( 0, formats.success( testSuite ) );
-
- // Invert the results so we can display them in a table.
- /** @type {Record>} */
- const invertedResult = {};
- for ( const [ branch, metrics ] of Object.entries(
- results[ testSuite ]
- ) ) {
- for ( const [ metric, value ] of Object.entries( metrics ) ) {
- invertedResult[ metric ] = invertedResult[ metric ] || {};
- invertedResult[ metric ][ branch ] = `${ value } ms`;
- }
- }
-
- // Print the results.
- console.table( invertedResult );
- }
+ await processPerformanceReports( testSuites, branches );
}
module.exports = {
diff --git a/tools/compare-perf/process-reports.ts b/tools/compare-perf/process-reports.ts
new file mode 100644
index 00000000000..ec2684161e9
--- /dev/null
+++ b/tools/compare-perf/process-reports.ts
@@ -0,0 +1,119 @@
+/**
+ * External dependencies
+ */
+const bold = require( 'chalk' );
+const fs = require( 'fs' );
+const path = require( 'path' );
+
+/**
+ * Internal dependencies
+ */
+const {
+ getFilesFromDir,
+ readJSONFile,
+ logAtIndent,
+ sanitizeBranchName,
+ median
+} = require( './utils' ) ;
+
+const formats = {
+ success: bold.green,
+};
+
+const ARTIFACTS_PATH =
+ process.env.WP_ARTIFACTS_PATH || path.join( process.cwd(), 'artifacts' );
+const RESULTS_FILE_SUFFIX = '.performance-results.json';
+
+/**
+ * Calculates and prints results from the generated reports.
+ *
+ * @param {string[]} testSuites Test suites we are aiming.
+ * @param {string[]} branches Branches we are aiming.
+ */
+async function processPerformanceReports(
+ testSuites: string[],
+ branches: string[]
+): Promise< void > {
+ logAtIndent( 0, 'Calculating results' );
+
+ const resultFiles = getFilesFromDir( ARTIFACTS_PATH ).filter(
+ ( file: string ) => file.endsWith( RESULTS_FILE_SUFFIX )
+ );
+ const results: Record<
+ string,
+ Record< string, Record< string, number > >
+ > = {};
+
+ // Calculate medians from all rounds.
+ for ( const testSuite of testSuites ) {
+ logAtIndent( 1, 'Test suite:', formats.success( testSuite ) );
+
+ results[ testSuite ] = {};
+ for ( const branch of branches ) {
+ const sanitizedBranchName = sanitizeBranchName( branch );
+ const resultsRounds: any[] = resultFiles
+ .filter( ( file: string ) =>
+ file.includes(
+ `/${ testSuite }_${ sanitizedBranchName }_round-`
+ )
+ )
+ .map( ( file: string ) => {
+ logAtIndent( 2, 'Reading from:', formats.success( file ) );
+ return readJSONFile( file );
+ } );
+
+ const metrics = Object.keys( resultsRounds[ 0 ] );
+ results[ testSuite ][ branch ] = {};
+
+ for ( const metric of metrics ) {
+ const values = resultsRounds
+ .map( ( round ) => round[ metric ] )
+ .filter( ( value ) => typeof value === 'number' );
+
+ const value = median( values );
+ if ( value !== undefined ) {
+ results[ testSuite ][ branch ][ metric ] = value;
+ }
+ }
+ }
+ const calculatedResultsPath = path.join(
+ ARTIFACTS_PATH,
+ testSuite + RESULTS_FILE_SUFFIX
+ );
+
+ logAtIndent(
+ 2,
+ 'Saving curated results to:',
+ formats.success( calculatedResultsPath )
+ );
+ fs.writeFileSync(
+ calculatedResultsPath,
+ JSON.stringify( results[ testSuite ], null, 2 )
+ );
+ }
+
+ logAtIndent( 0, 'Printing results' );
+
+ for ( const testSuite of testSuites ) {
+ logAtIndent( 0, formats.success( testSuite ) );
+
+ // Invert the results, so we can display them in a table.
+ const invertedResult: Record< string, Record< string, string > > = {};
+ for ( const [ branch, metrics ] of Object.entries(
+ results[ testSuite ]
+ ) ) {
+ for ( const [ metric, value ] of Object.entries( metrics ) ) {
+ invertedResult[ metric ] = invertedResult[ metric ] || {};
+ invertedResult[ metric ][ branch ] = `${ value } ms`;
+ }
+ }
+
+ // Print the results.
+ // eslint-disable-next-line no-console
+ console.table( invertedResult );
+ }
+}
+
+module.exports = {
+ processPerformanceReports,
+};
diff --git a/tools/compare-perf/tsconfig.json b/tools/compare-perf/tsconfig.json
new file mode 100644
index 00000000000..d491017bfb9
--- /dev/null
+++ b/tools/compare-perf/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "extends": "./node_modules/@tsconfig/node16/tsconfig.json",
+ "compilerOptions": {
+ "module": "Node16",
+ "moduleResolution": "Node16",
+ "typeRoots": [
+ "./typings",
+ "./node_modules/@types"
+ ]
+ },
+ "ts-node": {
+ "transpileOnly": true,
+ "files": true,
+ },
+}
diff --git a/tools/compare-perf/utils.js b/tools/compare-perf/utils.js
index 2cca3b1a781..4a47cb41ded 100644
--- a/tools/compare-perf/utils.js
+++ b/tools/compare-perf/utils.js
@@ -97,9 +97,58 @@ function getFilesFromDir( dir ) {
.map( ( dirent ) => path.join( dir, dirent.name ) );
}
+/**
+ * A logging helper for printing steps and their substeps.
+ *
+ * @param {number} indent Value to indent the log.
+ * @param {any} msg Message to log.
+ * @param {...any} args Rest of the arguments to pass to console.log.
+ */
+function logAtIndent( indent, msg, ...args ) {
+ const prefix = indent === 0 ? '▶ ' : '> ';
+ const newline = indent === 0 ? '\n' : '';
+ return console.log(
+ newline + ' '.repeat( indent ) + prefix + msg,
+ ...args
+ );
+}
+
+/**
+ * Sanitizes branch name to be used in a path or a filename.
+ *
+ * @param {string} branch
+ *
+ * @return {string} Sanitized branch name.
+ */
+function sanitizeBranchName( branch ) {
+ return branch.replace( /[^a-zA-Z0-9-]/g, '-' );
+}
+
+/**
+ * Computes the median number from an array numbers.
+ *
+ * @param {number[]} array
+ *
+ * @return {number|undefined} Median value or undefined if array empty.
+ */
+function median( array ) {
+ if ( ! array || ! array.length ) return undefined;
+
+ const numbers = [ ...array ].sort( ( a, b ) => a - b );
+ const middleIndex = Math.floor( numbers.length / 2 );
+
+ if ( numbers.length % 2 === 0 ) {
+ return ( numbers[ middleIndex - 1 ] + numbers[ middleIndex ] ) / 2;
+ }
+ return numbers[ middleIndex ];
+}
+
module.exports = {
askForConfirmation,
readJSONFile,
runShellScript,
getFilesFromDir,
+ logAtIndent,
+ sanitizeBranchName,
+ median
};