0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-17 23:44:39 -05:00

Added free member signup flow tests for multiple tiers

closes https://github.com/TryGhost/Team/issues/1345

- adds free member signup tests for sites with multiple tiers
- updates test fixtures
This commit is contained in:
Rishabh 2022-02-15 13:13:07 +05:30
parent 83a4a0e62a
commit 0921217fd8
2 changed files with 240 additions and 62 deletions

View file

@ -51,14 +51,63 @@ const setup = async ({site, member = null}) => {
}; };
}; };
describe('App with tiers disabled', () => { const multiTierSetup = async ({site, member = null}) => {
const ghostApi = setupGhostApi({siteUrl: 'https://example.com'});
ghostApi.init = jest.fn(() => {
return Promise.resolve({
site,
member
});
});
ghostApi.member.sendMagicLink = jest.fn(() => {
return Promise.resolve('success');
});
const utils = appRender(
<App api={ghostApi} />
);
const freeTierDescription = site.products?.find(p => p.type === 'free')?.description;
const triggerButtonFrame = await utils.findByTitle(/portal-trigger/i);
const popupFrame = utils.queryByTitle(/portal-popup/i);
const popupIframeDocument = popupFrame.contentDocument;
const emailInput = within(popupIframeDocument).queryByLabelText(/email/i);
const nameInput = within(popupIframeDocument).queryByLabelText(/name/i);
const submitButton = within(popupIframeDocument).queryByRole('button', {name: 'Continue'});
const signinButton = within(popupIframeDocument).queryByRole('button', {name: 'Sign in'});
const siteTitle = within(popupIframeDocument).queryByText(site.title);
const freePlanTitle = within(popupIframeDocument).queryAllByText(/free$/i);
const freePlanDescription = within(popupIframeDocument).queryAllByText(freeTierDescription);
const monthlyPlanTitle = within(popupIframeDocument).queryByText('Monthly');
const yearlyPlanTitle = within(popupIframeDocument).queryByText('Yearly');
const fullAccessTitle = within(popupIframeDocument).queryByText('Full access');
return {
ghostApi,
popupIframeDocument,
popupFrame,
triggerButtonFrame,
siteTitle,
emailInput,
nameInput,
signinButton,
submitButton,
freePlanTitle,
monthlyPlanTitle,
yearlyPlanTitle,
fullAccessTitle,
freePlanDescription,
...utils
};
};
describe('Single tier site', () => {
describe('Signup page', () => { describe('Signup page', () => {
test('renders basic signup page', async () => { test('renders with default settings', async () => {
const { const {
ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, signinButton, submitButton, ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, signinButton, submitButton,
siteTitle, popupIframeDocument, freePlanTitle, monthlyPlanTitle, yearlyPlanTitle, fullAccessTitle siteTitle, popupIframeDocument, freePlanTitle, monthlyPlanTitle, yearlyPlanTitle, fullAccessTitle
} = await setup({ } = await setup({
site: FixtureSite.tiersDisabled.basic site: FixtureSite.singleTier.basic
}); });
expect(popupFrame).toBeInTheDocument(); expect(popupFrame).toBeInTheDocument();
@ -88,12 +137,12 @@ describe('App with tiers disabled', () => {
expect(magicLink).toBeInTheDocument(); expect(magicLink).toBeInTheDocument();
}); });
test('renders signup page without name', async () => { test('renders without portal name', async () => {
const { const {
ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, signinButton, submitButton, ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, signinButton, submitButton,
siteTitle, popupIframeDocument, freePlanTitle, monthlyPlanTitle, yearlyPlanTitle, fullAccessTitle siteTitle, popupIframeDocument, freePlanTitle, monthlyPlanTitle, yearlyPlanTitle, fullAccessTitle
} = await setup({ } = await setup({
site: FixtureSite.tiersDisabled.withoutName site: FixtureSite.singleTier.withoutName
}); });
expect(popupFrame).toBeInTheDocument(); expect(popupFrame).toBeInTheDocument();
@ -124,12 +173,12 @@ describe('App with tiers disabled', () => {
expect(magicLink).toBeInTheDocument(); expect(magicLink).toBeInTheDocument();
}); });
test('renders signup page with only free plan', async () => { test('renders with only free plan', async () => {
let { let {
ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, signinButton, submitButton, ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, signinButton, submitButton,
siteTitle, popupIframeDocument, freePlanTitle, monthlyPlanTitle, yearlyPlanTitle, fullAccessTitle siteTitle, popupIframeDocument, freePlanTitle, monthlyPlanTitle, yearlyPlanTitle, fullAccessTitle
} = await setup({ } = await setup({
site: FixtureSite.tiersDisabled.onlyFreePlan site: FixtureSite.singleTier.onlyFreePlan
}); });
expect(popupFrame).toBeInTheDocument(); expect(popupFrame).toBeInTheDocument();
@ -164,3 +213,108 @@ describe('App with tiers disabled', () => {
}); });
}); });
}); });
describe('Multiple tiers site', () => {
describe('Signup page', () => {
test('renders with default settings', async () => {
const {
ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, signinButton, submitButton,
siteTitle, popupIframeDocument, freePlanTitle
} = await multiTierSetup({
site: FixtureSite.multipleTiers.basic
});
expect(popupFrame).toBeInTheDocument();
expect(triggerButtonFrame).toBeInTheDocument();
expect(siteTitle).toBeInTheDocument();
expect(emailInput).toBeInTheDocument();
expect(nameInput).toBeInTheDocument();
expect(freePlanTitle[0]).toBeInTheDocument();
expect(signinButton).toBeInTheDocument();
expect(submitButton).toBeInTheDocument();
fireEvent.change(nameInput, {target: {value: 'Jamie Larsen'}});
fireEvent.change(emailInput, {target: {value: 'jamie@example.com'}});
expect(emailInput).toHaveValue('jamie@example.com');
expect(nameInput).toHaveValue('Jamie Larsen');
fireEvent.click(submitButton);
expect(ghostApi.member.sendMagicLink).toHaveBeenLastCalledWith({
email: 'jamie@example.com',
name: 'Jamie Larsen',
plan: 'free'
});
const magicLink = await within(popupIframeDocument).findByText(/now check your email/i);
expect(magicLink).toBeInTheDocument();
});
test('renders without portal name', async () => {
const {
ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, signinButton, submitButton,
siteTitle, popupIframeDocument, freePlanTitle
} = await multiTierSetup({
site: FixtureSite.multipleTiers.withoutName
});
expect(popupFrame).toBeInTheDocument();
expect(triggerButtonFrame).toBeInTheDocument();
expect(siteTitle).toBeInTheDocument();
expect(emailInput).toBeInTheDocument();
expect(nameInput).not.toBeInTheDocument();
expect(freePlanTitle[0]).toBeInTheDocument();
expect(signinButton).toBeInTheDocument();
expect(submitButton).toBeInTheDocument();
fireEvent.change(emailInput, {target: {value: 'jamie@example.com'}});
expect(emailInput).toHaveValue('jamie@example.com');
fireEvent.click(submitButton);
expect(ghostApi.member.sendMagicLink).toHaveBeenLastCalledWith({
email: 'jamie@example.com',
name: '',
plan: 'free'
});
// Check if magic link page is shown
const magicLink = await within(popupIframeDocument).findByText(/now check your email/i);
expect(magicLink).toBeInTheDocument();
});
test('renders with only free plan', async () => {
let {
ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, signinButton, submitButton,
siteTitle, popupIframeDocument, freePlanTitle
} = await multiTierSetup({
site: FixtureSite.multipleTiers.onlyFreePlan
});
expect(popupFrame).toBeInTheDocument();
expect(triggerButtonFrame).toBeInTheDocument();
expect(siteTitle).toBeInTheDocument();
expect(emailInput).toBeInTheDocument();
expect(nameInput).toBeInTheDocument();
expect(freePlanTitle.length).toBe(0);
expect(signinButton).toBeInTheDocument();
expect(submitButton).not.toBeInTheDocument();
submitButton = within(popupIframeDocument).queryByRole('button', {name: 'Sign up'});
fireEvent.change(emailInput, {target: {value: 'jamie@example.com'}});
fireEvent.change(nameInput, {target: {value: 'Jamie Larsen'}});
expect(emailInput).toHaveValue('jamie@example.com');
expect(nameInput).toHaveValue('Jamie Larsen');
fireEvent.click(submitButton);
expect(ghostApi.member.sendMagicLink).toHaveBeenLastCalledWith({
email: 'jamie@example.com',
name: 'Jamie Larsen',
plan: 'free'
});
// Check if magic link page is shown
const magicLink = await within(popupIframeDocument).findByText(/now check your email/i);
expect(magicLink).toBeInTheDocument();
});
});
});

View file

@ -1,13 +1,10 @@
/* eslint-disable no-unused-vars*/ /* eslint-disable no-unused-vars*/
import {getFreeProduct, getMemberData, getOfferData, getPriceData, getProductData, getSiteData, getSubscriptionData, getTestSite} from './fixtures-generator'; import {getFreeProduct, getMemberData, getOfferData, getPriceData, getProductData, getSiteData, getSubscriptionData, getTestSite} from './fixtures-generator';
export const testSite = getTestSite(); const singleSiteTier = [
const products = [
getFreeProduct({ getFreeProduct({
name: 'Free', name: 'Free',
// description: 'Free tier description which is actually a pretty long description', description: 'Free tier description',
description: '',
numOfBenefits: 0 numOfBenefits: 0
}) })
, ,
@ -25,37 +22,39 @@ const products = [
}), }),
numOfBenefits: 2 numOfBenefits: 2
}) })
// ,
// getProductData({
// name: 'Silver',
// description: 'Access to all members articles and weekly podcast',
// monthlyPrice: getPriceData({
// interval: 'month',
// amount: 1200
// }),
// yearlyPrice: getPriceData({
// interval: 'year',
// amount: 12000
// }),
// numOfBenefits: 3
// })
// getProductData({
// name: 'Friends of the Blueprint',
// description: 'Get access to everything and lock in early adopter pricing for life + listen to my podcast',
// monthlyPrice: getPriceData({
// interval: 'month',
// amount: 18000
// }),
// yearlyPrice: getPriceData({
// interval: 'year',
// amount: 17000
// }),
// numOfBenefits: 4
// })
]; ];
const basicSite = getSiteData({ const multipleSiteTiers = [
...singleSiteTier,
getProductData({
name: 'Silver',
description: 'Access to all members articles and weekly podcast',
monthlyPrice: getPriceData({
interval: 'month',
amount: 1200
}),
yearlyPrice: getPriceData({
interval: 'year',
amount: 12000
}),
numOfBenefits: 3
}),
getProductData({
name: 'Friends of the Blueprint',
description: 'Get access to everything and lock in early adopter pricing for life + listen to my podcast',
monthlyPrice: getPriceData({
interval: 'month',
amount: 18000
}),
yearlyPrice: getPriceData({
interval: 'year',
amount: 17000
}),
numOfBenefits: 4
})
];
const baseSingleTierSite = getSiteData({
title: 'The Blueprint', title: 'The Blueprint',
description: 'Thoughts, stories and ideas.', description: 'Thoughts, stories and ideas.',
logo: 'https://static.ghost.org/v4.0.0/images/ghost-orb-1.png', logo: 'https://static.ghost.org/v4.0.0/images/ghost-orb-1.png',
@ -67,16 +66,8 @@ const basicSite = getSiteData({
yearly: 150000, yearly: 150000,
currency: 'USD' currency: 'USD'
}, },
products: singleSiteTier,
// Simulate pre-multiple-tiers state: portalProducts: singleSiteTier.filter(p => p.type === 'paid').map(p => p.id),
// products: [products.find(d => d.type === 'paid')],
// portalProducts: null,
// Simulate multiple-tiers state:
products,
portalProducts: products.map(p => p.id),
//
allowSelfSignup: true, allowSelfSignup: true,
membersSignupAccess: 'all', membersSignupAccess: 'all',
freePriceName: 'Free', freePriceName: 'Free',
@ -91,28 +82,61 @@ const basicSite = getSiteData({
membersSupportAddress: 'support@example.com' membersSupportAddress: 'support@example.com'
}); });
const tiersDisabledSite = { const baseMultiTierSite = getSiteData({
...basicSite, title: 'The Blueprint',
portal_products: undefined, description: 'Thoughts, stories and ideas.',
products: [products.find(d => d.type === 'paid')] logo: 'https://static.ghost.org/v4.0.0/images/ghost-orb-1.png',
}; icon: 'https://static.ghost.org/v4.0.0/images/ghost-orb-1.png',
accentColor: '#45C32E',
url: 'https://portal.localhost',
plans: {
monthly: 5000,
yearly: 150000,
currency: 'USD'
},
products: multipleSiteTiers,
portalProducts: multipleSiteTiers.filter(p => p.type === 'paid').map(p => p.id),
allowSelfSignup: true,
membersSignupAccess: 'all',
freePriceName: 'Free',
freePriceDescription: 'Free preview',
isStripeConfigured: true,
portalButton: true,
portalName: true,
portalPlans: ['free', 'monthly', 'yearly'],
portalButtonIcon: 'icon-1',
portalButtonSignupText: 'Subscribe now',
portalButtonStyle: 'icon-and-text',
membersSupportAddress: 'support@example.com'
});
export const site = { export const site = {
tiersDisabled: { singleTier: {
basic: tiersDisabledSite, basic: baseSingleTierSite,
onlyFreePlan: { onlyFreePlan: {
...tiersDisabledSite, ...baseSingleTierSite,
portal_plans: 'free' portal_plans: ['free']
}, },
withoutName: { withoutName: {
...tiersDisabledSite, ...baseSingleTierSite,
portal_name: false
}
},
multipleTiers: {
basic: baseMultiTierSite,
onlyFreePlan: {
...baseMultiTierSite,
portal_plans: ['free']
},
withoutName: {
...baseMultiTierSite,
portal_name: false portal_name: false
} }
} }
}; };
export const offer = getOfferData({ export const offer = getOfferData({
tierId: basicSite.products[0]?.id tierId: baseSingleTierSite.products[0]?.id
}); });
export const member = { export const member = {