Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Playwright E2E tests: Multiple signed in roles #10561

Merged
merged 40 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
6d0668c
Convert checkout place order E2E tests to Playwright
tarhi-saad Aug 14, 2023
e99ca49
Add "gotoMyAccount" method
tarhi-saad Aug 15, 2023
6e90115
Create login/logout utility functions
tarhi-saad Aug 15, 2023
c71f95e
Use the existing "customer" test data
tarhi-saad Aug 15, 2023
7aa81cc
Complete the place order test cases
tarhi-saad Aug 15, 2023
4b04cdc
Fix "My Account" page title
tarhi-saad Aug 15, 2023
29ae83b
Fix rebase
tarhi-saad Aug 16, 2023
b1ec104
Reset My account page title
tarhi-saad Aug 16, 2023
f4a780a
Check for heading instead of the page title
tarhi-saad Aug 16, 2023
27221a2
Check for heading in login/logout functions
tarhi-saad Aug 16, 2023
263f515
Fix all failing tests
tarhi-saad Aug 16, 2023
768ca6d
Add guest/customer/admin roles
tarhi-saad Aug 17, 2023
a27e226
Update the auth setup
tarhi-saad Aug 18, 2023
fb22c66
Register the auth setup within Playwright
tarhi-saad Aug 18, 2023
3ca7bcd
Update testing cases
tarhi-saad Aug 18, 2023
74598aa
Add generated auth files to .gitignore
tarhi-saad Aug 18, 2023
d54759c
Tidy up comments
tarhi-saad Aug 18, 2023
2552bb5
Remove unnecessary comment
tarhi-saad Aug 18, 2023
f87427a
Update comments
tarhi-saad Aug 18, 2023
913f58b
Remove unnecessary comment
tarhi-saad Aug 18, 2023
84f3d21
Update comment for Guest case
tarhi-saad Aug 18, 2023
3d9fb92
Remove confusing comment
tarhi-saad Aug 18, 2023
dd09d82
Remove another unnecessary comment
tarhi-saad Aug 18, 2023
12d5357
Remove unnecessary Playwright project dependency
tarhi-saad Aug 18, 2023
c254a36
Tidy up the file structure and constants
tarhi-saad Aug 18, 2023
436bc81
Fix mixed up test descriptions
tarhi-saad Aug 18, 2023
27c98e3
Remove commented code
tarhi-saad Aug 18, 2023
73d9b27
Remove unnecessary function from frontend-utils
tarhi-saad Aug 18, 2023
bdc6f19
Refactor testing cases
tarhi-saad Aug 18, 2023
6024135
Rename testing file
tarhi-saad Aug 18, 2023
5f67b4a
Delete unused testing file
tarhi-saad Aug 18, 2023
5b58fc0
Ensure we're logged out before trying to log in as a user
opr Aug 23, 2023
4bcccbf
Log out before each authentication setup step
opr Aug 23, 2023
6c1f7c5
Ensure tests requiring admin are logged in
opr Aug 24, 2023
a662985
Log in as admin during block theme setup
tarhi-saad Nov 22, 2023
7fa1e5a
Fix Playwright strict mode violation
tarhi-saad Nov 22, 2023
63f69a8
Run Multiple sign-in roles to the global-setup phase
tarhi-saad Dec 1, 2023
007c05f
Remove unnecessary login as admin
tarhi-saad Dec 1, 2023
4ae8dd1
Remove "auth.setup" dependency since the logic lives in the global se…
tarhi-saad Dec 1, 2023
4fe2bb8
Remove unnecessary login as admin from test files
tarhi-saad Dec 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ tests/cli/vendor
**/e2e/artifacts/
/artifacts/
/playwright-report/
**/e2e/.auth

# Logs
/logs
Expand Down
25 changes: 0 additions & 25 deletions tests/e2e-jest/specs/shopper/cart-checkout/checkout.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -333,31 +333,6 @@ describe( 'Shopper → Checkout', () => {
} );
} );

