mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-03 08:25:06 +03:00
Added portal data attributes tests
closes https://github.com/TryGhost/Team/issues/1364 - extends data attributes test to cover `data-portal=*` tests
This commit is contained in:
parent
58f2025038
commit
98f212c3df
@ -99,9 +99,6 @@ export default class App extends React.Component {
|
||||
|
||||
/** Setup custom trigger buttons handling on page */
|
||||
setupCustomTriggerButton() {
|
||||
if (hasMode(['test'])) {
|
||||
return;
|
||||
}
|
||||
// Handler for custom buttons
|
||||
this.clickHandler = (event) => {
|
||||
event.preventDefault();
|
||||
@ -217,7 +214,7 @@ export default class App extends React.Component {
|
||||
// Setup test mode data
|
||||
if (hasMode(['test'])) {
|
||||
return {
|
||||
showPopup: true
|
||||
showPopup: this.props.showPopup !== undefined ? this.props.showPopup : true
|
||||
};
|
||||
}
|
||||
return {};
|
||||
|
@ -1,4 +1,8 @@
|
||||
import App from '../App';
|
||||
import {site as FixturesSite, member as FixtureMember} from '../utils/test-fixtures';
|
||||
import {fireEvent, appRender, within} from '../utils/test-utils';
|
||||
import {site as FixtureSite} from '../utils/test-fixtures';
|
||||
import setupGhostApi from '../utils/api';
|
||||
const {formSubmitHandler, planClickHandler} = require('../data-attributes');
|
||||
|
||||
// Mock data
|
||||
@ -68,7 +72,7 @@ function getMockData() {
|
||||
};
|
||||
}
|
||||
|
||||
describe('Data attributes:', () => {
|
||||
describe('Member Data attributes:', () => {
|
||||
beforeEach(() => {
|
||||
// Mock global fetch
|
||||
jest.spyOn(window, 'fetch').mockImplementation((url) => {
|
||||
@ -120,55 +124,279 @@ describe('Data attributes:', () => {
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
test('data-members-form: allows free signup', () => {
|
||||
const {event, form, errorEl, siteUrl, submitHandler} = getMockData();
|
||||
describe('data-members-form', () => {
|
||||
test('allows free signup', () => {
|
||||
const {event, form, errorEl, siteUrl, submitHandler} = getMockData();
|
||||
|
||||
formSubmitHandler({event, form, errorEl, siteUrl, submitHandler});
|
||||
formSubmitHandler({event, form, errorEl, siteUrl, submitHandler});
|
||||
|
||||
expect(window.fetch).toHaveBeenCalledTimes(1);
|
||||
expect(window.fetch).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(window.fetch).toHaveBeenCalledWith('https://portal.localhost/members/api/send-magic-link/', {body: '{"email":"jamie@example.com","emailType":"signup","labels":["Gold"],"name":"Jamie Larsen"}', headers: {'Content-Type': 'application/json'}, method: 'POST'});
|
||||
expect(window.fetch).toHaveBeenCalledWith('https://portal.localhost/members/api/send-magic-link/', {body: '{"email":"jamie@example.com","emailType":"signup","labels":["Gold"],"name":"Jamie Larsen"}', headers: {'Content-Type': 'application/json'}, method: 'POST'});
|
||||
});
|
||||
});
|
||||
|
||||
test('data-members-plan: allows new member paid signup via direct checkout', async () => {
|
||||
const {event, errorEl, siteUrl, clickHandler, site, member, element} = getMockData();
|
||||
describe('data-members-plan', () => {
|
||||
test('allows new member paid signup via direct checkout', async () => {
|
||||
const {event, errorEl, siteUrl, clickHandler, site, member, element} = getMockData();
|
||||
|
||||
const paidTier = site.products.find(p => p.type === 'paid');
|
||||
const plan = paidTier.monthlyPrice.id;
|
||||
const paidTier = site.products.find(p => p.type === 'paid');
|
||||
const plan = paidTier.monthlyPrice.id;
|
||||
|
||||
await planClickHandler({event, errorEl, siteUrl, clickHandler, site, member, el: element});
|
||||
expect(window.fetch).toHaveBeenNthCalledWith(1,
|
||||
'https://portal.localhost/members/api/session', {
|
||||
await planClickHandler({event, errorEl, siteUrl, clickHandler, site, member, el: element});
|
||||
expect(window.fetch).toHaveBeenNthCalledWith(1,
|
||||
'https://portal.localhost/members/api/session', {
|
||||
credentials: 'same-origin'
|
||||
}
|
||||
);
|
||||
expect(window.fetch).toHaveBeenNthCalledWith(2,
|
||||
'https://portal.localhost/members/api/create-stripe-checkout-session/', {
|
||||
body: `{"priceId":"${plan}","identity":"session-identity","successUrl":"https://portal.localhost/success","cancelUrl":"https://portal.localhost/cancel","metadata":{}}`,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
method: 'POST'
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('data-members-plan', () => {
|
||||
test('allows free member upgrade via direct checkout', async () => {
|
||||
let {event, errorEl, siteUrl, clickHandler, site, member, element} = getMockData();
|
||||
member = FixtureMember.free;
|
||||
const paidTier = site.products.find(p => p.type === 'paid');
|
||||
const plan = paidTier.monthlyPrice.id;
|
||||
|
||||
await planClickHandler({event, errorEl, siteUrl, clickHandler, site, member, el: element});
|
||||
expect(window.fetch).toHaveBeenNthCalledWith(1, 'https://portal.localhost/members/api/session', {
|
||||
credentials: 'same-origin'
|
||||
}
|
||||
);
|
||||
expect(window.fetch).toHaveBeenNthCalledWith(2,
|
||||
'https://portal.localhost/members/api/create-stripe-checkout-session/', {
|
||||
body: `{"priceId":"${plan}","identity":"session-identity","successUrl":"https://portal.localhost/success","cancelUrl":"https://portal.localhost/cancel","metadata":{}}`,
|
||||
});
|
||||
expect(window.fetch).toHaveBeenNthCalledWith(2, 'https://portal.localhost/members/api/create-stripe-checkout-session/', {
|
||||
body: `{"priceId":"${plan}","identity":"session-identity","successUrl":"https://portal.localhost/success","cancelUrl":"https://portal.localhost/cancel","metadata":{"checkoutType":"upgrade"}}`,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
method: 'POST'
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('data-members-plan: allows free member upgrade via direct checkout', async () => {
|
||||
let {event, errorEl, siteUrl, clickHandler, site, member, element} = getMockData();
|
||||
member = FixtureMember.free;
|
||||
const paidTier = site.products.find(p => p.type === 'paid');
|
||||
const plan = paidTier.monthlyPrice.id;
|
||||
|
||||
await planClickHandler({event, errorEl, siteUrl, clickHandler, site, member, el: element});
|
||||
expect(window.fetch).toHaveBeenNthCalledWith(1, 'https://portal.localhost/members/api/session', {
|
||||
credentials: 'same-origin'
|
||||
});
|
||||
expect(window.fetch).toHaveBeenNthCalledWith(2, 'https://portal.localhost/members/api/create-stripe-checkout-session/', {
|
||||
body: `{"priceId":"${plan}","identity":"session-identity","successUrl":"https://portal.localhost/success","cancelUrl":"https://portal.localhost/cancel","metadata":{"checkoutType":"upgrade"}}`,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
method: 'POST'
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const setup = async ({site, member = null, showPopup = true}) => {
|
||||
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');
|
||||
});
|
||||
|
||||
ghostApi.member.checkoutPlan = jest.fn(() => {
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
const utils = appRender(
|
||||
<App api={ghostApi} showPopup={showPopup} />
|
||||
);
|
||||
|
||||
const triggerButtonFrame = await utils.findByTitle(/portal-trigger/i);
|
||||
const popupFrame = utils.queryByTitle(/portal-popup/i);
|
||||
return {
|
||||
ghostApi,
|
||||
popupFrame,
|
||||
triggerButtonFrame,
|
||||
...utils
|
||||
};
|
||||
};
|
||||
|
||||
describe('Portal Data attributes:', () => {
|
||||
beforeEach(() => {
|
||||
// Mock global fetch
|
||||
jest.spyOn(window, 'fetch').mockImplementation((url) => {
|
||||
if (url.includes('send-magic-link')) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
json: async () => ({success: true})
|
||||
});
|
||||
}
|
||||
|
||||
if (url.includes('api/session')) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
text: async () => {
|
||||
return 'session-identity';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (url.includes('create-stripe-checkout-session')) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
json: async () => {
|
||||
return {
|
||||
publicKey: 'key-xyz'
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
return Promise.resolve({});
|
||||
});
|
||||
|
||||
// Mock global Stripe
|
||||
window.Stripe = () => {};
|
||||
jest.spyOn(window, 'Stripe').mockImplementation(() => {
|
||||
return {
|
||||
redirectToCheckout: () => {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// Mock window.location
|
||||
let locationMock = jest.fn();
|
||||
delete window.location;
|
||||
window.location = {assign: locationMock};
|
||||
window.location.href = (new URL('https://portal.localhost')).href;
|
||||
window.location.hash = '';
|
||||
});
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
describe('data-portal', () => {
|
||||
test('opens default portal page', async () => {
|
||||
document.body.innerHTML = `
|
||||
<div data-portal> </div>
|
||||
`;
|
||||
let {
|
||||
popupFrame, triggerButtonFrame, ...utils
|
||||
} = await setup({
|
||||
site: FixtureSite.singleTier.basic,
|
||||
showPopup: false
|
||||
});
|
||||
expect(popupFrame).not.toBeInTheDocument();
|
||||
expect(triggerButtonFrame).toBeInTheDocument();
|
||||
const portalElement = document.querySelector('[data-portal]');
|
||||
fireEvent.click(portalElement);
|
||||
popupFrame = await utils.findByTitle(/portal-popup/i);
|
||||
expect(popupFrame).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('data-portal=signin', () => {
|
||||
test('opens Portal signin page', async () => {
|
||||
document.body.innerHTML = `
|
||||
<div data-portal="signin"> </div>
|
||||
`;
|
||||
let {
|
||||
popupFrame, triggerButtonFrame, ...utils
|
||||
} = await setup({
|
||||
site: FixtureSite.singleTier.basic,
|
||||
showPopup: false
|
||||
});
|
||||
expect(popupFrame).not.toBeInTheDocument();
|
||||
expect(triggerButtonFrame).toBeInTheDocument();
|
||||
const portalElement = document.querySelector('[data-portal]');
|
||||
fireEvent.click(portalElement);
|
||||
popupFrame = await utils.findByTitle(/portal-popup/i);
|
||||
expect(popupFrame).toBeInTheDocument();
|
||||
const loginTitle = within(popupFrame.contentDocument).queryByText(/log in/i);
|
||||
expect(loginTitle).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('data-portal=signup', () => {
|
||||
test('opens Portal signup page', async () => {
|
||||
document.body.innerHTML = `
|
||||
<div data-portal="signup"> </div>
|
||||
`;
|
||||
let {
|
||||
popupFrame, triggerButtonFrame, ...utils
|
||||
} = await setup({
|
||||
site: FixtureSite.singleTier.basic,
|
||||
showPopup: false
|
||||
});
|
||||
expect(popupFrame).not.toBeInTheDocument();
|
||||
expect(triggerButtonFrame).toBeInTheDocument();
|
||||
const portalElement = document.querySelector('[data-portal]');
|
||||
fireEvent.click(portalElement);
|
||||
popupFrame = await utils.findByTitle(/portal-popup/i);
|
||||
expect(popupFrame).toBeInTheDocument();
|
||||
const loginTitle = within(popupFrame.contentDocument).queryByText(/already a member/i);
|
||||
expect(loginTitle).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('data-portal=account', () => {
|
||||
test('opens Portal account home page', async () => {
|
||||
document.body.innerHTML = `
|
||||
<div data-portal="account"> </div>
|
||||
`;
|
||||
let {
|
||||
popupFrame, triggerButtonFrame, ...utils
|
||||
} = await setup({
|
||||
site: FixtureSite.singleTier.basic,
|
||||
member: FixtureMember.free,
|
||||
showPopup: false
|
||||
});
|
||||
expect(popupFrame).not.toBeInTheDocument();
|
||||
expect(triggerButtonFrame).toBeInTheDocument();
|
||||
const portalElement = document.querySelector('[data-portal]');
|
||||
fireEvent.click(portalElement);
|
||||
popupFrame = await utils.findByTitle(/portal-popup/i);
|
||||
expect(popupFrame).toBeInTheDocument();
|
||||
const accountHomeTitle = within(popupFrame.contentDocument).queryByText(/your account/i);
|
||||
expect(accountHomeTitle).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('data-portal=account/plans', () => {
|
||||
test('opens Portal account plan page', async () => {
|
||||
document.body.innerHTML = `
|
||||
<div data-portal="account/plans"> </div>
|
||||
`;
|
||||
let {
|
||||
popupFrame, triggerButtonFrame, ...utils
|
||||
} = await setup({
|
||||
site: FixtureSite.singleTier.basic,
|
||||
member: FixtureMember.free,
|
||||
showPopup: false
|
||||
});
|
||||
expect(popupFrame).not.toBeInTheDocument();
|
||||
expect(triggerButtonFrame).toBeInTheDocument();
|
||||
const portalElement = document.querySelector('[data-portal]');
|
||||
fireEvent.click(portalElement);
|
||||
popupFrame = await utils.findByTitle(/portal-popup/i);
|
||||
expect(popupFrame).toBeInTheDocument();
|
||||
const accountPlanTitle = within(popupFrame.contentDocument).queryByText(/choose a plan/i);
|
||||
expect(accountPlanTitle).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('data-portal=account/profile', () => {
|
||||
test('opens Portal account profile page', async () => {
|
||||
document.body.innerHTML = `
|
||||
<div data-portal="account/profile"> </div>
|
||||
`;
|
||||
let {
|
||||
popupFrame, triggerButtonFrame, ...utils
|
||||
} = await setup({
|
||||
site: FixtureSite.singleTier.basic,
|
||||
member: FixtureMember.free,
|
||||
showPopup: false
|
||||
});
|
||||
expect(popupFrame).not.toBeInTheDocument();
|
||||
expect(triggerButtonFrame).toBeInTheDocument();
|
||||
const portalElement = document.querySelector('[data-portal]');
|
||||
fireEvent.click(portalElement);
|
||||
popupFrame = await utils.findByTitle(/portal-popup/i);
|
||||
expect(popupFrame).toBeInTheDocument();
|
||||
const accountProfileTitle = within(popupFrame.contentDocument).queryByText(/account settings/i);
|
||||
expect(accountProfileTitle).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user