Skip to content

Commit 8b20024

Browse files
Add E2E smoke tests for subscriptions (#2524)
* Add placeholder files * Fix config conflicts * Add spec for subscription purchase on regular checkout * Add spec for subscription purchase on blocks checkout * Fix teardown * Disable WP_DEBUG on setup * Remove unused constant * Add subscription renewal spec * Add util to login users * Update specs to use login util * Fix user login util * Use login util on setup and teardown * Remove unused try catch blocks * Update error messages * Fix typo * Move login step on teardown
1 parent 1c36361 commit 8b20024

File tree

13 files changed

+380
-102
lines changed

13 files changed

+380
-102
lines changed

tests/e2e/config/global-setup.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
require( 'dotenv' ).config( {
2-
path: `${ process.env.E2E_ROOT }/config/local.env`,
3-
} );
4-
51
import { chromium } from '@playwright/test';
62
import fs from 'fs';
73

@@ -17,7 +13,6 @@ const {
1713
BASE_URL,
1814
ADMIN_USER,
1915
ADMIN_PASSWORD,
20-
ADMINSTATE,
2116
PLUGIN_VERSION,
2217
WOO_SETUP,
2318
STRIPE_SETUP,

tests/e2e/config/global-teardown.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ import path from 'path';
22

33
import { chromium } from '@playwright/test';
44
import { getReleaseZipUrl, deleteZip } from '../utils/plugin-utils';
5+
import { user } from '../utils';
56

67
const { ADMIN_USER, ADMIN_PASSWORD, PLUGIN_VERSION } = process.env;
7-
const adminUsername = ADMIN_USER ?? 'admin';
8-
const adminPassword = ADMIN_PASSWORD ?? 'password';
98

109
module.exports = async ( config ) => {
1110
const { baseURL, userAgent } = config.projects[ 0 ].use;
@@ -21,15 +20,14 @@ module.exports = async ( config ) => {
2120

2221
let consumerTokenCleared = false;
2322

23+
await user.login( adminPage, ADMIN_USER, ADMIN_PASSWORD );
24+
2425
// Clean up the consumer keys
2526
const keysRetries = 5;
26-
for ( let i = 0; i < keysRetries; i++ ) {
27+
for ( let i = 1; i <= keysRetries; i++ ) {
2728
try {
2829
console.log( '- Trying to clear consumer token... Try:' + i );
29-
await adminPage.goto( `/wp-admin` );
30-
await adminPage.fill( 'input[name="log"]', adminUsername );
31-
await adminPage.fill( 'input[name="pwd"]', adminPassword );
32-
await adminPage.click( 'text=Log In' );
30+
3331
await adminPage.goto(
3432
`/wp-admin/admin.php?page=wc-settings&tab=advanced&section=keys`
3533
);
@@ -38,7 +36,10 @@ module.exports = async ( config ) => {
3836
consumerTokenCleared = true;
3937
break;
4038
} catch ( e ) {
41-
console.log( 'Failed to clear consumer token. Retrying...' );
39+
console.error(
40+
`Failed to clear consumer token. Retrying... ${ i }/${ keysRetries }. Error:`,
41+
e
42+
);
4243
}
4344
}
4445

tests/e2e/config/playwright.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
import { devices } from '@playwright/test';
2+
import dotenv from 'dotenv';
3+
4+
dotenv.config( {
5+
path: `${ process.env.E2E_ROOT }/config/local.env`,
6+
} );
7+
28
const {
39
ALLURE_RESULTS_DIR,
410
BASE_URL,

tests/e2e/test-data/default.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
},
2424
"grouped": {
2525
"name": "Grouped Product with Three Children"
26+
},
27+
"subscription": {
28+
"name": "Subscription Product",
29+
"type": "subscription"
2630
}
2731
},
2832
"addresses": {

tests/e2e/tests/checkout/saved-card.spec.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { test, expect } from '@playwright/test';
22
import config from 'config';
3-
import { payments, api } from '../../utils';
3+
import { payments, api, user } from '../../utils';
44

55
const {
66
emptyCart,
@@ -29,15 +29,11 @@ test.beforeAll( async () => {
2929

3030
test( 'customer can checkout with a saved card @smoke', async ( { page } ) => {
3131
await test.step( 'customer login', async () => {
32-
await page.goto( `/wp-admin` );
33-
await page.fill( 'input[name="log"]', username );
34-
await page.fill(
35-
'input[name="pwd"]',
32+
await user.login(
33+
page,
34+
username,
3635
config.get( 'users.customer.password' )
3736
);
38-
await page.click( 'text=Log In' );
39-
40-
await expect( page.locator( 'body' ) ).toHaveClass( /logged-in/ );
4137
} );
4238

4339
await test.step( 'checkout and choose to save the card', async () => {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { test, expect } from '@playwright/test';
2+
import config from 'config';
3+
import { payments, api } from '../../utils';
4+
5+
const { setupCheckout, fillCardDetails } = payments;
6+
7+
let productId;
8+
9+
test.beforeAll( async () => {
10+
const product = {
11+
...config.get( 'products.subscription' ),
12+
regular_price: '9.99',
13+
meta_data: [
14+
{
15+
key: '_subscription_period',
16+
value: 'month',
17+
},
18+
{
19+
key: '_subscription_period_interval',
20+
value: '1',
21+
},
22+
],
23+
};
24+
25+
productId = await api.create.product( product );
26+
} );
27+
28+
test.afterAll( async () => {
29+
await api.deletePost.product( productId );
30+
} );
31+
32+
test( 'customer can purchase a subscription product @smoke @subscriptions', async ( {
33+
page,
34+
} ) => {
35+
await page.goto( `?p=${ productId }` );
36+
await page.locator( 'button[name="add-to-cart"]' ).click();
37+
38+
// Subscriptions will create an account for this checkout, we need a random email.
39+
const customerData = {
40+
...config.get( 'addresses.customer.billing' ),
41+
email:
42+
Date.now() + '+' + config.get( 'addresses.customer.billing.email' ),
43+
};
44+
45+
await setupCheckout( page, customerData );
46+
await fillCardDetails( page, config.get( 'cards.basic' ) );
47+
48+
await page.locator( 'text=Sign up now' ).click();
49+
await page.waitForNavigation();
50+
51+
await expect( page.locator( 'h1.entry-title' ) ).toHaveText(
52+
'Order received'
53+
);
54+
} );
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { test, expect } from '@playwright/test';
2+
import config from 'config';
3+
import { payments, api, user } from '../../utils';
4+
5+
const { setupCheckout, fillCardDetails } = payments;
6+
7+
let productId;
8+
let username, userEmail;
9+
10+
test.beforeAll( async () => {
11+
// This allow multiple tests to run in parallel.
12+
const randomString = Date.now();
13+
userEmail = randomString + '+' + config.get( 'users.customer.email' );
14+
username = randomString + '.' + config.get( 'users.customer.username' );
15+
16+
const user = {
17+
...config.get( 'users.customer' ),
18+
...config.get( 'addresses.customer' ),
19+
email: userEmail,
20+
username,
21+
};
22+
23+
await api.create.customer( user );
24+
25+
const product = {
26+
...config.get( 'products.subscription' ),
27+
regular_price: '9.99',
28+
meta_data: [
29+
{
30+
key: '_subscription_period',
31+
value: 'month',
32+
},
33+
{
34+
key: '_subscription_period_interval',
35+
value: '1',
36+
},
37+
],
38+
};
39+
40+
productId = await api.create.product( product );
41+
} );
42+
43+
test.afterAll( async () => {
44+
await api.deletePost.product( productId );
45+
} );
46+
47+
test( 'customer can renew a subscription @smoke @subscriptions', async ( {
48+
page,
49+
} ) => {
50+
await test.step( 'customer login', async () => {
51+
await user.login(
52+
page,
53+
username,
54+
config.get( 'users.customer.password' )
55+
);
56+
} );
57+
58+
await test.step( 'customer purchase a subscription product', async () => {
59+
await page.goto( `?p=${ productId }` );
60+
await page.locator( 'button[name="add-to-cart"]' ).click();
61+
62+
await setupCheckout( page );
63+
await fillCardDetails( page, config.get( 'cards.basic' ) );
64+
65+
await page.locator( 'text=Sign up now' ).click();
66+
67+
await expect( page.locator( 'h1.entry-title' ) ).toHaveText(
68+
'Order received'
69+
);
70+
} );
71+
72+
await test.step( 'customer renews the subscription', async () => {
73+
await page.goto( `/my-account` );
74+
await page.click( 'text=My Subscription' );
75+
76+
// Expect only one related order.
77+
await expect(
78+
page.locator( '.woocommerce-orders-table--orders tbody tr' )
79+
).toHaveCount( 1 );
80+
81+
await page.locator( 'text=Renew now' ).click();
82+
await page.locator( 'text=Renew subscription' ).click();
83+
await expect( page.locator( 'h1.entry-title' ) ).toHaveText(
84+
'Order received'
85+
);
86+
} );
87+
88+
await test.step(
89+
'check for new entry in the related orders table',
90+
async () => {
91+
await page.goto( `/my-account` );
92+
await page.click( 'text=My Subscription' );
93+
94+
// Expect only one related order.
95+
await expect(
96+
page.locator( '.woocommerce-orders-table--orders tbody tr' )
97+
).toHaveCount( 2 );
98+
}
99+
);
100+
} );

tests/e2e/tests/woocommerce-blocks/saved-card.spec.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { test, expect } from '@playwright/test';
22
import config from 'config';
3-
import { payments, api } from '../../utils';
3+
import { payments, api, user } from '../../utils';
44

55
const {
66
emptyCart,
@@ -31,15 +31,11 @@ test( 'customer can checkout with a saved card @smoke @blocks', async ( {
3131
page,
3232
} ) => {
3333
await test.step( 'customer login', async () => {
34-
await page.goto( `/wp-admin` );
35-
await page.fill( 'input[name="log"]', username );
36-
await page.fill(
37-
'input[name="pwd"]',
34+
await user.login(
35+
page,
36+
username,
3837
config.get( 'users.customer.password' )
3938
);
40-
await page.click( 'text=Log In' );
41-
42-
await expect( page.locator( 'body' ) ).toHaveClass( /logged-in/ );
4339
} );
4440

4541
await test.step( 'checkout and choose to save the card', async () => {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { test, expect } from '@playwright/test';
2+
import config from 'config';
3+
import { payments, api } from '../../utils';
4+
5+
const { setupBlocksCheckout, fillCardDetails } = payments;
6+
7+
let productId;
8+
9+
test.beforeAll( async () => {
10+
const product = {
11+
...config.get( 'products.subscription' ),
12+
regular_price: '9.99',
13+
meta_data: [
14+
{
15+
key: '_subscription_period',
16+
value: 'month',
17+
},
18+
{
19+
key: '_subscription_period_interval',
20+
value: '1',
21+
},
22+
],
23+
};
24+
25+
productId = await api.create.product( product );
26+
} );
27+
28+
test.afterAll( async () => {
29+
await api.deletePost.product( productId );
30+
} );
31+
32+
test( 'customer can purchase a subscription product @smoke @blocks @subscriptions', async ( {
33+
page,
34+
} ) => {
35+
await page.goto( `?p=${ productId }` );
36+
await page.locator( 'button[name="add-to-cart"]' ).click();
37+
38+
// Subscriptions will create an account for this checkout, we need a random email.
39+
const customerData = {
40+
...config.get( 'addresses.customer.billing' ),
41+
email:
42+
Date.now() + '+' + config.get( 'addresses.customer.billing.email' ),
43+
};
44+
45+
await setupBlocksCheckout( page, customerData );
46+
await fillCardDetails( page, config.get( 'cards.basic' ) );
47+
48+
await page.locator( 'text=Place Order' ).click();
49+
await page.waitForNavigation();
50+
51+
await expect( page.locator( 'h1.entry-title' ) ).toHaveText(
52+
'Order received'
53+
);
54+
} );

0 commit comments

Comments
 (0)