0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00

Added playwright test for free member upgrade via portal (#15961)

refs https://github.com/TryGhost/Team/issues/2371

- tests that a free member can upgrade to a paid tier via stripe checkout and the payment details are reflected in portal and member detail page on admin
This commit is contained in:
Rishabh Garg 2022-12-07 21:41:55 +05:30 committed by GitHub
parent 80b766047e
commit b6db85a5d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 91 additions and 1 deletions

View file

@ -3,7 +3,7 @@
<h4>Start building your audience</h4>
{{#if (not-eq this.settings.membersSignupAccess "none")}}
<p>Use memberships to allow your readers to sign up and subscribe to your content.</p>
<button class="gh-btn gh-btn-green" type="button" {{on "click" this.addYourself}}>
<button class="gh-btn gh-btn-green" type="button" {{on "click" this.addYourself}} data-test-button="add-yourself">
<span>Add yourself as a member to test</span>
</button>
<p class="gh-members-empty-secondary-cta">Have members already? <LinkTo @route="member.new">Add them manually</LinkTo> or <LinkTo @route="members.import">import from CSV</LinkTo></p>

View file

@ -21,6 +21,7 @@
<fieldset>
<div class="gh-input-group">
<GhTextInput
data-test-input="member-signin-url"
@id="member-signin-url"
@name="member-signin-url"
@disabled={{true}}
@ -29,12 +30,14 @@
/>
{{#if this.signinUrl}}
<GhTaskButton
data-test-button="copy-impersonate-link"
@buttonText="Copy link"
@task={{this.copySigninUrl}}
@successText="Link copied"
@class="gh-btn gh-btn-black gh-btn-icon" />
{{else}}
<GhTaskButton
data-test-button="impersonate-link-copied"
@buttonText="Copy link"
@task={{this.copySigninUrl}}
@successText="Link copied"

View file

@ -0,0 +1,49 @@
const {expect, test} = require('@playwright/test');
const {completeStripeSubscription, createMember} = require('../utils');
test.describe('Portal', () => {
test.describe('Upgrade', () => {
test('allows free member upgrade to paid tier', async ({page}) => {
// create a new free member
await createMember(page, {
name: 'Testy McTest',
email: 'testy@example.com',
note: 'Testy McTest is a test member'
});
//get the url of the current member on admin
const memberUrl = await page.url();
// open member impersonation modal
await page.locator('[data-test-button="member-actions"]').click();
await page.locator('[data-test-button="impersonate"]').click();
await page.locator('[data-test-button="copy-impersonate-link"]').click();
await page.waitForSelector('[data-test-button="copy-impersonate-link"] span:has-text("Link copied")');
// get impersonation link from input and redirect to it
const link = await page.locator('[data-test-input="member-signin-url"]').inputValue();
await page.goto(link);
const portalTriggerButton = page.frameLocator('#ghost-portal-root iframe.gh-portal-triggerbtn-iframe').locator('div').nth(1);
const portalFrame = page.frameLocator('#ghost-portal-root div iframe');
// open portal, go to plans and click continue to select the first plan(yearly)
await portalTriggerButton.click();
// view plans button only shows for free member
await portalFrame.getByRole('button', {name: 'View plans'}).click();
await portalFrame.getByRole('button', {name: 'Continue'}).click();
// complete stripe checkout
await completeStripeSubscription(page);
// open portal and check that member has been upgraded to paid tier
await portalTriggerButton.click();
await expect(portalFrame.getByText('$50.00/year')).toBeVisible();
await expect(portalFrame.getByRole('heading', {name: 'Billing info'})).toBeVisible();
await expect(portalFrame.getByText('**** **** **** 4242')).toBeVisible();
// check that member has been upgraded in admin and a tier exists for them
await page.goto(memberUrl);
await expect(page.locator('[data-test-tier]').first()).toBeVisible();
});
});
});

View file

@ -236,6 +236,12 @@ const createOffer = async (page, {name, tierName, offerType, amount}) => {
return offerName;
};
const fillInputIfExists = async (page, selector, value) => {
if (await page.isVisible(selector)) {
await page.locator(selector).fill(value);
}
};
const completeStripeSubscription = async (page) => {
await page.locator('#cardNumber').fill('4242 4242 4242 4242');
await page.locator('#cardExpiry').fill('04 / 24');
@ -243,14 +249,46 @@ const completeStripeSubscription = async (page) => {
await page.locator('#billingName').fill('Testy McTesterson');
await page.getByRole('combobox', {name: 'Country or region'}).selectOption('US');
await page.locator('#billingPostalCode').fill('42424');
await fillInputIfExists(page, '#billingAddressLine1', '123 Test St');
await fillInputIfExists(page, '#billingAddressLine2', 'Apt 1');
await fillInputIfExists(page, '#billingLocality', 'Testville');
await page.getByTestId('hosted-payment-submit-button').click();
};
const createMember = async (page, {email, name, note, label = ''}) => {
await page.goto('/ghost');
await page.locator('.gh-nav a[href="#/members/"]').click();
await page.waitForSelector('a[href="#/members/new/"] span');
await page.locator('a[href="#/members/new/"] span:has-text("New member")').click();
await page.waitForSelector('input[name="name"]');
await page.fill('input[name="email"]', email);
if (name) {
await page.fill('input[name="name"]', name);
}
if (note) {
await page.fill('textarea[name="note"]', note);
}
if (label) {
await page.locator('label:has-text("Labels") + div').click();
await page.keyboard.type(label);
await page.keyboard.press('Tab');
}
await page.locator('button span:has-text("Save")').click();
await page.waitForSelector('button span:has-text("Saved")');
};
module.exports = {
setupGhost,
setupStripe,
deleteAllMembers,
createTier,
createOffer,
createMember,
completeStripeSubscription
};