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:
parent
83a4a0e62a
commit
0921217fd8
2 changed files with 240 additions and 62 deletions
|
@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
Loading…
Add table
Reference in a new issue