Fix/update playwright and test fixes (#34790)

* Update Playwright 1.22.1 -> 1.26.0

* Update page title locator

* Wait for View cart link after adding to cart

* Add a wait when applying second coupon

* Fix flakey coupon test

* Ensure Store is in US

* Add changelog

* Revert lock file commit

This reverts commit b75192f53c.

* Updated lock file

* Added command for Playwright test execution

* Resolve merge conflict

* Resolve merge conflict

* Fixed pnpm-lock.json

* Update PW Selectors (#34959)

* Updated PW selectors

* Updated selector

* Removed extra command

* Ensure Billing country is set

* Fix failing payment setup test

* Old test is still running in actions

* Adds colour output for Playwright in GH Actions

* Fix payment test

* Lock file update

* Skipping a test for now

Co-authored-by: Jon Lane <jon.lane@automattic.com>
Co-authored-by: jamelreid <jnoelreid@gmail.com>
Co-authored-by: Jamel Noel Reid <MrJnrman@users.noreply.github.com>
This commit is contained in:
Jonathan Lane 2022-10-07 11:39:39 -07:00 committed by GitHub
parent c32eb268cf
commit aa438e5741
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 316 additions and 219 deletions

View File

@ -15,7 +15,7 @@ jobs:
E2E_GRAND_TOTAL: ${{ steps.count_e2e_total.outputs.E2E_GRAND_TOTAL }} E2E_GRAND_TOTAL: ${{ steps.count_e2e_total.outputs.E2E_GRAND_TOTAL }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup WooCommerce Monorepo - name: Setup WooCommerce Monorepo
uses: ./.github/actions/setup-woocommerce-monorepo uses: ./.github/actions/setup-woocommerce-monorepo
@ -42,6 +42,7 @@ jobs:
env: env:
USE_WP_ENV: 1 USE_WP_ENV: 1
E2E_MAX_FAILURES: 15 E2E_MAX_FAILURES: 15
FORCE_COLOR: 1
working-directory: plugins/woocommerce working-directory: plugins/woocommerce
run: pnpm exec playwright test --config=tests/e2e-pw/playwright.config.js run: pnpm exec playwright test --config=tests/e2e-pw/playwright.config.js
@ -76,7 +77,7 @@ jobs:
API_TEST_REPORT_DIR: ${{ github.workspace }}/api-test-report API_TEST_REPORT_DIR: ${{ github.workspace }}/api-test-report
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup WooCommerce Monorepo - name: Setup WooCommerce Monorepo
uses: ./.github/actions/setup-woocommerce-monorepo uses: ./.github/actions/setup-woocommerce-monorepo
@ -92,7 +93,7 @@ jobs:
USER_KEY: admin USER_KEY: admin
USER_SECRET: password USER_SECRET: password
run: pnpm exec playwright test --config=tests/api-core-tests/playwright.config.js run: pnpm exec playwright test --config=tests/api-core-tests/playwright.config.js
- name: Generate Playwright API Test report. - name: Generate Playwright API Test report.
id: generate_api_report id: generate_api_report
if: | if: |
@ -121,15 +122,15 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup WooCommerce Monorepo - name: Setup WooCommerce Monorepo
uses: ./.github/actions/setup-woocommerce-monorepo uses: ./.github/actions/setup-woocommerce-monorepo
- name: Load docker images and start containers. - name: Load docker images and start containers.
working-directory: plugins/woocommerce working-directory: plugins/woocommerce
run: | run: |
pnpm env:dev --filter=woocommerce pnpm env:dev --filter=woocommerce
pnpm env:performance-init --filter=woocommerce pnpm env:performance-init --filter=woocommerce
- name: Install k6 - name: Install k6
run: | run: |
@ -236,4 +237,4 @@ jobs:
-f pr_number=$PR_NUMBER \ -f pr_number=$PR_NUMBER \
-f commit_sha=$COMMIT_SHA \ -f commit_sha=$COMMIT_SHA \
-f s3_root=public \ -f s3_root=public \
--repo woocommerce/woocommerce-test-reports --repo woocommerce/woocommerce-test-reports

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Update Playwright to 1.26.0 and fix a few flaky tests

View File

@ -0,0 +1,4 @@
Significance: patch
Type: update
Updates a few css selectors to be more robust

View File

@ -33,6 +33,7 @@
"docker:up": "pnpm exec wc-e2e docker:up", "docker:up": "pnpm exec wc-e2e docker:up",
"env:dev": "pnpm wp-env start", "env:dev": "pnpm wp-env start",
"env:test": "pnpm run env:dev && ./tests/e2e-pw/bin/test-env-setup.sh", "env:test": "pnpm run env:dev && ./tests/e2e-pw/bin/test-env-setup.sh",
"e2e-pw": "USE_WP_ENV=1 pnpm playwright test --config=tests/e2e-pw/playwright.config.js",
"env:test:cot": "pnpm run env:dev && ./tests/e2e-pw/bin/test-env-setup.sh --cot", "env:test:cot": "pnpm run env:dev && ./tests/e2e-pw/bin/test-env-setup.sh --cot",
"env:performance-init": "./tests/performance/bin/init-sample-products.sh", "env:performance-init": "./tests/performance/bin/init-sample-products.sh",
"env:down": "pnpm wp-env stop", "env:down": "pnpm wp-env stop",
@ -50,7 +51,7 @@
"@babel/core": "7.12.9", "@babel/core": "7.12.9",
"@babel/preset-env": "7.12.7", "@babel/preset-env": "7.12.7",
"@babel/register": "7.12.1", "@babel/register": "7.12.1",
"@playwright/test": "^1.22.1", "@playwright/test": "^1.26.1",
"@typescript-eslint/eslint-plugin": "3.10.1", "@typescript-eslint/eslint-plugin": "3.10.1",
"@typescript-eslint/experimental-utils": "3.10.1", "@typescript-eslint/experimental-utils": "3.10.1",
"@typescript-eslint/parser": "3.10.1", "@typescript-eslint/parser": "3.10.1",
@ -81,6 +82,7 @@
"istanbul": "1.0.0-alpha.2", "istanbul": "1.0.0-alpha.2",
"jest": "^27.5.1", "jest": "^27.5.1",
"mocha": "7.2.0", "mocha": "7.2.0",
"playwright": "^1.26.1",
"prettier": "npm:wp-prettier@2.0.5", "prettier": "npm:wp-prettier@2.0.5",
"stylelint": "^13.8.0", "stylelint": "^13.8.0",
"typescript": "^4.8.3", "typescript": "^4.8.3",

View File

@ -1,121 +1,118 @@
const { test, expect } = require( '@playwright/test' ); const { test, expect } = require('@playwright/test');
const { onboarding } = require( '../../utils' ); const { onboarding } = require('../../utils');
const { storeDetails } = require( '../../test-data/data' ); const { storeDetails } = require('../../test-data/data');
test.describe( 'Store owner can complete onboarding wizard', () => { test.describe('Store owner can complete onboarding wizard', () => {
test.use( { storageState: process.env.ADMINSTATE } ); test.use({ storageState: process.env.ADMINSTATE });
test.beforeEach( async ( { page } ) => { test.beforeEach(async ({ page }) => {
await onboarding.completeStoreDetailsSection( await onboarding.completeStoreDetailsSection(
page, page,
storeDetails.us.store storeDetails.us.store
); );
} ); });
// eslint-disable-next-line jest/expect-expect // eslint-disable-next-line jest/expect-expect
test( 'can complete the industry section', async ( { page } ) => { test('can complete the industry section', async ({ page }) => {
await onboarding.completeIndustrySection( await onboarding.completeIndustrySection(
page, page,
storeDetails.us.industries, storeDetails.us.industries,
storeDetails.us.expectedIndustries storeDetails.us.expectedIndustries
); );
await page.click( 'button >> text=Continue' ); await page.click('button >> text=Continue');
} ); });
// eslint-disable-next-line jest/expect-expect // eslint-disable-next-line jest/expect-expect
test( 'can complete the product types section', async ( { page } ) => { test('can complete the product types section', async ({ page }) => {
await onboarding.completeProductTypesSection( await onboarding.completeProductTypesSection(
page, page,
storeDetails.us.products storeDetails.us.products
); );
await page.click( 'button >> text=Continue' ); await page.click('button >> text=Continue');
} ); });
// eslint-disable-next-line jest/expect-expect // eslint-disable-next-line jest/expect-expect
test( 'can complete the business section', async ( { page } ) => { test('can complete the business section', async ({ page }) => {
// We have to ensure that previous steps are complete to avoid generating an error // We have to ensure that previous steps are complete to avoid generating an error
await onboarding.completeIndustrySection( await onboarding.completeIndustrySection(
page, page,
storeDetails.us.industries, storeDetails.us.industries,
storeDetails.us.expectedIndustries storeDetails.us.expectedIndustries
); );
await page.click( 'button >> text=Continue' ); await page.click('button >> text=Continue');
await onboarding.completeProductTypesSection( await onboarding.completeProductTypesSection(
page, page,
storeDetails.us.products storeDetails.us.products
); );
await page.click( 'button >> text=Continue' ); await page.click('button >> text=Continue');
await onboarding.completeBusinessDetailsSection( page ); await onboarding.completeBusinessDetailsSection(page);
await page.click( 'button >> text=Continue' ); await page.click('button >> text=Continue');
} ); });
// eslint-disable-next-line jest/expect-expect // eslint-disable-next-line jest/expect-expect
test( 'can unselect all business features and continue', async ( { test.skip('can unselect all business features and continue', async ({
page, page,
} ) => { }) => {
// We have to ensure that previous steps are complete to avoid generating an error // We have to ensure that previous steps are complete to avoid generating an error
await onboarding.completeIndustrySection( await onboarding.completeIndustrySection(
page, page,
storeDetails.us.industries, storeDetails.us.industries,
storeDetails.us.expectedIndustries storeDetails.us.expectedIndustries
); );
await page.click( 'button >> text=Continue' ); // Check to see if WC Payments is present
const wcPay = await page.locator(
'.woocommerce-admin__business-details__selective-extensions-bundle__description a[href*=woocommerce-payments]'
);
await onboarding.completeProductTypesSection( await onboarding.completeProductTypesSection(
page, page,
storeDetails.us.products storeDetails.us.products
); );
await page.click( 'button >> text=Continue' );
await onboarding.completeBusinessDetailsSection( page ); await onboarding.unselectBusinessFeatures(page);
await page.click( 'button >> text=Continue' ); await page.click('button >> text=Continue');
});
await onboarding.unselectBusinessFeatures( page ); test('can complete the theme selection section', async ({ page }) => {
await page.click( 'button >> text=Continue' );
} );
test( 'can complete the theme selection section', async ( { page } ) => {
await page.goto( await page.goto(
'wp-admin/admin.php?page=wc-admin&path=%2Fsetup-wizard&step=theme' 'wp-admin/admin.php?page=wc-admin&path=%2Fsetup-wizard&step=theme'
); );
const pageHeading = await page.textContent( const pageHeading = await page.textContent(
'div.woocommerce-profile-wizard__step-header > h2' 'div.woocommerce-profile-wizard__step-header > h2'
); );
expect( pageHeading ).toContain( 'Choose a theme' ); expect(pageHeading).toContain('Choose a theme');
// Just continue with the current theme // Just continue with the current theme
await page.click( 'button >> text=Continue with my active theme' ); await page.click('button >> text=Continue with my active theme');
} ); });
} ); });
// !Changed from Japanese to Malta store, as Japanese Yen does not use decimals // !Changed from Japanese to Malta store, as Japanese Yen does not use decimals
test.describe( test.describe(
'A Malta store can complete the selective bundle install but does not include WCPay.', 'A Malta store can complete the selective bundle install but does not include WCPay.',
() => { () => {
test.use( { storageState: process.env.ADMINSTATE } ); test.use({ storageState: process.env.ADMINSTATE });
test.beforeEach( async ( { page } ) => { test.beforeEach(async ({ page }) => {
await onboarding.completeStoreDetailsSection( await onboarding.completeStoreDetailsSection(
page, page,
storeDetails.malta.store storeDetails.malta.store
); );
} ); });
// eslint-disable-next-line jest/expect-expect // eslint-disable-next-line jest/expect-expect
test( 'can choose the "Other" industry', async ( { page } ) => { test('can choose the "Other" industry', async ({ page }) => {
await onboarding.completeIndustrySection( await onboarding.completeIndustrySection(
page, page,
storeDetails.malta.industries, storeDetails.malta.industries,
storeDetails.malta.expectedIndustries storeDetails.malta.expectedIndustries
); );
await page.click( 'button >> text=Continue' ); await page.click('button >> text=Continue');
} ); });
// eslint-disable-next-line jest/expect-expect // eslint-disable-next-line jest/expect-expect
test( 'can choose not to install any extensions', async ( { test('can choose not to install any extensions', async ({ page }) => {
page,
} ) => {
const expect_wp_pay = false; const expect_wp_pay = false;
await onboarding.completeIndustrySection( await onboarding.completeIndustrySection(
@ -123,102 +120,106 @@ test.describe(
storeDetails.malta.industries, storeDetails.malta.industries,
storeDetails.malta.expectedIndustries storeDetails.malta.expectedIndustries
); );
await page.click( 'button >> text=Continue' ); await page.click('button >> text=Continue');
await onboarding.completeProductTypesSection( await onboarding.completeProductTypesSection(
page, page,
storeDetails.malta.products storeDetails.malta.products
); );
await page.click( 'button >> text=Continue' ); // Make sure WC Payments is NOT present
await expect(
page.locator(
'.woocommerce-admin__business-details__selective-extensions-bundle__description a[href*=woocommerce-payments]'
)
).toHaveCount(0);
await onboarding.completeBusinessDetailsSection( page ); await page.click('button >> text=Continue');
await page.click( 'button >> text=Continue' );
await onboarding.unselectBusinessFeatures( page, expect_wp_pay ); await onboarding.completeBusinessDetailsSection(page);
await page.click( 'button >> text=Continue' ); await page.click('button >> text=Continue');
} );
await onboarding.unselectBusinessFeatures(page, expect_wp_pay);
await page.click('button >> text=Continue');
});
// Skipping this test because it's very flaky. Onboarding checklist changed so that the text // Skipping this test because it's very flaky. Onboarding checklist changed so that the text
// changes when a task is completed. // changes when a task is completed.
// eslint-disable-next-line jest/no-disabled-tests // eslint-disable-next-line jest/no-disabled-tests
test.skip( 'should display the choose payments task, and not the WC Pay task', async ( { test.skip('should display the choose payments task, and not the WC Pay task', async ({
page, page,
} ) => { }) => {
// If payment has previously been setup, the setup checklist will show something different // If payment has previously been setup, the setup checklist will show something different
// This step resets it // This step resets it
await page.goto( await page.goto('wp-admin/admin.php?page=wc-settings&tab=checkout');
'wp-admin/admin.php?page=wc-settings&tab=checkout'
);
// Ensure that all payment methods are disabled // Ensure that all payment methods are disabled
await expect( await expect(
page.locator( '.woocommerce-input-toggle--disabled' ) page.locator('.woocommerce-input-toggle--disabled')
).toHaveCount( 3 ); ).toHaveCount(3);
// Checklist shows when completing setup wizard // Checklist shows when completing setup wizard
await page.goto( await page.goto(
'wp-admin/admin.php?page=wc-admin&path=%2Fsetup-wizard&step=theme' 'wp-admin/admin.php?page=wc-admin&path=%2Fsetup-wizard&step=theme'
); );
await page.click( 'button >> text=Continue with my active theme' ); await page.click('button >> text=Continue with my active theme');
// Start test // Start test
await page.waitForLoadState( 'networkidle' ); await page.waitForLoadState('networkidle');
await expect( await expect(
page.locator( page.locator(
':nth-match(.woocommerce-task-list__item-title, 3)' ':nth-match(.woocommerce-task-list__item-title, 3)'
) )
).toContainText( 'Set up payments' ); ).toContainText('Set up payments');
await expect( await expect(
page.locator( page.locator(
':nth-match(.woocommerce-task-list__item-title, 3)' ':nth-match(.woocommerce-task-list__item-title, 3)'
) )
).not.toContainText( 'Set up WooCommerce Payments' ); ).not.toContainText('Set up WooCommerce Payments');
} ); });
} }
); );
// Skipping this test because it's very flaky. // Skipping this test because it's very flaky.
test.describe.skip( 'Store owner can go through setup Task List', () => { test.describe.skip('Store owner can go through setup Task List', () => {
test.use( { storageState: process.env.ADMINSTATE } ); test.use({ storageState: process.env.ADMINSTATE });
test.beforeEach( async ( { page } ) => { test.beforeEach(async ({ page }) => {
await page.goto( await page.goto('wp-admin/admin.php?page=wc-admin&path=/setup-wizard');
'wp-admin/admin.php?page=wc-admin&path=/setup-wizard' await page.click('#woocommerce-select-control-0__control-input');
);
await page.click( '#woocommerce-select-control-0__control-input' );
await page.fill( await page.fill(
'#woocommerce-select-control-0__control-input', '#woocommerce-select-control-0__control-input',
'United States (US) — California' 'United States (US) — California'
); );
await page.click( 'button >> text=United States (US) — California' ); await page.click('button >> text=United States (US) — California');
await page.fill( '#inspector-text-control-0', 'addr 1' ); await page.fill('#inspector-text-control-0', 'addr 1');
await page.fill( '#inspector-text-control-1', '94107' ); await page.fill('#inspector-text-control-1', '94107');
await page.fill( '#inspector-text-control-2', 'San Francisco' ); await page.fill('#inspector-text-control-2', 'San Francisco');
await page.fill( await page.fill(
'#inspector-text-control-3', '#inspector-text-control-3',
storeDetails.us.store.email storeDetails.us.store.email
); );
await page.check( '#inspector-checkbox-control-0' ); await page.check('#inspector-checkbox-control-0');
await page.click( 'button >> text=Continue' ); await page.click('button >> text=Continue');
await page.click( 'button >> text=No thanks' ); await page.click('button >> text=No thanks');
await page.click( 'button >> text=Continue' ); await page.click('button >> text=Continue');
await page.click( 'button >> text=Continue' ); await page.click('button >> text=Continue');
await page.click( 'button >> text=Continue' ); await page.click('button >> text=Continue');
// Uncheck all business features // Uncheck all business features
if ( page.isChecked( '.components-checkbox-control__input' ) ) { if (page.isChecked('.components-checkbox-control__input')) {
await page.click( '.components-checkbox-control__input' ); await page.click('.components-checkbox-control__input');
} }
await page.click( 'button >> text=Continue' ); await page.click('button >> text=Continue');
await page.click( 'button >> text=Continue with my active theme' ); await page.click('button >> text=Continue with my active theme');
await page.waitForLoadState( 'networkidle' ); // not autowaiting for form submission await page.waitForLoadState('networkidle'); // not autowaiting for form submission
} ); });
test( 'can setup shipping', async ( { page } ) => { test('can setup shipping', async ({ page }) => {
await page.goto( '/wp-admin/admin.php?page=wc-admin' ); await page.goto('/wp-admin/admin.php?page=wc-admin');
await page.click( 'div >> text=Review Shipping Options' ); await page.click('div >> text=Review Shipping Options');
// dismiss tourkit if visible // dismiss tourkit if visible
const tourkitVisible = await page const tourkitVisible = await page
.locator( 'button.woocommerce-tour-kit-step-controls__close-btn' ) .locator('button.woocommerce-tour-kit-step-controls__close-btn')
.isVisible(); .isVisible();
if ( tourkitVisible ) { if (tourkitVisible) {
await page.click( await page.click(
'button.woocommerce-tour-kit-step-controls__close-btn' 'button.woocommerce-tour-kit-step-controls__close-btn'
); );
@ -226,15 +227,15 @@ test.describe.skip( 'Store owner can go through setup Task List', () => {
// check for automatically added shipping zone // check for automatically added shipping zone
await expect( await expect(
page.locator( 'tr[data-id="1"] >> td.wc-shipping-zone-name > a' ) page.locator('tr[data-id="1"] >> td.wc-shipping-zone-name > a')
).toContainText( 'United States (US)' ); ).toContainText('United States (US)');
await expect( await expect(
page.locator( 'tr[data-id="1"] >> td.wc-shipping-zone-region' ) page.locator('tr[data-id="1"] >> td.wc-shipping-zone-region')
).toContainText( 'United States (US)' ); ).toContainText('United States (US)');
await expect( await expect(
page.locator( page.locator(
'tr[data-id="1"] >> td.wc-shipping-zone-methods > div > ul > li' 'tr[data-id="1"] >> td.wc-shipping-zone-methods > div > ul > li'
) )
).toContainText( 'Free shipping' ); ).toContainText('Free shipping');
} ); });
} ); });

View File

@ -1,108 +1,125 @@
const { test, expect } = require( '@playwright/test' ); const { test, expect } = require('@playwright/test');
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default; const wcApi = require('@woocommerce/woocommerce-rest-api').default;
test.describe( 'Payment setup task', () => { test.describe('Payment setup task', () => {
test.use( { storageState: process.env.ADMINSTATE } ); test.use({ storageState: process.env.ADMINSTATE });
test.beforeEach( async ( { page } ) => { test.beforeEach(async ({ page }) => {
await page.goto( await page.goto('wp-admin/admin.php?page=wc-admin&path=/setup-wizard');
'wp-admin/admin.php?page=wc-admin&path=/setup-wizard' await page.click('text=Skip setup store details');
); await page.click('text=No thanks');
await page.click( 'text=Skip setup store details' ); await page.waitForLoadState('networkidle');
await page.click( 'text=No thanks' ); });
await page.waitForLoadState( 'networkidle' );
} );
test.afterAll( async ( { baseURL } ) => { test.afterAll(async ({ baseURL }) => {
const api = new wcApi( { const api = new wcApi({
url: baseURL, url: baseURL,
consumerKey: process.env.CONSUMER_KEY, consumerKey: process.env.CONSUMER_KEY,
consumerSecret: process.env.CONSUMER_SECRET, consumerSecret: process.env.CONSUMER_SECRET,
version: 'wc/v3', version: 'wc/v3',
} ); });
await api.put( 'payment_gateways/bacs', { await api.put('payment_gateways/bacs', {
enabled: false, enabled: false,
} ); });
await api.put( 'payment_gateways/cod', { await api.put('payment_gateways/cod', {
enabled: false, enabled: false,
} ); });
} ); });
test( 'Can visit the payment setup task from the homescreen if the setup wizard has been skipped', async ( { test('Can visit the payment setup task from the homescreen if the setup wizard has been skipped', async ({
page, page,
} ) => { }) => {
await page.goto( 'wp-admin/admin.php?page=wc-admin' ); await page.goto('wp-admin/admin.php?page=wc-admin');
await page.click( 'text=Set up payments' ); await page.click('text=Set up payments');
await expect( page.locator( 'h1' ) ).toHaveText( 'Set up payments' ); await expect(page.locator('h1')).toHaveText('Set up payments');
} ); });
test( 'Saving valid bank account transfer details enables the payment method', async ( { test('Saving valid bank account transfer details enables the payment method', async ({
page, page,
} ) => { }) => {
// load the bank transfer page // load the bank transfer page
await page.goto( await page.goto(
'wp-admin/admin.php?page=wc-admin&task=payments&id=bacs' 'wp-admin/admin.php?page=wc-admin&task=payments&id=bacs'
); );
// purposely no await -- close the help dialog if/when it appears // purposely no await -- close the help dialog if/when it appears
page.locator( '.components-button.is-small.has-icon' ) page.locator('.components-button.is-small.has-icon')
.click() .click()
.catch( () => {} ); .catch(() => {});
// fill in bank transfer form // fill in bank transfer form
await page.fill( '//input[@placeholder="Account name"]', 'Savings' ); await page.fill('//input[@placeholder="Account name"]', 'Savings');
await page.fill( '//input[@placeholder="Account number"]', '1234' ); await page.fill('//input[@placeholder="Account number"]', '1234');
await page.fill( '//input[@placeholder="Bank name"]', 'Test Bank' ); await page.fill('//input[@placeholder="Bank name"]', 'Test Bank');
await page.fill( '//input[@placeholder="Sort code"]', '12' ); await page.fill('//input[@placeholder="Sort code"]', '12');
await page.fill( '//input[@placeholder="IBAN"]', '12 3456 7890' ); await page.fill('//input[@placeholder="IBAN"]', '12 3456 7890');
await page.fill( '//input[@placeholder="BIC / Swift"]', 'ABBA' ); await page.fill('//input[@placeholder="BIC / Swift"]', 'ABBA');
await page.click( 'text=Save' ); await page.click('text=Save');
// check that bank transfers were set up // check that bank transfers were set up
await expect( await expect(
page.locator( 'div.components-snackbar__content' ) page.locator('div.components-snackbar__content')
).toContainText( 'Direct bank transfer details added successfully' ); ).toContainText('Direct bank transfer details added successfully');
await page.goto( 'wp-admin/admin.php?page=wc-settings&tab=checkout' ); await page.goto('wp-admin/admin.php?page=wc-settings&tab=checkout');
await expect( await expect(
page.locator( page.locator('//tr[@data-gateway_id="bacs"]/td[@class="status"]/a')
'//tr[@data-gateway_id="bacs"]/td[@class="status"]/a' ).toHaveClass('wc-payment-gateway-method-toggle-enabled');
) });
).toHaveClass( 'wc-payment-gateway-method-toggle-enabled' );
} );
test( 'Enabling cash on delivery enables the payment method', async ( { test('Enabling cash on delivery enables the payment method', async ({
page, page,
} ) => { baseURL,
await page.goto( 'wp-admin/admin.php?page=wc-admin&task=payments' ); }) => {
// Payments page differs if located outside of a WCPay-supported country, so make sure we aren't.
const api = new wcApi({
url: baseURL,
consumerKey: process.env.CONSUMER_KEY,
consumerSecret: process.env.CONSUMER_SECRET,
version: 'wc/v3',
});
// ensure store address is US
await api.post('settings/general/batch', {
update: [
{
id: 'woocommerce_store_address',
value: 'addr 1',
},
{
id: 'woocommerce_store_city',
value: 'San Francisco',
},
{
id: 'woocommerce_default_country',
value: 'US:CA',
},
{
id: 'woocommerce_store_postcode',
value: '94107',
},
],
});
await page.goto('wp-admin/admin.php?page=wc-admin&task=payments');
// purposely no await -- close the help dialog if/when it appears // purposely no await -- close the help dialog if/when it appears
page.locator( '.components-button.is-small.has-icon' ) page.locator('.components-button.is-small.has-icon')
.click() .click()
.catch( () => {} ); .catch(() => {});
await page.waitForLoadState('networkidle');
await page.waitForLoadState( 'networkidle' ); // purposely no await again
page.click('button.toggle-button');
if (
( await page.isVisible( 'text=Offline payment methods' ) ) ||
( await page.isVisible( 'text=Additional payment gateways' ) )
) {
// other payment methods are already shown
} else {
// show other payment methods
await page.click( 'button.toggle-button' );
}
// enable COD payment option // enable COD payment option
await page.click( await page.click(
'div.woocommerce-task-payment-cod > div.woocommerce-task-payment__footer > button' 'div.woocommerce-task-payment-cod > div.woocommerce-task-payment__footer > button'
); );
await page.waitForLoadState( 'networkidle' ); await page.waitForLoadState('networkidle');
await page.goto( 'wp-admin/admin.php?page=wc-settings&tab=checkout' ); await page.goto('wp-admin/admin.php?page=wc-settings&tab=checkout');
await expect( await expect(
page.locator( '//tr[@data-gateway_id="cod"]/td[@class="status"]/a' ) page.locator('//tr[@data-gateway_id="cod"]/td[@class="status"]/a')
).toHaveClass( 'wc-payment-gateway-method-toggle-enabled' ); ).toHaveClass('wc-payment-gateway-method-toggle-enabled');
} ); });
} ); });

View File

@ -199,7 +199,7 @@ test.describe( 'WooCommerce Orders > Add new order', () => {
test( 'can create new order', async ( { page } ) => { test( 'can create new order', async ( { page } ) => {
await page.goto( 'wp-admin/post-new.php?post_type=shop_order' ); await page.goto( 'wp-admin/post-new.php?post_type=shop_order' );
await expect( page.locator( 'title' ) ).toContainText( await expect( page.locator( 'h1.wp-heading-inline' ) ).toContainText(
'Add new order' 'Add new order'
); );

View File

@ -113,8 +113,10 @@ test.describe( 'Cart applying coupons', () => {
); );
await page.waitForLoadState( 'networkidle' ); await page.waitForLoadState( 'networkidle' );
// try to apply the same coupon // try to apply the same coupon
await page.goto( '/cart/' );
await page.fill( '#coupon_code', coupons[ 0 ].code ); await page.fill( '#coupon_code', coupons[ 0 ].code );
await page.click( 'text=Apply coupon' ); await page.click( 'text=Apply coupon' );
await page.waitForLoadState( 'networkidle' );
// error received // error received
await expect( page.locator( '.woocommerce-error' ) ).toContainText( await expect( page.locator( '.woocommerce-error' ) ).toContainText(
'Coupon code already applied!' 'Coupon code already applied!'
@ -138,6 +140,7 @@ test.describe( 'Cart applying coupons', () => {
); );
await page.waitForLoadState( 'networkidle' ); await page.waitForLoadState( 'networkidle' );
await page.click( '#coupon_code' );
await page.fill( '#coupon_code', coupons[ 2 ].code ); await page.fill( '#coupon_code', coupons[ 2 ].code );
await page.click( 'text=Apply coupon' ); await page.click( 'text=Apply coupon' );
// successful // successful

View File

@ -55,7 +55,9 @@ test.describe( 'Cart > Redirect to cart from shop', () => {
test( 'can redirect user to cart from shop page', async ( { page } ) => { test( 'can redirect user to cart from shop page', async ( { page } ) => {
await page.goto( '/shop/' ); await page.goto( '/shop/' );
await page.click( `a:below(:text("${ productName }"))` ); await page.click(
`a[data-product_id='${ productId }'][href*=add-to-cart]`
);
await page.waitForLoadState( 'networkidle' ); await page.waitForLoadState( 'networkidle' );
await expect( page.url() ).toContain( '/cart/' ); await expect( page.url() ).toContain( '/cart/' );

View File

@ -59,7 +59,9 @@ test.describe( 'Cart page', () => {
page, page,
} ) => { } ) => {
await page.goto( '/shop/' ); await page.goto( '/shop/' );
await page.click( `a:below(:text("${ productName }"))` ); await page.click(
`a[data-product_id='${ productId }'][href*=add-to-cart]`
);
await page.waitForLoadState( 'networkidle' ); await page.waitForLoadState( 'networkidle' );
await page.goto( '/cart/' ); await page.goto( '/cart/' );
@ -72,13 +74,17 @@ test.describe( 'Cart page', () => {
page, page,
} ) => { } ) => {
await page.goto( '/shop/' ); await page.goto( '/shop/' );
await page.click( `a:below(:text("${ productName }"))` ); await page.click(
`a[data-product_id='${ productId }'][href*=add-to-cart]`
);
// Once the view cart link is visible, item has been added // Once the view cart link is visible, item has been added
await page.waitForLoadState( 'networkidle' ); await page.waitForSelector( 'a.added_to_cart' );
// Click add to cart a second time (load the shop in case redirection enabled) // Click add to cart a second time (load the shop in case redirection enabled)
await page.goto( '/shop/' ); await page.goto( '/shop/' );
await page.click( `a:below(:text("${ productName }"))` ); await page.click(
await page.waitForLoadState( 'networkidle' ); `a[data-product_id='${ productId }'][href*=add-to-cart]`
);
await page.waitForSelector( 'a.added_to_cart' );
await page.goto( '/cart/' ); await page.goto( '/cart/' );
await expect( page.locator( 'input.qty' ) ).toHaveValue( '2' ); await expect( page.locator( 'input.qty' ) ).toHaveValue( '2' );
@ -88,7 +94,9 @@ test.describe( 'Cart page', () => {
page, page,
} ) => { } ) => {
await page.goto( '/shop/' ); await page.goto( '/shop/' );
await page.click( `a:below(:text("${ productName }"))` ); await page.click(
`a[data-product_id='${ productId }'][href*=add-to-cart]`
);
await page.waitForLoadState( 'networkidle' ); await page.waitForLoadState( 'networkidle' );
await page.goto( '/cart/' ); await page.goto( '/cart/' );
@ -104,7 +112,9 @@ test.describe( 'Cart page', () => {
page, page,
} ) => { } ) => {
await page.goto( '/shop/' ); await page.goto( '/shop/' );
await page.click( `a:below(:text("${ productName }"))` ); await page.click(
`a[data-product_id='${ productId }'][href*=add-to-cart]`
);
await page.waitForLoadState( 'networkidle' ); await page.waitForLoadState( 'networkidle' );
await page.goto( '/cart/' ); await page.goto( '/cart/' );
@ -124,7 +134,9 @@ test.describe( 'Cart page', () => {
page, page,
} ) => { } ) => {
await page.goto( '/shop/' ); await page.goto( '/shop/' );
await page.click( `a:below(:text("${ productName }"))` ); await page.click(
`a[data-product_id='${ productId }'][href*=add-to-cart]`
);
await page.waitForLoadState( 'networkidle' ); await page.waitForLoadState( 'networkidle' );
await page.goto( '/cart/' ); await page.goto( '/cart/' );
@ -144,7 +156,9 @@ test.describe( 'Cart page', () => {
page, page,
} ) => { } ) => {
await page.goto( '/shop/' ); await page.goto( '/shop/' );
await page.click( `a:below(:text("${ productName }"))` ); await page.click(
`a[data-product_id='${ productId }'][href*=add-to-cart]`
);
await page.waitForLoadState( 'networkidle' ); await page.waitForLoadState( 'networkidle' );
await page.goto( '/cart/' ); await page.goto( '/cart/' );

View File

@ -13,6 +13,27 @@ test.describe( 'Shopper Checkout Create Account', () => {
consumerSecret: process.env.CONSUMER_SECRET, consumerSecret: process.env.CONSUMER_SECRET,
version: 'wc/v3', version: 'wc/v3',
} ); } );
// ensure store address is US
await api.post( 'settings/general/batch', {
update: [
{
id: 'woocommerce_store_address',
value: 'addr 1',
},
{
id: 'woocommerce_store_city',
value: 'San Francisco',
},
{
id: 'woocommerce_default_country',
value: 'US:CA',
},
{
id: 'woocommerce_store_postcode',
value: '94107',
},
],
} );
// add product // add product
await api await api
.post( 'products', { .post( 'products', {

View File

@ -19,6 +19,27 @@ test.describe( 'Checkout page', () => {
consumerSecret: process.env.CONSUMER_SECRET, consumerSecret: process.env.CONSUMER_SECRET,
version: 'wc/v3', version: 'wc/v3',
} ); } );
// ensure store address is US
await api.post( 'settings/general/batch', {
update: [
{
id: 'woocommerce_store_address',
value: 'addr 1',
},
{
id: 'woocommerce_store_city',
value: 'San Francisco',
},
{
id: 'woocommerce_default_country',
value: 'US:CA',
},
{
id: 'woocommerce_store_postcode',
value: '94107',
},
],
} );
// add product // add product
await api await api
.post( 'products', { .post( 'products', {
@ -276,6 +297,7 @@ test.describe( 'Checkout page', () => {
await page.fill( '#billing_last_name', 'Simpson' ); await page.fill( '#billing_last_name', 'Simpson' );
await page.fill( '#billing_address_1', '123 Evergreen Terrace' ); await page.fill( '#billing_address_1', '123 Evergreen Terrace' );
await page.fill( '#billing_city', 'Springfield' ); await page.fill( '#billing_city', 'Springfield' );
await page.selectOption( '#billing_country', 'US' );
await page.selectOption( '#billing_state', 'OR' ); await page.selectOption( '#billing_state', 'OR' );
await page.fill( '#billing_postcode', '97403' ); await page.fill( '#billing_postcode', '97403' );
await page.fill( '#billing_phone', '555 555-5555' ); await page.fill( '#billing_phone', '555 555-5555' );

View File

@ -16,6 +16,27 @@ test.describe( 'Shopper Order Email Receiving', () => {
consumerSecret: process.env.CONSUMER_SECRET, consumerSecret: process.env.CONSUMER_SECRET,
version: 'wc/v3', version: 'wc/v3',
} ); } );
// ensure store address is US
await api.post( 'settings/general/batch', {
update: [
{
id: 'woocommerce_store_address',
value: 'addr 1',
},
{
id: 'woocommerce_store_city',
value: 'San Francisco',
},
{
id: 'woocommerce_default_country',
value: 'US:CA',
},
{
id: 'woocommerce_store_postcode',
value: '94107',
},
],
} );
// add product // add product
await api await api
.post( 'products', { .post( 'products', {
@ -78,6 +99,7 @@ test.describe( 'Shopper Order Email Receiving', () => {
await page.fill( '#billing_last_name', 'Simpson' ); await page.fill( '#billing_last_name', 'Simpson' );
await page.fill( '#billing_address_1', '123 Evergreen Terrace' ); await page.fill( '#billing_address_1', '123 Evergreen Terrace' );
await page.fill( '#billing_city', 'Springfield' ); await page.fill( '#billing_city', 'Springfield' );
await page.selectOption( '#billing_country', 'US' );
await page.selectOption( '#billing_state', 'OR' ); await page.selectOption( '#billing_state', 'OR' );
await page.fill( '#billing_postcode', '97403' ); await page.fill( '#billing_postcode', '97403' );
await page.fill( '#billing_phone', '555 555-5555' ); await page.fill( '#billing_phone', '555 555-5555' );

View File

@ -1281,7 +1281,7 @@ importers:
'@babel/core': 7.12.9 '@babel/core': 7.12.9
'@babel/preset-env': 7.12.7 '@babel/preset-env': 7.12.7
'@babel/register': 7.12.1 '@babel/register': 7.12.1
'@playwright/test': ^1.22.1 '@playwright/test': ^1.26.1
'@typescript-eslint/eslint-plugin': 3.10.1 '@typescript-eslint/eslint-plugin': 3.10.1
'@typescript-eslint/experimental-utils': 3.10.1 '@typescript-eslint/experimental-utils': 3.10.1
'@typescript-eslint/parser': 3.10.1 '@typescript-eslint/parser': 3.10.1
@ -1312,6 +1312,7 @@ importers:
istanbul: 1.0.0-alpha.2 istanbul: 1.0.0-alpha.2
jest: ^27.5.1 jest: ^27.5.1
mocha: 7.2.0 mocha: 7.2.0
playwright: ^1.26.1
prettier: npm:wp-prettier@2.0.5 prettier: npm:wp-prettier@2.0.5
stylelint: ^13.8.0 stylelint: ^13.8.0
typescript: ^4.8.3 typescript: ^4.8.3
@ -1324,7 +1325,7 @@ importers:
'@babel/core': 7.12.9 '@babel/core': 7.12.9
'@babel/preset-env': 7.12.7_@babel+core@7.12.9 '@babel/preset-env': 7.12.7_@babel+core@7.12.9
'@babel/register': 7.12.1_@babel+core@7.12.9 '@babel/register': 7.12.1_@babel+core@7.12.9
'@playwright/test': 1.25.2 '@playwright/test': 1.26.1
'@typescript-eslint/eslint-plugin': 3.10.1_emvgcsyrrniq64kkwdpw54irvu '@typescript-eslint/eslint-plugin': 3.10.1_emvgcsyrrniq64kkwdpw54irvu
'@typescript-eslint/experimental-utils': 3.10.1_gjkzpvg3kr4mru3ob5fvm4vice '@typescript-eslint/experimental-utils': 3.10.1_gjkzpvg3kr4mru3ob5fvm4vice
'@typescript-eslint/parser': 3.10.1_gjkzpvg3kr4mru3ob5fvm4vice '@typescript-eslint/parser': 3.10.1_gjkzpvg3kr4mru3ob5fvm4vice
@ -1355,6 +1356,7 @@ importers:
istanbul: 1.0.0-alpha.2 istanbul: 1.0.0-alpha.2
jest: 27.5.1 jest: 27.5.1
mocha: 7.2.0 mocha: 7.2.0
playwright: 1.26.1
prettier: /wp-prettier/2.0.5 prettier: /wp-prettier/2.0.5
stylelint: 13.13.1 stylelint: 13.13.1
typescript: 4.8.4 typescript: 4.8.4
@ -8451,13 +8453,13 @@ packages:
dependencies: dependencies:
'@octokit/openapi-types': 13.10.0 '@octokit/openapi-types': 13.10.0
/@playwright/test/1.25.2: /@playwright/test/1.26.1:
resolution: {integrity: sha512-6qPznIR4Fw02OMbqXUPMG6bFFg1hDVNEdihKy0t9K0dmRbus1DyP5Q5XFQhGwEHQkLG5hrSfBuu9CW/foqhQHQ==} resolution: {integrity: sha512-bNxyZASVt2adSZ9gbD7NCydzcb5JaI0OR9hc7s+nmPeH604gwp0zp17NNpwXY4c8nvuBGQQ9oGDx72LE+cUWvw==}
engines: {node: '>=14'} engines: {node: '>=14'}
hasBin: true hasBin: true
dependencies: dependencies:
'@types/node': 17.0.21 '@types/node': 17.0.21
playwright-core: 1.25.2 playwright-core: 1.26.1
dev: true dev: true
/@pmmmwh/react-refresh-webpack-plugin/0.5.1_a3gyllrqvxpec3fpybsrposvju: /@pmmmwh/react-refresh-webpack-plugin/0.5.1_a3gyllrqvxpec3fpybsrposvju:
@ -31757,12 +31759,21 @@ packages:
find-up: 5.0.0 find-up: 5.0.0
dev: true dev: true
/playwright-core/1.25.2: /playwright-core/1.26.1:
resolution: {integrity: sha512-0yTbUE9lIddkEpLHL3u8PoCL+pWiZtj5A/j3U7YoNjcmKKDGBnCrgHJMzwd2J5vy6l28q4ki3JIuz7McLHhl1A==} resolution: {integrity: sha512-hzFchhhxnEiPc4qVPs9q2ZR+5eKNifY2hQDHtg1HnTTUuphYCBP8ZRb2si+B1TR7BHirgXaPi48LIye5SgrLAA==}
engines: {node: '>=14'} engines: {node: '>=14'}
hasBin: true hasBin: true
dev: true dev: true
/playwright/1.26.1:
resolution: {integrity: sha512-WQmEdCgYYe8jOEkhkW9QLcK0PB+w1RZztBLYIT10MEEsENYg251cU0IzebDINreQsUt+HCwwRhtdz4weH9ICcQ==}
engines: {node: '>=14'}
hasBin: true
requiresBuild: true
dependencies:
playwright-core: 1.26.1
dev: true
/plur/4.0.0: /plur/4.0.0:
resolution: {integrity: sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==} resolution: {integrity: sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -32535,33 +32546,6 @@ packages:
svgo: 2.8.0 svgo: 2.8.0
dev: true dev: true
/postcss-syntax/0.36.2_kei4jy7wdgbhc236h4oijypxom:
resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==}
peerDependencies:
postcss: '>=5.0.0'
postcss-html: '*'
postcss-jsx: '*'
postcss-less: '*'
postcss-markdown: '*'
postcss-scss: '*'
peerDependenciesMeta:
postcss-html:
optional: true
postcss-jsx:
optional: true
postcss-less:
optional: true
postcss-markdown:
optional: true
postcss-scss:
optional: true
dependencies:
postcss: 7.0.39
postcss-html: 0.36.0_j55xdkkcxc32kvnyvx3y7casfm
postcss-less: 3.1.4
postcss-scss: 2.1.1
dev: true
/postcss-syntax/0.36.2_postcss@7.0.39: /postcss-syntax/0.36.2_postcss@7.0.39:
resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==} resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==}
peerDependencies: peerDependencies:
@ -36644,7 +36628,7 @@ packages:
postcss-sass: 0.4.4 postcss-sass: 0.4.4
postcss-scss: 2.1.1 postcss-scss: 2.1.1
postcss-selector-parser: 6.0.6 postcss-selector-parser: 6.0.6
postcss-syntax: 0.36.2_kei4jy7wdgbhc236h4oijypxom postcss-syntax: 0.36.2_postcss@7.0.39
postcss-value-parser: 4.1.0 postcss-value-parser: 4.1.0
resolve-from: 5.0.0 resolve-from: 5.0.0
slash: 3.0.0 slash: 3.0.0
@ -37236,7 +37220,7 @@ packages:
serialize-javascript: 6.0.0 serialize-javascript: 6.0.0
source-map: 0.6.1 source-map: 0.6.1
terser: 5.10.0_acorn@8.7.0 terser: 5.10.0_acorn@8.7.0
webpack: 5.70.0 webpack: 5.70.0_webpack-cli@3.3.12
transitivePeerDependencies: transitivePeerDependencies:
- acorn - acorn