Skip to content

Commit b763f99

Browse files
Migrate the Shopper Renew Subscription E2E test to Playwright (#10144)
1 parent 95473ac commit b763f99

File tree

9 files changed

+195
-97
lines changed

9 files changed

+195
-97
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: patch
2+
Type: dev
3+
4+
Migrate the Shopper Renew Subscription spec to Playwright and remove the corresponding Puppeteer test.

tests/e2e-pw/config/default.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,25 +76,25 @@ export const config = {
7676
},
7777
'subscriptions-customer': {
7878
billing: {
79-
first_name: 'I am',
80-
last_name: 'Subscriptions Customer',
79+
firstname: 'I am',
80+
lastname: 'Subscriptions Customer',
8181
company: 'Automattic',
8282
country: 'United States (US)',
83-
address_1: '60 29th Street #343',
84-
address_2: 'billing',
83+
addressfirstline: '60 29th Street #343',
84+
addresssecondline: 'billing',
8585
city: 'San Francisco',
8686
state: 'CA',
8787
postcode: '94110',
8888
phone: '123456789',
8989
9090
},
9191
shipping: {
92-
first_name: 'I am',
93-
last_name: 'Subscriptions Recipient',
92+
firstname: 'I am',
93+
lastname: 'Subscriptions Recipient',
9494
company: 'Automattic',
9595
country: 'United States (US)',
96-
address_1: '60 29th Street #343',
97-
address_2: 'shipping',
96+
addressfirstline: '60 29th Street #343',
97+
addresssecondline: 'shipping',
9898
city: 'San Francisco',
9999
state: 'CA',
100100
postcode: '94110',
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import { test, expect, Page } from '@playwright/test';
5+
6+
/**
7+
* Internal dependencies
8+
*/
9+
import { config } from '../../config/default';
10+
import { describeif, getAnonymousShopper } from '../../utils/helpers';
11+
import * as shopper from '../../utils/shopper';
12+
import * as navigation from '../../utils/shopper-navigation';
13+
import { products, shouldRunSubscriptionsTests } from '../../utils/constants';
14+
import RestAPI from '../../utils/rest-api';
15+
16+
describeif( shouldRunSubscriptionsTests )(
17+
'Subscriptions > Renew a subscription in my account',
18+
() => {
19+
const customerBillingConfig =
20+
config.addresses[ 'subscriptions-customer' ].billing;
21+
22+
let subscriptionId: string;
23+
let page: Page;
24+
25+
test.beforeAll( async ( { browser }, { project } ) => {
26+
const restApi = new RestAPI( project.use.baseURL );
27+
await restApi.deleteCustomerByEmailAddress(
28+
customerBillingConfig.email
29+
);
30+
31+
const { shopperPage } = await getAnonymousShopper( browser );
32+
page = shopperPage;
33+
} );
34+
35+
test( 'should be able to purchase a subscription', async () => {
36+
await shopper.addCartProduct(
37+
page,
38+
products.SUBSCRIPTION_SIGNUP_FEE
39+
);
40+
await shopper.setupCheckout( page, customerBillingConfig );
41+
await shopper.fillCardDetails( page, config.cards.basic );
42+
await shopper.placeOrder( page );
43+
await expect(
44+
page.getByRole( 'heading', { name: 'Order received' } )
45+
).toBeVisible();
46+
47+
subscriptionId = await page
48+
.getByLabel( 'View subscription number' )
49+
.innerText();
50+
} );
51+
52+
test( 'should be able to renew a subscription in my account', async () => {
53+
await navigation.goToSubscriptions( page );
54+
55+
if ( ! subscriptionId ) {
56+
throw new Error( 'Subscription ID is not set' );
57+
}
58+
59+
const numericSubscriptionId = subscriptionId.substring( 1 );
60+
61+
await page
62+
.getByLabel(
63+
`View subscription number ${ numericSubscriptionId }`
64+
)
65+
.click();
66+
67+
await page.getByText( 'Renew now' ).click();
68+
await page
69+
.getByText( 'Complete checkout to renew now.' )
70+
.isVisible();
71+
await shopper.focusPlaceOrderButton( page );
72+
await shopper.placeOrder( page );
73+
await expect(
74+
page.getByRole( 'heading', { name: 'Order received' } )
75+
).toBeVisible();
76+
} );
77+
}
78+
);

tests/e2e-pw/utils/constants.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const shouldRunSubscriptionsTests =
2+
process.env.SKIP_WC_SUBSCRIPTIONS_TESTS !== '1';
3+
4+
export const products = {
5+
SUBSCRIPTION_SIGNUP_FEE: 70,
6+
};

tests/e2e-pw/utils/helpers.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,9 @@ export const getAnonymousShopper = async (
9393
const shopperPage = await shopperContext.newPage();
9494
return { shopperPage, shopperContext };
9595
};
96+
97+
/**
98+
* Conditionally determine whether or not to skip a test suite.
99+
*/
100+
export const describeif = ( condition: boolean ) =>
101+
condition ? test.describe : test.describe.skip;

tests/e2e-pw/utils/rest-api.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import { HTTPClientFactory } from '@woocommerce/api';
5+
6+
/**
7+
* Internal dependencies
8+
*/
9+
import { config } from '../config/default';
10+
11+
const userEndpoint = '/wp/v2/users';
12+
13+
class RestAPI {
14+
private baseUrl: string;
15+
16+
constructor( baseUrl: string ) {
17+
if ( ! baseUrl ) {
18+
throw new Error( 'Base URL is required.' );
19+
}
20+
this.baseUrl = baseUrl;
21+
}
22+
23+
private getAdminClient() {
24+
return HTTPClientFactory.build( this.baseUrl )
25+
.withBasicAuth(
26+
config.users.admin.username,
27+
config.users.admin.password
28+
)
29+
.create();
30+
}
31+
32+
/**
33+
* Deletes a customer account by their email address if the user exists.
34+
*
35+
* Copied from https://github.com/woocommerce/woocommerce/blob/trunk/packages/js/e2e-utils/src/flows/with-rest-api.js#L374
36+
*
37+
* @param {string} emailAddress Customer user account email address.
38+
* @return {Promise<void>}
39+
*/
40+
async deleteCustomerByEmailAddress(
41+
emailAddress: string
42+
): Promise< void > {
43+
const client = this.getAdminClient();
44+
45+
const query = {
46+
search: emailAddress,
47+
context: 'edit',
48+
};
49+
const customers = await client.get( userEndpoint, query );
50+
51+
if ( customers.data && customers.data.length ) {
52+
for ( let c = 0; c < customers.data.length; c++ ) {
53+
const deleteUser = {
54+
id: customers.data[ c ].id,
55+
force: true,
56+
reassign: 1,
57+
};
58+
59+
await client.delete(
60+
`${ userEndpoint }/${ deleteUser.id }`,
61+
deleteUser
62+
);
63+
}
64+
}
65+
}
66+
}
67+
68+
export default RestAPI;

tests/e2e-pw/utils/shopper-navigation.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,8 @@ export const goToOrder = async ( page: Page, orderId: string ) => {
4343
waitUntil: 'load',
4444
} );
4545
};
46+
47+
export const goToSubscriptions = ( page: Page ) =>
48+
page.goto( '/my-account/subscriptions/', {
49+
waitUntil: 'load',
50+
} );

tests/e2e-pw/utils/shopper.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,24 @@ export const isUIUnblocked = async ( page: Page ) => {
1212
await expect( page.locator( '.blockUI' ) ).toHaveCount( 0 );
1313
};
1414

15+
/**
16+
* Waits for the UI to refresh after a user interaction.
17+
*
18+
* Woo core blocks and refreshes the UI after 1s after each key press
19+
* in a text field or immediately after a select field changes.
20+
* We need to wait to make sure that all key presses were processed by that mechanism.
21+
*/
22+
export const waitForUiRefresh = ( page: Page ) => page.waitForTimeout( 1000 );
23+
24+
/**
25+
* Takes off the focus out of the Stripe elements to let Stripe logic
26+
* wrap up and make sure the Place Order button is clickable.
27+
*/
28+
export const focusPlaceOrderButton = async ( page: Page ) => {
29+
await page.locator( '#place_order' ).focus();
30+
await waitForUiRefresh( page );
31+
};
32+
1533
export const fillBillingAddress = async (
1634
page: Page,
1735
billingAddress: CustomerAddress
@@ -188,10 +206,7 @@ export const setupCheckout = async (
188206
) => {
189207
await navigation.goToCheckout( page );
190208
await fillBillingAddress( page, billingAddress );
191-
// Woo core blocks and refreshes the UI after 1s after each key press
192-
// in a text field or immediately after a select field changes.
193-
// We need to wait to make sure that all key presses were processed by that mechanism.
194-
await page.waitForTimeout( 1000 );
209+
await waitForUiRefresh( page );
195210
await isUIUnblocked( page );
196211
await page
197212
.locator( '.wc_payment_method.payment_method_woocommerce_payments' )
@@ -252,10 +267,7 @@ export const placeOrderWithCurrency = async (
252267
await navigation.goToShopWithCurrency( page, currency );
253268
await setupProductCheckout( page, [ [ config.products.simple.name, 1 ] ] );
254269
await fillCardDetails( page, config.cards.basic );
255-
// Takes off the focus out of the Stripe elements to let Stripe logic
256-
// wrap up and make sure the Place Order button is clickable.
257-
await page.locator( '#place_order' ).focus();
258-
await page.waitForTimeout( 1000 );
270+
await focusPlaceOrderButton( page );
259271
await placeOrder( page );
260272
await page.waitForURL( /\/order-received\//, { waitUntil: 'load' } );
261273
await expect(

tests/e2e/specs/subscriptions/shopper/shopper-myaccount-renew-subscription.spec.js

Lines changed: 0 additions & 81 deletions
This file was deleted.

0 commit comments

Comments
 (0)