Skip to content

Commit

Permalink
Merge branch 'jwplayer:develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristiaanScheermeijer authored Apr 22, 2024
2 parents 7438bc7 + 8df8c30 commit 04323b6
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 105 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { testConfigs } from '@jwp/ott-testing/constants';

import { LoginContext } from '#utils/password_utils';
import constants, { longTimeout } from '#utils/constants';
import { goToCheckout, finishAndCheckSubscription, cancelPlan, renewPlan, overrideIP, addYear } from '#utils/payments';
import constants from '#utils/constants';
import { goToCheckout, overrideIP } from '#utils/payments';
import { ProviderProps } from '#test/types';

const jwProps: ProviderProps = {
Expand All @@ -13,11 +13,9 @@ const jwProps: ProviderProps = {
creditCard: constants.creditCard.inplayer,
applicableTax: 0,
canRenewSubscription: false,
canOpenReceipts: false,
fieldWrapper: '',
hasInlineOfferSwitch: true,
};

const cleengProps: ProviderProps = {
config: testConfigs.svod,
monthlyOffer: constants.offers.monthlyOffer.cleeng,
Expand All @@ -26,7 +24,6 @@ const cleengProps: ProviderProps = {
creditCard: constants.creditCard.cleeng,
applicableTax: 21,
canRenewSubscription: true,
canOpenReceipts: false, // Cleeng returns an error on Sandbox making this test flaky
fieldWrapper: 'iframe',
hasInlineOfferSwitch: false,
};
Expand All @@ -37,19 +34,16 @@ runTestSuite(cleengProps, 'Cleeng');
function runTestSuite(props: ProviderProps, providerName: string) {
let paidLoginContext: LoginContext;

const today = new Date();

const cardInfo = Array.of(['Card number', '•••• •••• •••• 1111'], ['Expiry date', '03/2030'], ['Security code', '******']);

Feature(`payments - ${providerName}`).retry(Number(process.env.TEST_RETRY_COUNT) || 0);
Feature(`choose offer - ${providerName}`).retry(Number(process.env.TEST_RETRY_COUNT) || 0);

Before(async ({ I }) => {
// This gets used in checkoutService.getOffer to make sure the offers are geolocated for NL
overrideIP(I);

I.useConfig(props.config);
});

Scenario(`I can see my payments data - ${providerName}`, async ({ I }) => {
Scenario(`I can see a payments page with no history - ${providerName}`, async ({ I }) => {
paidLoginContext = await I.registerOrLogin(paidLoginContext);

await I.openMainMenu();
Expand Down Expand Up @@ -146,75 +140,6 @@ function runTestSuite(props: ProviderProps, providerName: string) {
I.dontSee('Expiry date');
I.dontSee('Security code');
I.waitForText('Continue');
});

Scenario(`I can open the PayPal site - ${providerName}`, async ({ I }) => {
paidLoginContext = await I.registerOrLogin(paidLoginContext);

await goToCheckout(I);

I.click('PayPal');
I.click('Continue');

I.waitInUrl('paypal.com', longTimeout);
// I'm sorry, I don't know why, but this test ends in a way that causes the next test to fail
I.amOnPage(constants.baseUrl);
});

Scenario(`I can finish my subscription with credit card - ${providerName}`, async ({ I }) => {
paidLoginContext = await I.registerOrLogin(paidLoginContext);

await goToCheckout(I);

await I.payWithCreditCard(
props.paymentFields.creditCardholder,
props.creditCard,
props.paymentFields.cardNumber,
props.paymentFields.expiryDate,
props.paymentFields.securityCode,
props.fieldWrapper,
);

await finishAndCheckSubscription(I, addYear(today), today, props.yearlyOffer.price, props.hasInlineOfferSwitch);

cardInfo.forEach(([label, value]) => I.seeInField(label, value));
});

Scenario(`I can cancel my subscription - ${providerName}`, async ({ I }) => {
paidLoginContext = await I.registerOrLogin(paidLoginContext);

cancelPlan(I, addYear(today), props.canRenewSubscription, providerName);

// Still see payment info
cardInfo.forEach(([label, value]) => I.seeInField(label, value));
});

Scenario(`I can renew my subscription - ${providerName}`, async ({ I }) => {
if (props.canRenewSubscription) {
paidLoginContext = await I.registerOrLogin(paidLoginContext);
renewPlan(I, addYear(today), props.yearlyOffer.price);
}
});

Scenario(`I can view my invoices - ${providerName}`, async ({ I }) => {
if (props.canRenewSubscription) {
paidLoginContext = await I.registerOrLogin(paidLoginContext);
I.amOnPage(constants.paymentsUrl);
I.waitForLoaderDone();
I.see('Billing history');
I.dontSee('No transactions');

I.scrollPageToBottom();

if (props.canOpenReceipts) {
// Open the invoice which is opened in a new tab
I.click('Show receipt');
I.switchToNextTab();

// Assert invoice functionality by validating the presence of the purchase button
I.seeElement('.purchase-button');
I.closeCurrentTab();
}
}
I.useConfig(props.config);
});
}
6 changes: 3 additions & 3 deletions platforms/web/test-e2e/tests/payments/coupons_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { testConfigs } from '@jwp/ott-testing/constants';

import { LoginContext } from '#utils/password_utils';
import constants from '#utils/constants';
import { goToCheckout, formatPrice, finishAndCheckSubscription, addYear, cancelPlan, renewPlan, overrideIP } from '#utils/payments';
import { addYear, cancelPlan, checkSubscription, finishSubscription, formatPrice, goToCheckout, overrideIP, renewPlan } from '#utils/payments';
import { ProviderProps } from '#test/types';

const jwProps: ProviderProps = {
Expand Down Expand Up @@ -87,8 +87,8 @@ function runTestSuite(props: ProviderProps, providerName: string) {
'',
);
}

await finishAndCheckSubscription(I, addYear(today), today, props.yearlyOffer.price, props.hasInlineOfferSwitch);
await finishSubscription(I);
await checkSubscription(I, addYear(today), today, props.yearlyOffer.price, props.hasInlineOfferSwitch);
});

Scenario(`I can cancel a free subscription - ${providerName}`, async ({ I }) => {
Expand Down
117 changes: 117 additions & 0 deletions platforms/web/test-e2e/tests/payments/payments_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { testConfigs } from '@jwp/ott-testing/constants';

import { LoginContext } from '#utils/password_utils';
import constants, { longTimeout } from '#utils/constants';
import { goToCheckout, finishSubscription, cancelPlan, renewPlan, overrideIP, addYear, formatDate, checkSubscription } from '#utils/payments';
import { ProviderProps } from '#test/types';

const jwProps: ProviderProps = {
config: testConfigs.jwpSvod,
monthlyOffer: constants.offers.monthlyOffer.inplayer,
yearlyOffer: constants.offers.yearlyOffer.inplayer,
paymentFields: constants.paymentFields.inplayer,
creditCard: constants.creditCard.inplayer,
applicableTax: 0,
canRenewSubscription: false,
fieldWrapper: '',
hasInlineOfferSwitch: true,
};

const cleengProps: ProviderProps = {
config: testConfigs.svod,
monthlyOffer: constants.offers.monthlyOffer.cleeng,
yearlyOffer: constants.offers.yearlyOffer.cleeng,
paymentFields: constants.paymentFields.cleeng,
creditCard: constants.creditCard.cleeng,
applicableTax: 21,
canRenewSubscription: true,
fieldWrapper: 'iframe',
hasInlineOfferSwitch: false,
};

runTestSuite(jwProps, 'JW Player');
runTestSuite(cleengProps, 'Cleeng');

function runTestSuite(props: ProviderProps, providerName: string) {
let paidLoginContext: LoginContext;

const today = new Date();

const cardInfo = Array.of(['Card number', '•••• •••• •••• 1111'], ['Expiry date', '03/2030'], ['Security code', '******']);

Feature(`payments - ${providerName}`).retry(Number(process.env.TEST_RETRY_COUNT) || 0);

Before(async ({ I }) => {
// This gets used in checkoutService.getOffer to make sure the offers are geolocated for NL
overrideIP(I);
I.useConfig(props.config);
});

Scenario(`I can open the PayPal site - ${providerName}`, async ({ I }) => {
paidLoginContext = await I.registerOrLogin(paidLoginContext);

await goToCheckout(I);

I.click('PayPal');
I.click('Continue');

I.waitInUrl('paypal.com', longTimeout);
// I'm sorry, I don't know why, but this test ends in a way that causes the next test to fail
I.amOnPage(constants.baseUrl);
});

Scenario(`I can finish my subscription with credit card - ${providerName}`, async ({ I }) => {
paidLoginContext = await I.registerOrLogin(paidLoginContext);

await goToCheckout(I);

const alreadySubscribed = await tryTo(() => {
I.waitForText('Next billing date is on ' + formatDate(today));
});

if (!alreadySubscribed) {
await I.payWithCreditCard(
props.paymentFields.creditCardholder,
props.creditCard,
props.paymentFields.cardNumber,
props.paymentFields.expiryDate,
props.paymentFields.securityCode,
props.fieldWrapper,
);

await finishSubscription(I);
}

await checkSubscription(I, addYear(today), today, props.yearlyOffer.price, props.hasInlineOfferSwitch);

cardInfo.forEach(([label, value]) => I.seeInField(label, value));
});

Scenario(`I can cancel my subscription - ${providerName}`, async ({ I }) => {
paidLoginContext = await I.registerOrLogin(paidLoginContext);

await cancelPlan(I, addYear(today), props.canRenewSubscription, providerName);

// Still see payment info
cardInfo.forEach(([label, value]) => I.seeInField(label, value));
});

Scenario(`I can renew my subscription - ${providerName}`, async ({ I }) => {
if (props.canRenewSubscription) {
paidLoginContext = await I.registerOrLogin(paidLoginContext);
renewPlan(I, addYear(today), props.yearlyOffer.price);
}
});

Scenario(`I can view my invoices - ${providerName}`, async ({ I }) => {
if (props.canRenewSubscription) {
paidLoginContext = await I.registerOrLogin(paidLoginContext);
I.amOnPage(constants.paymentsUrl);
I.waitForLoaderDone();
I.see('Billing history');
I.dontSee('No transactions');

I.scrollPageToBottom();
}
});
}
51 changes: 30 additions & 21 deletions platforms/web/test-e2e/utils/payments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ export function formatDate(date: Date) {
return new Intl.DateTimeFormat('en-US', { day: 'numeric', month: 'long', year: 'numeric' }).format(date);
}

export async function finishAndCheckSubscription(I: CodeceptJS.I, billingDate: Date, today: Date, yearlyPrice: string, hasInlineOfferSwitch: boolean) {
export async function finishSubscription(I: CodeceptJS.I) {
I.click('Continue');
I.waitForText(`Welcome to JW OTT Web App (SVOD)`, longTimeout);
I.waitForText(`Thank you for subscribing to JW OTT Web App (SVOD). Please enjoy all our content.`);

I.click('Start watching');
}

export async function checkSubscription(I: CodeceptJS.I, billingDate: Date, today: Date, yearlyPrice: string, hasInlineOfferSwitch: boolean) {
const transactionText = 'Annual subscription';

// It takes a few seconds for transactions to load, so try and refresh a few times
Expand Down Expand Up @@ -67,31 +69,38 @@ export async function finishAndCheckSubscription(I: CodeceptJS.I, billingDate: D
I.waitForText(formatDate(today));
}

export function cancelPlan(I: CodeceptJS.I, expirationDate: Date, canRenewSubscription: boolean, providerName?: string) {
export async function cancelPlan(I: CodeceptJS.I, expirationDate: Date, canRenewSubscription: boolean, providerName?: string) {
I.amOnPage(constants.paymentsUrl);
I.waitForLoaderDone();

if (providerName?.includes('JW')) {
I.waitForElement('[data-testid="change-subscription-button"]', 10);
I.click('[data-testid="change-subscription-button"]');
}

I.waitForElement('[data-testid="cancel-subscription-button"]', 10);
I.click('[data-testid="cancel-subscription-button"]');
I.see('We are sorry to see you go.');
I.see('You will be unsubscribed from your current plan by clicking the unsubscribe button below.');
I.see('Unsubscribe');
// Make sure the cancel button works
I.click('No, thanks');
// sometimes the response takes too long, and we retry this test while the subscription is canceled
const isAlreadyCancelled = await tryTo(() => {
I.see('This plan will expire on ' + formatDate(expirationDate));
});

I.dontSee('This plan will expire');
if (!isAlreadyCancelled) {
if (providerName?.includes('JW')) {
I.waitForElement('[data-testid="change-subscription-button"]', 10);
I.click('[data-testid="change-subscription-button"]');
}

I.waitForElement('[data-testid="cancel-subscription-button"]', 10);
I.click('[data-testid="cancel-subscription-button"]');
I.click('Unsubscribe');
I.waitForText('Miss you already.', longTimeout);
I.see('You have been successfully unsubscribed. Your current plan will expire on ' + formatDate(expirationDate));
I.click('Return to profile');
I.waitForElement('[data-testid="cancel-subscription-button"]', 10);
I.click('[data-testid="cancel-subscription-button"]');
I.see('We are sorry to see you go.');
I.see('You will be unsubscribed from your current plan by clicking the unsubscribe button below.');
I.see('Unsubscribe');
// Make sure the cancel button works
I.click('No, thanks');

I.dontSee('This plan will expire');

I.waitForElement('[data-testid="cancel-subscription-button"]', 10);
I.click('[data-testid="cancel-subscription-button"]');
I.click('Unsubscribe');
I.waitForText('Miss you already.', longTimeout);
I.see('You have been successfully unsubscribed. Your current plan will expire on ' + formatDate(expirationDate));
I.click('Return to profile');
}

if (canRenewSubscription) {
I.waitForText('Renew subscription');
Expand Down

0 comments on commit 04323b6

Please sign in to comment.