describe( 'Place Order', () => {
it( 'Guest user can place order', async () => {
if ( await shopper.isLoggedIn() ) {
await shopper.logout();
}
await shopper.block.goToShop();
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
await shopper.block.goToCheckout();
await shopper.block.fillBillingDetails( BILLING_DETAILS );
await shopper.block.placeOrder();
await expect( page ).toMatch( 'Your order has been received.' );
} );

it( 'Logged in user can place an order', async () => {
await shopper.login();
await shopper.block.goToShop();
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
await shopper.block.goToCheckout();
await shopper.block.fillBillingDetails( BILLING_DETAILS );
await shopper.block.placeOrder();
await expect( page ).toMatch( 'Your order has been received.' );
await shopper.logout();
} );
} );

describe.skip( `Shipping`, () => {
afterEach( async () => {
await merchant.login();
Expand Down
99 changes: 98 additions & 1 deletion tests/e2e/global-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@
*/
import { FullConfig, chromium, request } from '@playwright/test';
import { RequestUtils } from '@wordpress/e2e-test-utils-playwright';
import { expect } from '@woocommerce/e2e-playwright-utils';
import fs from 'fs';
import { cli } from '@woocommerce/e2e-utils';
import {
cli,
adminFile,
customerFile,
guestFile,
} from '@woocommerce/e2e-utils';

/**
* Internal dependencies
Expand Down Expand Up @@ -79,6 +85,94 @@ const loginAsCustomer = async ( config: FullConfig ) => {
await browser.close();
};

const authenticateAsAdmin = async ( config: FullConfig ) => {
const { baseURL, userAgent } = config.projects[ 0 ].use;

// Specify user agent when running against an external test site to avoid getting HTTP 406 NOT ACCEPTABLE errors.
const contextOptions = { baseURL, userAgent };
// Create browser, browserContext, and page for admin users
const browser = await chromium.launch();
const context = await browser.newContext( contextOptions );
const page = await context.newPage();
await page.goto( '/my-account' );
await page.getByLabel( 'Username or email address' ).fill( admin.username );
await page.getByLabel( 'Password' ).fill( admin.password );
await page.getByRole( 'button', { name: 'Log in' } ).click();
// Sometimes login flow sets cookies in the process of several redirects.
// Wait for the final URL to ensure that the cookies are actually set.
await page.waitForURL( '/my-account/' );

await expect(
page
.getByRole( 'list' )
.filter( {
hasText:
'Dashboard Orders Downloads Addresses Account details Log out',
} )
.getByRole( 'link', { name: 'Log out' } )
).toBeVisible();

await page.context().storageState( { path: adminFile } );

await context.close();
await browser.close();
};

const authenticateAsCustomer = async ( config: FullConfig ) => {
const { baseURL, userAgent } = config.projects[ 0 ].use;

// Specify user agent when running against an external test site to avoid getting HTTP 406 NOT ACCEPTABLE errors.
const contextOptions = { baseURL, userAgent };
// Create browser, browserContext, and page for customer users
const browser = await chromium.launch();
const context = await browser.newContext( contextOptions );
const page = await context.newPage();
await page.goto( '/my-account' );
await page
.getByLabel( 'Username or email address' )
.fill( customer.username );
await page.getByLabel( 'Password' ).fill( customer.password );
await page.getByRole( 'button', { name: 'Log in' } ).click();
// Sometimes login flow sets cookies in the process of several redirects.
// Wait for the final URL to ensure that the cookies are actually set.
await page.waitForURL( '/my-account/' );

await expect(
page
.getByRole( 'list' )
.filter( {
hasText:
'Dashboard Orders Downloads Addresses Account details Log out',
} )
.getByRole( 'link', { name: 'Log out' } )
).toBeVisible();

await page.context().storageState( { path: customerFile } );

await context.close();
await browser.close();
};

const visitAsGuest = async ( config: FullConfig ) => {
const { baseURL, userAgent } = config.projects[ 0 ].use;

// Specify user agent when running against an external test site to avoid getting HTTP 406 NOT ACCEPTABLE errors.
const contextOptions = { baseURL, userAgent };
// Create browser, browserContext, and page for customer and admin users
const browser = await chromium.launch();
const context = await browser.newContext( contextOptions );
const page = await context.newPage();
await page.goto( '/my-account' );
await expect(
page.getByLabel( 'Username or email address' )
).toBeVisible();

await page.context().storageState( { path: guestFile } );

await context.close();
await browser.close();
};

const prepareAttributes = async ( config: FullConfig ) => {
const { baseURL, userAgent } = config.projects[ 0 ].use;

Expand Down Expand Up @@ -145,6 +239,9 @@ async function globalSetup( config: FullConfig ) {

await prepareAttributes( config );
await loginAsCustomer( config );
await authenticateAsAdmin( config );
await authenticateAsCustomer( config );
await visitAsGuest( config );
}

export default globalSetup;
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,19 @@
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { customerFile, guestFile } from '@woocommerce/e2e-utils';

/**
* Internal dependencies
*/
import { CheckoutPage } from './checkout.page';
import {
FREE_SHIPPING_NAME,
FREE_SHIPPING_PRICE,
SIMPLE_PHYSICAL_PRODUCT_NAME,
FLAT_RATE_SHIPPING_NAME,
FLAT_RATE_SHIPPING_PRICE,
} from './constants';

const test = base.extend< { pageObject: CheckoutPage } >( {
pageObject: async ( { page }, use ) => {
Expand All @@ -18,14 +26,7 @@ const test = base.extend< { pageObject: CheckoutPage } >( {
} );

test.describe( 'Shopper → Checkout block → Shipping', () => {
const FREE_SHIPPING_NAME = 'Free shipping';
const FREE_SHIPPING_PRICE = '$0.00';
const FLAT_RATE_SHIPPING_NAME = 'Flat rate shipping';
const FLAT_RATE_SHIPPING_PRICE = '$10.00';

test.use( {
storageState: process.env.CUSTOMERSTATE,
} );
test.use( { storageState: customerFile } );

test( 'Shopper can choose free shipping, flat rate shipping, and can have different billing and shipping addresses', async ( {
pageObject,
Expand Down Expand Up @@ -96,3 +97,31 @@ test.describe( 'Shopper → Checkout block → Shipping', () => {
await pageObject.verifyAddressDetails( 'shipping' );
} );
} );

// We only check if guest user can place an order because we already checked if logged in user can
// place an order in the previous test
test.describe( 'Shopper → Checkout block → Place Order', () => {
test.use( { storageState: guestFile } );

test( 'Guest user can place order', async ( {
pageObject,
frontendUtils,
page,
} ) => {
await frontendUtils.emptyCart();
await frontendUtils.goToShop();
await frontendUtils.addToCart( SIMPLE_PHYSICAL_PRODUCT_NAME );
await frontendUtils.goToCheckout();
await expect(
await pageObject.selectAndVerifyShippingOption(
FREE_SHIPPING_NAME,
FREE_SHIPPING_PRICE
)
).toBe( true );
await pageObject.fillInCheckoutWithTestData();
await pageObject.placeOrder();
await expect(
page.getByText( 'Your order has been received.' )
).toBeVisible();
} );
} );
2 changes: 1 addition & 1 deletion tests/e2e/tests/checkout/checkout.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ export class CheckoutPage {
shippingName: string,
shippingPrice: string
) {
const shipping = this.page.getByLabel( shippingName );
const shipping = this.page.getByLabel( shippingName ).first();
await expect( shipping ).toBeVisible();
if (
! ( await this.isShippingRateSelected(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import { BlockData } from '@woocommerce/e2e-types';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { BASE_URL, cli } from '@woocommerce/e2e-utils';

/**
* Internal dependencies
*/

const blockData: BlockData< {
urlSearchParamWhenFilterIsApplied: string;
endpointAPI: string;
Expand Down
5 changes: 5 additions & 0 deletions tests/e2e/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@ export const STORAGE_STATE_PATH = path.join(
process.cwd(),
'artifacts/storage-states/admin.json'
);

// User roles file paths
export const adminFile = '.auth/admin.json';
export const customerFile = '.auth/customer.json';
export const guestFile = '.auth/guest.json';
Comment on lines +16 to +19
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are saving these at the project root, but the .gitignore only ignores things in e2e. We should update these paths.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@opr, when I run the tests locally, these files are created in tests/e2e/.auth/, not on the project root.

6 changes: 6 additions & 0 deletions tests/e2e/utils/frontend/frontend-utils.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,10 @@ export class FrontendUtils {
await locator.press( 'End' );
await locator.press( 'Shift+Home' );
}

async gotoMyAccount() {
await this.page.goto( '/my-account', {
waitUntil: 'commit',
} );
}
}
Loading