Merge branch 'trunk' into oginomizuho-patch-1
This commit is contained in:
commit
c87551b6c0
|
@ -0,0 +1,26 @@
|
||||||
|
name: Milestone Manager
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [milestoned]
|
||||||
|
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
remove-milestone-from-unmerged-prs:
|
||||||
|
name: "Remove Milestone from Unmerged PRs"
|
||||||
|
if: github.event.pull_request.merged != true
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
github.rest.issues.update({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.payload.pull_request.number,
|
||||||
|
milestone: null,
|
||||||
|
});
|
|
@ -38,9 +38,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
php-version: '7.4'
|
php-version: '7.4'
|
||||||
- name: 'Run the script to assign a milestone'
|
- name: 'Run the script to assign a milestone'
|
||||||
if: |
|
if: github.event.pull_request.base.ref == 'trunk'
|
||||||
!github.event.pull_request.milestone &&
|
|
||||||
github.event.pull_request.base.ref == 'trunk'
|
|
||||||
run: php assign-milestone-to-merged-pr.php
|
run: php assign-milestone-to-merged-pr.php
|
||||||
env:
|
env:
|
||||||
PULL_REQUEST_ID: ${{ github.event.pull_request.node_id }}
|
PULL_REQUEST_ID: ${{ github.event.pull_request.node_id }}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/**
|
||||||
|
* Set the stalebot start date given a cron schedule.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// You need to install this dependency as part of your workflow.
|
||||||
|
const core = require( '@actions/core' );
|
||||||
|
|
||||||
|
const ScheduleStartDate = () => {
|
||||||
|
let scheduleStartDate;
|
||||||
|
|
||||||
|
switch ( process.env.CRON_SCHEDULE ) {
|
||||||
|
case '21 1 * * *':
|
||||||
|
scheduleStartDate = '2022-01-01';
|
||||||
|
break;
|
||||||
|
case '31 2 * * *':
|
||||||
|
scheduleStartDate = '2023-01-01';
|
||||||
|
break;
|
||||||
|
case '41 3 * * *':
|
||||||
|
scheduleStartDate = '2023-08-01';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
scheduleStartDate = '2018-01-01';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
core.setOutput( 'stale-start-date', scheduleStartDate );
|
||||||
|
};
|
||||||
|
|
||||||
|
ScheduleStartDate();
|
|
@ -1,7 +1,10 @@
|
||||||
name: 'Close stale needs-feedback issues'
|
name: 'Process stale needs-feedback issues'
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '21 0 * * *'
|
- cron: '11 0 * * *'
|
||||||
|
- cron: '21 1 * * *'
|
||||||
|
- cron: '31 2 * * *'
|
||||||
|
- cron: '41 3 * * *'
|
||||||
|
|
||||||
permissions: {}
|
permissions: {}
|
||||||
|
|
||||||
|
@ -13,10 +16,20 @@ jobs:
|
||||||
issues: write
|
issues: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v8
|
- name: Install Actions Core
|
||||||
|
run: npm --prefix .github/workflows/scripts install @actions/core
|
||||||
|
|
||||||
|
- name: Get start date
|
||||||
|
id: startdate
|
||||||
|
run: node .github/workflows/scripts/stalebot.js
|
||||||
|
env:
|
||||||
|
CRON_SCHEDULE: ${{ github.event.schedule }}
|
||||||
|
- name: Scan issues
|
||||||
|
uses: actions/stale@v8
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
operations-per-run: 40
|
operations-per-run: 8
|
||||||
|
start-date: steps.startdate.outputs.stale-start-date
|
||||||
stale-issue-message: "As a part of this repository's maintenance, this issue is being marked as stale due to inactivity. Please feel free to comment on it in case we missed something.\n\n###### After 7 days with no activity this issue will be automatically be closed."
|
stale-issue-message: "As a part of this repository's maintenance, this issue is being marked as stale due to inactivity. Please feel free to comment on it in case we missed something.\n\n###### After 7 days with no activity this issue will be automatically be closed."
|
||||||
close-issue-message: 'This issue was closed because it has been 14 days with no activity.'
|
close-issue-message: 'This issue was closed because it has been 14 days with no activity.'
|
||||||
days-before-issue-stale: 7
|
days-before-issue-stale: 7
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: update
|
||||||
|
|
||||||
|
Allow plugins to access PostTypeContext and blocks (through core/block-editor data store).
|
|
@ -5,6 +5,7 @@ import { synchronizeBlocksWithTemplate, Template } from '@wordpress/blocks';
|
||||||
import { createElement, useMemo, useLayoutEffect } from '@wordpress/element';
|
import { createElement, useMemo, useLayoutEffect } from '@wordpress/element';
|
||||||
import { useDispatch, useSelect, select as WPSelect } from '@wordpress/data';
|
import { useDispatch, useSelect, select as WPSelect } from '@wordpress/data';
|
||||||
import { uploadMedia } from '@wordpress/media-utils';
|
import { uploadMedia } from '@wordpress/media-utils';
|
||||||
|
import { PluginArea } from '@wordpress/plugins';
|
||||||
import {
|
import {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore No types for this exist yet.
|
// @ts-ignore No types for this exist yet.
|
||||||
|
@ -32,6 +33,7 @@ import {
|
||||||
*/
|
*/
|
||||||
import { useConfirmUnsavedProductChanges } from '../../hooks/use-confirm-unsaved-product-changes';
|
import { useConfirmUnsavedProductChanges } from '../../hooks/use-confirm-unsaved-product-changes';
|
||||||
import { ProductEditorContext } from '../../types';
|
import { ProductEditorContext } from '../../types';
|
||||||
|
import { PostTypeContext } from '../../contexts/post-type-context';
|
||||||
|
|
||||||
type BlockEditorProps = {
|
type BlockEditorProps = {
|
||||||
context: Partial< ProductEditorContext >;
|
context: Partial< ProductEditorContext >;
|
||||||
|
@ -120,6 +122,11 @@ export function BlockEditor( {
|
||||||
<BlockList className="woocommerce-product-block-editor__block-list" />
|
<BlockList className="woocommerce-product-block-editor__block-list" />
|
||||||
</ObserveTyping>
|
</ObserveTyping>
|
||||||
</BlockTools>
|
</BlockTools>
|
||||||
|
{ /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */ }
|
||||||
|
<PostTypeContext.Provider value={ context.postType! }>
|
||||||
|
{ /* @ts-expect-error 'scope' does exist. @types/wordpress__plugins is outdated. */ }
|
||||||
|
<PluginArea scope="woocommerce-product-block-editor" />
|
||||||
|
</PostTypeContext.Provider>
|
||||||
</BlockEditorProvider>
|
</BlockEditorProvider>
|
||||||
</BlockContextProvider>
|
</BlockContextProvider>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,7 +7,6 @@ import {
|
||||||
Fragment,
|
Fragment,
|
||||||
useState,
|
useState,
|
||||||
} from '@wordpress/element';
|
} from '@wordpress/element';
|
||||||
import { PluginArea } from '@wordpress/plugins';
|
|
||||||
import {
|
import {
|
||||||
LayoutContextProvider,
|
LayoutContextProvider,
|
||||||
useExtendLayout,
|
useExtendLayout,
|
||||||
|
@ -90,8 +89,6 @@ export function Editor( {
|
||||||
postId: product.id,
|
postId: product.id,
|
||||||
} }
|
} }
|
||||||
/>
|
/>
|
||||||
{ /* @ts-expect-error 'scope' does exist. @types/wordpress__plugins is outdated. */ }
|
|
||||||
<PluginArea scope="woocommerce-product-block-editor" />
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import { createContext } from '@wordpress/element';
|
||||||
|
|
||||||
|
export const PostTypeContext = createContext( 'product' );
|
|
@ -20,5 +20,6 @@ export * from './utils';
|
||||||
* Hooks
|
* Hooks
|
||||||
*/
|
*/
|
||||||
export * from './hooks';
|
export * from './hooks';
|
||||||
|
export { PostTypeContext } from './contexts/post-type-context';
|
||||||
export { useValidation, useValidations } from './contexts/validation-context';
|
export { useValidation, useValidations } from './contexts/validation-context';
|
||||||
export * from './contexts/validation-context/types';
|
export * from './contexts/validation-context/types';
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: update
|
||||||
|
|
||||||
|
Add stalebot schedules to allow processing of all issues
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: dev
|
||||||
|
|
||||||
|
Adds e2e tests for tax display in store, cart and checkout
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: fix
|
||||||
|
|
||||||
|
Fixed warning on wc_get_product_variation_attributes when product does not exist
|
|
@ -685,7 +685,7 @@ function wc_get_product_id_by_sku( $sku ) {
|
||||||
*/
|
*/
|
||||||
function wc_get_product_variation_attributes( $variation_id ) {
|
function wc_get_product_variation_attributes( $variation_id ) {
|
||||||
// Build variation data from meta.
|
// Build variation data from meta.
|
||||||
$all_meta = get_post_meta( $variation_id );
|
$all_meta = is_array( get_post_meta( $variation_id ) ) ? get_post_meta( $variation_id ) : array();
|
||||||
$parent_id = wp_get_post_parent_id( $variation_id );
|
$parent_id = wp_get_post_parent_id( $variation_id );
|
||||||
$parent_attributes = array_filter( (array) get_post_meta( $parent_id, '_product_attributes', true ) );
|
$parent_attributes = array_filter( (array) get_post_meta( $parent_id, '_product_attributes', true ) );
|
||||||
$found_parent_attributes = array();
|
$found_parent_attributes = array();
|
||||||
|
|
|
@ -0,0 +1,695 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||||
|
const { admin, customer } = require( '../../test-data/data' );
|
||||||
|
|
||||||
|
const productName = 'Taxed products are awesome';
|
||||||
|
const productPrice = '100.00';
|
||||||
|
const messyProductPrice = '13.47';
|
||||||
|
const secondProductName = 'Other products are also awesome';
|
||||||
|
|
||||||
|
let productId, productId2, nastyTaxId, seventeenTaxId, sixTaxId, countryTaxId, stateTaxId, cityTaxId, zipTaxId, shippingTaxId, shippingZoneId, shippingMethodId;
|
||||||
|
|
||||||
|
test.describe( 'Shopper Tax Display Tests', () => {
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/general/woocommerce_calc_taxes', {
|
||||||
|
value: 'yes',
|
||||||
|
} );
|
||||||
|
await api.post( 'products', {
|
||||||
|
name: productName,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: productPrice,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
productId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.post( 'taxes', {
|
||||||
|
"country": "US",
|
||||||
|
"state": "*",
|
||||||
|
"cities": "*",
|
||||||
|
"postcodes": "*",
|
||||||
|
"rate": "25",
|
||||||
|
"name": "Nasty Tax",
|
||||||
|
"shipping": false
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
nastyTaxId = response.data.id;
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { page, context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
await context.clearCookies();
|
||||||
|
|
||||||
|
// all tests use the first product
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId }`, { waitUntil: 'networkidle' } );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_cart', {
|
||||||
|
value: 'excl',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_shop', {
|
||||||
|
value: 'excl'
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_price_display_suffix', {
|
||||||
|
value: '',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/general/woocommerce_calc_taxes', {
|
||||||
|
value: 'no',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_total_display', {
|
||||||
|
value: 'itemized',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ productId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `taxes/${ nastyTaxId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'checks that taxes are calculated properly on totals, inclusive tax displayed properly', async ( { page, baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_cart', {
|
||||||
|
value: 'incl',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_shop', {
|
||||||
|
value: 'incl'
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load shop page and confirm price display', async() => {
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Shop' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole('link', { name: 'Placeholder Taxed products are awesome $125.00' }).first() ).toBeVisible();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load cart page and confirm price display', async() => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Cart', exact: true } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'cell', { name: '$125.00 (incl. tax)' } ) ).toHaveCount(2);
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Subtotal $125.00 (incl. tax)'} ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Total $125.00 (includes $25.00 Nasty Tax)' } ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load checkout page and confirm price display', async() => {
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Checkout' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Taxed products are awesome × 1 $125.00 (incl. tax)' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Subtotal $125.00 (incl. tax)' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Total $125.00 (includes $25.00 Nasty Tax)'} ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'checks that taxes are calculated and displayed correctly exclusive on shop, cart and checkout', async ( { page, baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_cart', {
|
||||||
|
value: 'excl',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_shop', {
|
||||||
|
value: 'excl'
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load shop page and confirm price display', async() => {
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Shop' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole('link', { name: 'Placeholder Taxed products are awesome $100.00' }).first() ).toBeVisible();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load cart page and confirm price display', async() => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Cart', exact: true } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'cell', { name: '$100.00' } ) ).toHaveCount(3);
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Subtotal $100.00'} ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Tax $25.00' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Total $125.00' } ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load checkout page and confirm price display', async() => {
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Checkout' } ) ).toBeVisible();
|
||||||
|
|
||||||
|
await page.locator( '#billing_first_name' ).fill( customer.billing.us.first_name );
|
||||||
|
await page.locator( '#billing_last_name' ).fill( customer.billing.us.last_name );
|
||||||
|
await page.locator( '#billing_address_1' ).fill( customer.billing.us.address );
|
||||||
|
await page.locator( '#billing_city' ).fill( customer.billing.us.city );
|
||||||
|
await page.locator( '#billing_country' ).selectOption( customer.billing.us.country );
|
||||||
|
await page.locator( '#billing_state' ).selectOption( customer.billing.us.state );
|
||||||
|
await page.locator( '#billing_postcode' ).fill( customer.billing.us.zip );
|
||||||
|
await page.locator( '#billing_phone' ).fill( customer.billing.us.phone );
|
||||||
|
await page.locator( '#billing_email' ).fill( customer.billing.us.email );
|
||||||
|
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Taxed products are awesome × 1 $100.00' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Subtotal $100.00' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Tax $25.00' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Total $125.00' } ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'checks that display suffix is shown', async ( { page, baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_cart', {
|
||||||
|
value: 'excl',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_shop', {
|
||||||
|
value: 'excl',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_price_display_suffix', {
|
||||||
|
value: 'excluding VAT',
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load shop page and confirm price suffix display', async() => {
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Shop' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole('link', { name: 'Placeholder Taxed products are awesome $100.00 excluding VAT' }).first() ).toBeVisible();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.describe( 'Shopper Tax Rounding', () => {
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/general/woocommerce_calc_taxes', {
|
||||||
|
value: 'yes',
|
||||||
|
} );
|
||||||
|
await api.post( 'products', {
|
||||||
|
name: productName,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: messyProductPrice,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
productId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.post( 'products', {
|
||||||
|
name: secondProductName,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: messyProductPrice,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
productId2 = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.post( 'taxes', {
|
||||||
|
"country": "US",
|
||||||
|
"state": "*",
|
||||||
|
"cities": "*",
|
||||||
|
"postcodes": "*",
|
||||||
|
"rate": "17",
|
||||||
|
"name": "Seventeen Tax",
|
||||||
|
"shipping": false,
|
||||||
|
"compound": true,
|
||||||
|
"priority": 1
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
seventeenTaxId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.post( 'taxes', {
|
||||||
|
"country": "US",
|
||||||
|
"state": "*",
|
||||||
|
"cities": "*",
|
||||||
|
"postcodes": "*",
|
||||||
|
"rate": "6",
|
||||||
|
"name": "Six Tax",
|
||||||
|
"shipping": false,
|
||||||
|
"compound": true,
|
||||||
|
"priority": 2
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
sixTaxId = response.data.id;
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { page, context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
await context.clearCookies();
|
||||||
|
|
||||||
|
// all tests use the first product
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId }`, { waitUntil: 'networkidle' } );
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId2 }`, { waitUntil: 'networkidle' } );
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId2 }`, { waitUntil: 'networkidle' } );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_cart', {
|
||||||
|
value: 'excl',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_shop', {
|
||||||
|
value: 'excl'
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_round_at_subtotal', {
|
||||||
|
value: 'no',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/general/woocommerce_calc_taxes', {
|
||||||
|
value: 'no',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_total_display', {
|
||||||
|
value: 'itemized'
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ productId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ productId2 }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `taxes/${ seventeenTaxId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `taxes/${ sixTaxId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'checks rounding at subtotal level', async ( { page, baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_cart', {
|
||||||
|
value: 'excl',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_shop', {
|
||||||
|
value: 'excl',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_round_at_subtotal', {
|
||||||
|
value: 'yes',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_total_display', {
|
||||||
|
value: 'single',
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load shop page and confirm price display', async() => {
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Shop' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole('link', { name: 'Placeholder Taxed products are awesome $13.47' }).first() ).toBeVisible();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load cart page and confirm price display', async() => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Cart', exact: true } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'cell', { name: '$13.47' } ) ).toHaveCount(3);
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Subtotal $40.41'} ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Tax $9.71 ' } ) ).toBeVisible()
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Total $50.12 ' } ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'checks rounding off at subtotal level', async ( { page, baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_cart', {
|
||||||
|
value: 'excl',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_shop', {
|
||||||
|
value: 'excl',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_round_at_subtotal', {
|
||||||
|
value: 'no',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_total_display', {
|
||||||
|
value: 'itemized',
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load shop page and confirm price display', async() => {
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Shop' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole('link', { name: 'Placeholder Taxed products are awesome $13.47' }).first() ).toBeVisible();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load cart page and confirm price display', async() => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Cart', exact: true } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'cell', { name: '$13.47' } ) ).toHaveCount(3);
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Subtotal $40.41'} ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Seventeen Tax $6.87 ' } ) ).toBeVisible()
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Six Tax $2.84 ' } ) ).toBeVisible()
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Total $50.12 ' } ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.describe( 'Shopper Tax Levels', () => {
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/general/woocommerce_calc_taxes', {
|
||||||
|
value: 'yes',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_cart', {
|
||||||
|
value: 'excl',
|
||||||
|
} );
|
||||||
|
await api.post( 'products', {
|
||||||
|
name: productName,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: productPrice,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
productId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.post( 'taxes', {
|
||||||
|
"country": "US",
|
||||||
|
"state": "*",
|
||||||
|
"cities": "*",
|
||||||
|
"postcodes": "*",
|
||||||
|
"rate": "10",
|
||||||
|
"name": "Country Tax",
|
||||||
|
"shipping": false,
|
||||||
|
"priority": 1
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
countryTaxId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.post( 'taxes', {
|
||||||
|
"country": "*",
|
||||||
|
"state": "CA",
|
||||||
|
"cities": "*",
|
||||||
|
"postcodes": "*",
|
||||||
|
"rate": "5",
|
||||||
|
"name": "State Tax",
|
||||||
|
"shipping": false,
|
||||||
|
"priority": 2
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
stateTaxId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.post( 'taxes', {
|
||||||
|
"country": "*",
|
||||||
|
"state": "*",
|
||||||
|
"cities": "Sacramento",
|
||||||
|
"postcodes": "*",
|
||||||
|
"rate": "2.5",
|
||||||
|
"name": "City Tax",
|
||||||
|
"shipping": false,
|
||||||
|
"priority": 3
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
cityTaxId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.post( 'taxes', {
|
||||||
|
"country": "*",
|
||||||
|
"state": "*",
|
||||||
|
"cities": "*",
|
||||||
|
"postcodes": "55555",
|
||||||
|
"rate": "1.25",
|
||||||
|
"name": "Zip Tax",
|
||||||
|
"shipping": false,
|
||||||
|
"priority": 4
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
zipTaxId = response.data.id;
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { page, context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
await context.clearCookies();
|
||||||
|
|
||||||
|
// all tests use the first product
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId }`, { waitUntil: 'networkidle' } );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_total_display', {
|
||||||
|
value: 'itemized'
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_cart', {
|
||||||
|
value: 'excl',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ productId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
|
||||||
|
await api.delete( `taxes/${ countryTaxId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `taxes/${ stateTaxId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `taxes/${ cityTaxId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `taxes/${ zipTaxId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'checks applying taxes of 4 different levels', async ( { page, baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_total_display', {
|
||||||
|
value: 'itemized',
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load cart page and confirm price display', async() => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Cart', exact: true } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'cell', { name: '$100.00' } ) ).toHaveCount(3);
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Subtotal $100.00'} ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Country Tax $10.00 ' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'State Tax $5.00 ' } ) ).toBeVisible()
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Total $115.00 ' } ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load checkout page and confirm taxes displayed', async() => {
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Checkout', exact: true } ) ).toBeVisible();
|
||||||
|
|
||||||
|
await page.getByLabel('First name *').first().fill( customer.billing.us.first_name );
|
||||||
|
await page.getByLabel('Last name *').first().fill( customer.billing.us.last_name );
|
||||||
|
await page.getByPlaceholder('House number and street name').first().fill( customer.billing.us.address );
|
||||||
|
await page.getByLabel('Town / City *').first().pressSequentially( 'Sacramento' );
|
||||||
|
await page.getByLabel('ZIP Code *').first().pressSequentially( '55555' );
|
||||||
|
await page.getByLabel('Phone *').first().fill( customer.billing.us.phone );
|
||||||
|
await page.getByLabel('Email address *').first().fill( customer.billing.us.email );
|
||||||
|
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Subtotal $100.00'} ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Country Tax $10.00' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'State Tax $5.00' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'City Tax $2.50' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Zip Tax $1.25' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Total $118.75 ' } ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'checks applying taxes of 2 different levels (2 excluded)', async ( { page, baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_total_display', {
|
||||||
|
value: 'itemized',
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load cart page and confirm price display', async() => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Cart', exact: true } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'cell', { name: '$100.00' } ) ).toHaveCount(3);
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Subtotal $100.00'} ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Country Tax $10.00 ' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'State Tax $5.00 ' } ) ).toBeVisible()
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Total $115.00 ' } ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load checkout page and confirm taxes displayed', async() => {
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Checkout', exact: true } ) ).toBeVisible();
|
||||||
|
|
||||||
|
await page.getByLabel('First name *').first().fill( customer.billing.us.first_name );
|
||||||
|
await page.getByLabel('Last name *').first().fill( customer.billing.us.last_name );
|
||||||
|
await page.getByPlaceholder('House number and street name').first().fill( customer.billing.us.address );
|
||||||
|
await page.getByLabel('Town / City *').first().pressSequentially( customer.billing.us.city );
|
||||||
|
await page.getByLabel('ZIP Code *').first().pressSequentially( customer.billing.us.zip );
|
||||||
|
await page.getByLabel('Phone *').first().fill( customer.billing.us.phone );
|
||||||
|
await page.getByLabel('Email address *').first().fill( customer.billing.us.email );
|
||||||
|
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Subtotal $100.00'} ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Country Tax $10.00' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'State Tax $5.00' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'City Tax $2.50' } ) ).not.toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Zip Tax $1.25' } ) ).not.toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Total $115.00 ' } ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.describe( 'Shipping Tax', () => {
|
||||||
|
|
||||||
|
test.beforeAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/general/woocommerce_calc_taxes', {
|
||||||
|
value: 'yes',
|
||||||
|
} );
|
||||||
|
await api.post( 'products', {
|
||||||
|
name: productName,
|
||||||
|
type: 'simple',
|
||||||
|
regular_price: productPrice,
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
productId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.post( 'taxes', {
|
||||||
|
"country": "US",
|
||||||
|
"state": "*",
|
||||||
|
"cities": "*",
|
||||||
|
"postcodes": "*",
|
||||||
|
"rate": "15",
|
||||||
|
"name": "Shipping Tax",
|
||||||
|
"shipping": true
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
shippingTaxId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.post( 'shipping/zones', {
|
||||||
|
name: 'All',
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
shippingZoneId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.post( `shipping/zones/${ shippingZoneId }/methods`, {
|
||||||
|
method_id: 'flat_rate',
|
||||||
|
} )
|
||||||
|
.then( ( response ) => {
|
||||||
|
shippingMethodId = response.data.id;
|
||||||
|
} );
|
||||||
|
await api.put( `shipping/zones/${ shippingZoneId }/methods/${ shippingMethodId }`, {
|
||||||
|
settings: {
|
||||||
|
cost: '20.00',
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
await api.put( 'payment_gateways/cod' , {
|
||||||
|
enabled: true
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/tax/woocommerce_tax_display_cart', {
|
||||||
|
value: 'incl',
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.beforeEach( async ( { page, context } ) => {
|
||||||
|
// Shopping cart is very sensitive to cookies, so be explicit
|
||||||
|
await context.clearCookies();
|
||||||
|
|
||||||
|
// all tests use the first product
|
||||||
|
await page.goto( `/shop/?add-to-cart=${ productId }`, { waitUntil: 'networkidle' } );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async ( { baseURL } ) => {
|
||||||
|
const api = new wcApi( {
|
||||||
|
url: baseURL,
|
||||||
|
consumerKey: process.env.CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.CONSUMER_SECRET,
|
||||||
|
version: 'wc/v3',
|
||||||
|
} );
|
||||||
|
await api.put( 'settings/general/woocommerce_calc_taxes', {
|
||||||
|
value: 'no',
|
||||||
|
} );
|
||||||
|
await api.delete( `products/${ productId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.delete( `taxes/${ shippingTaxId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
await api.put( 'payment_gateways/cod' , {
|
||||||
|
enabled: false
|
||||||
|
} );
|
||||||
|
await api.delete( `shipping/zones/${ shippingZoneId }`, {
|
||||||
|
force: true,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'checks that tax is applied to shipping as well as order', async ( { page, baseURL } ) => {
|
||||||
|
|
||||||
|
await test.step( 'Load cart page and confirm price display', async() => {
|
||||||
|
await page.goto( '/cart/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Cart', exact: true } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'cell', { name: '$115.00 (incl. tax)' } ) ).toHaveCount(2);
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Subtotal $115.00 (incl. tax)'} ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Shipping Flat rate: $23.00 (incl. tax) Shipping to CA.' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Total $138.00 (includes $18.00 Shipping Tax)' } ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( 'Load checkout page and confirm price display', async() => {
|
||||||
|
await page.goto( '/checkout/' );
|
||||||
|
await expect( page.getByRole( 'heading', { name: 'Checkout' } ) ).toBeVisible();
|
||||||
|
|
||||||
|
await page.getByRole('textbox', { name: 'First name *' }).fill( customer.billing.us.first_name );
|
||||||
|
await page.getByRole('textbox', { name: 'Last name *' }).fill( customer.billing.us.last_name );
|
||||||
|
await page.getByRole('textbox', { name: 'Street address *' }).fill( customer.billing.us.address );
|
||||||
|
await page.getByRole('textbox', { name: 'Town / City *' }).type( customer.billing.us.city );
|
||||||
|
await page.getByRole('textbox', { name: 'ZIP Code *' }).type( customer.billing.us.zip );
|
||||||
|
await page.getByLabel('Phone *').fill( customer.billing.us.phone );
|
||||||
|
await page.getByLabel('Email address *').fill( customer.billing.us.email );
|
||||||
|
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Taxed products are awesome × 1 $115.00 (incl. tax)' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Subtotal $115.00 (incl. tax)' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Shipping Flat rate: $23.00 (incl. tax)' } ) ).toBeVisible();
|
||||||
|
await expect( page.getByRole( 'row', { name: 'Total $138.00 (includes $18.00 Shipping Tax)'} ) ).toBeVisible();
|
||||||
|
} );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
} );
|
Loading…
Reference in New Issue