Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate shopper free trial subscription purchase to Playwright #10159

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: dev

Migrate shopper subscription free-trial purchase E2E test to Playwright
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/**
* External dependencies
*/
import test, { expect } from '@playwright/test';

/**
* Internal dependencies
*/
import { shouldRunSubscriptionsTests } from '../../utils/constants';
import { describeif, getMerchant, getShopper } from '../../utils/helpers';
import RestAPI from '../../utils/rest-api';
import { config } from '../../config/default';
import {
confirmCardAuthentication,
emptyCart,
fillCardDetails,
setupCheckout,
} from '../../utils/shopper';
import {
goToCart,
goToProductPageBySlug,
} from '../../utils/shopper-navigation';
import { goToOrder, goToSubscriptions } from '../../utils/merchant-navigation';

const nowLocal = new Date();
const nowUTC = new Date(
nowLocal.getUTCFullYear(),
nowLocal.getUTCMonth(),
nowLocal.getUTCDate()
);
const formatter = new Intl.DateTimeFormat( 'en-US', {
dateStyle: 'long',
} );
const renewalDate = nowUTC.setDate( nowUTC.getDate() + 14 );
const renewalDateFormatted = formatter.format( renewalDate );
const productName = 'Subscription free trial product';
const productSlug = 'subscription-free-trial-product';
const customerBilling = config.addresses.customer.billing;
const customerBillingConfig =
config.addresses[ 'subscriptions-customer' ].billing;
let orderId, subscriptionId;

const testSelectors = {
productSubscriptionDetails: '.summary span.subscription-details',
cartSubscriptionDetails: '.product-price span.subscription-details',
cartSubscriptionFirstPaymentDate: '.first-payment-date',
cartOrderTotal: 'tr.order-total:not(.recurring-total) td',
checkoutSubscriptionDetails: 'span.subscription-details',
checkoutSubscriptionFirstPaymentDate: '.first-payment-date',
checkoutPlaceOrderButton: '#place_order',
checkoutOrderId: '.woocommerce-order-overview__order.order > strong',
checkoutSubscriptionId: 'td.subscription-id > a',
wcOrderPaymentId: '.woocommerce-order-data__meta',
subscriptionStatus: '.subscription-status',
subscriptionProductName: '.order-item',
subscriptionRecurringTotal: '.recurring_total',
subscriptionTrialEnd: 'time.trial_end_date',
};

describeif( shouldRunSubscriptionsTests )(
'Shopper: Subscriptions - Purchase Free Trial',
() => {
test.beforeAll( async ( {}, { project } ) => {
const restApi = new RestAPI( project.use.baseURL );
await restApi.deleteCustomerByEmailAddress(
customerBillingConfig.email
);
} );

test( 'Merchant should be able to purchase a free trial', async ( {
browser,
} ) => {
const { shopperPage } = await getShopper( browser );
Copy link
Contributor

Choose a reason for hiding this comment

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

Since you're deleting subscriptions-customer, it’s better to use getAnonymousShopper() instead, as getShopper() logs in with a different user (the regular customer).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, this test (and IMO most of the tests) doesn't need deleting the customer, we can go on with the regular customer. I just copied what was there in the puppeteer test. What about we deleting the regular customer instead to reset the saved cards? Did you understand the reason why we're deleting the customers?


// Just to be sure, empty the cart
await emptyCart( shopperPage );

// Open the subscription product, and verify that the
// 14-day free trial is shown in the product description
await goToProductPageBySlug( shopperPage, productSlug );
await expect(
shopperPage.locator( testSelectors.productSubscriptionDetails )
).toHaveText( /\s*\/ month with a 14-day free trial\s*/ );

// Add it to the cart and verify that the cart page shows the free trial details
await shopperPage.locator( '.single_add_to_cart_button' ).click();
await goToCart( shopperPage );
await expect(
shopperPage.locator( testSelectors.cartSubscriptionDetails )
).toHaveText( /\s*\/ month with a 14-day free trial\s*/ );

// Also verify that the first renewal is 14 days from now
await expect(
shopperPage.locator(
testSelectors.cartSubscriptionFirstPaymentDate
)
).toHaveText( `First renewal: ${ renewalDateFormatted }` );

// Verify that the order total is $0.00
await expect(
shopperPage.locator( testSelectors.cartOrderTotal )
).toHaveText( `$0.00` );

// Proceed to the checkout page and verify that the 14-day free trial is shown in the product line item,
// and that the first renewal date is 14 days from now.
await setupCheckout( shopperPage, customerBilling );
await expect(
shopperPage.locator( testSelectors.checkoutSubscriptionDetails )
).toHaveText( '/ month with a 14-day free trial' );
await expect(
shopperPage.locator(
testSelectors.cartSubscriptionFirstPaymentDate
)
).toHaveText( `First renewal: ${ renewalDateFormatted }` );

// Pay using a 3DS card
const card = config.cards[ '3dsOTP' ];
await fillCardDetails( shopperPage, card );
await shopperPage.click( testSelectors.checkoutPlaceOrderButton );
await shopperPage.frames()[ 0 ].waitForLoadState( 'load' );
await confirmCardAuthentication( shopperPage, true );
await shopperPage.waitForLoadState( 'networkidle' );
await expect(
shopperPage.getByRole( 'heading', {
name: 'Order received',
} )
).toBeVisible();

// Get the order ID so we can open it in the merchant view
const orderIdField = await shopperPage.$(
testSelectors.checkoutOrderId
);
orderId = await orderIdField.evaluate( ( el ) => el.textContent );
const subscriptionIdField = await shopperPage.$(
testSelectors.checkoutSubscriptionId
);
subscriptionId = await subscriptionIdField.evaluate( ( el ) =>
el.textContent.trim().replace( '#', '' )
);
} );

test( 'Merchant should be able to create an order with "Setup Intent"', async ( {
browser,
} ) => {
const { merchantPage } = await getMerchant( browser );
await goToOrder( merchantPage, orderId );
await expect(
merchantPage.locator( testSelectors.wcOrderPaymentId )
).toHaveText( /\(seti_.*\)/ );

await goToSubscriptions( merchantPage );
const subscriptionRow = await merchantPage.locator(
'#order-' + subscriptionId
);
await expect(
subscriptionRow.locator( testSelectors.subscriptionStatus )
).toHaveText( 'Active' );
await expect(
subscriptionRow.locator( testSelectors.subscriptionProductName )
).toHaveText( productName );
await expect(
subscriptionRow.locator(
testSelectors.subscriptionRecurringTotal
)
).toHaveText( /\$9\.99/ );
await expect(
subscriptionRow.locator( testSelectors.subscriptionTrialEnd )
).toHaveText( renewalDateFormatted );
} );
}
);
7 changes: 6 additions & 1 deletion tests/e2e-pw/utils/merchant-navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import { Page } from 'playwright/test';
import { dataHasLoaded } from './merchant';

export const goToOrder = async ( page: Page, orderId: string ) => {
await page.goto( `/wp-admin/post.php?post=${ orderId }&action=edit` );
await page.goto(
`/wp-admin/admin.php?page=wc-orders&action=edit&id=${ orderId }`,
{
waitUntil: 'load',
}
);
};

export const goToPaymentDetails = async (
Expand Down

This file was deleted.

Loading