diff --git a/ghost/portal/src/actions.js b/ghost/portal/src/actions.js index 65318692db..a62d065f70 100644 --- a/ghost/portal/src/actions.js +++ b/ghost/portal/src/actions.js @@ -111,11 +111,12 @@ async function signup({data, state, api}) { lastPage: 'signup' }; } catch (e) { + const message = e?.message || 'Failed to sign up, please try again'; return { action: 'signup:failed', popupNotification: createPopupNotification({ type: 'signup:failed', autoHide: false, closeable: true, state, status: 'error', - message: 'Failed to sign up, please try again' + message }) }; } diff --git a/ghost/portal/src/components/common/ProductsSection.js b/ghost/portal/src/components/common/ProductsSection.js index c1bebd1b73..edb8125559 100644 --- a/ghost/portal/src/components/common/ProductsSection.js +++ b/ghost/portal/src/components/common/ProductsSection.js @@ -624,7 +624,9 @@ function ProductCard({product, products, selectedInterval, handleChooseSignup}) const {action} = useContext(AppContext); const cardClass = selectedProduct === product.id ? 'gh-portal-product-card checked' : 'gh-portal-product-card'; - const noOfProducts = products.length; + const noOfProducts = products?.filter((d) => { + return d.type === 'paid'; + })?.length; let disabled = (['signup:running', 'checkoutPlan:running'].includes(action)) ? true : false; diff --git a/ghost/portal/src/components/pages/SignupPage.test.js b/ghost/portal/src/components/pages/SignupPage.test.js index 22f1b2b5f0..e4e557a405 100644 --- a/ghost/portal/src/components/pages/SignupPage.test.js +++ b/ghost/portal/src/components/pages/SignupPage.test.js @@ -29,11 +29,12 @@ const setup = (overrides) => { describe('SignupPage', () => { test('renders', () => { - const {nameInput, emailInput, chooseButton, signinButton} = setup(); + const {nameInput, emailInput, queryAllByRole, signinButton} = setup(); + const chooseButton = queryAllByRole('button', {name: 'Continue'}); expect(nameInput).toBeInTheDocument(); expect(emailInput).toBeInTheDocument(); - expect(chooseButton).toHaveLength(2); + expect(chooseButton).toHaveLength(1); expect(signinButton).toBeInTheDocument(); }); diff --git a/ghost/portal/src/tests/SignupFlow.test.js b/ghost/portal/src/tests/SignupFlow.test.js index 3f6f7d5736..e124ec1f60 100644 --- a/ghost/portal/src/tests/SignupFlow.test.js +++ b/ghost/portal/src/tests/SignupFlow.test.js @@ -185,7 +185,7 @@ describe('Signup', () => { } = await setup({ site: FixtureSite.singleTier.basic }); - + const continueButton = within(popupIframeDocument).queryAllByRole('button', {name: 'Continue'}); expect(popupFrame).toBeInTheDocument(); expect(triggerButtonFrame).toBeInTheDocument(); expect(siteTitle).toBeInTheDocument(); @@ -197,7 +197,8 @@ describe('Signup', () => { // expect(fullAccessTitle).toBeInTheDocument(); expect(signinButton).toBeInTheDocument(); // expect(submitButton).toBeInTheDocument(); - expect(chooseBtns).toHaveLength(2); + expect(chooseBtns).toHaveLength(1); + expect(continueButton).toHaveLength(1); fireEvent.change(nameInput, {target: {value: 'Jamie Larsen'}}); fireEvent.change(emailInput, {target: {value: 'jamie@example.com'}}); @@ -232,7 +233,7 @@ describe('Signup', () => { expect(yearlyPlanTitle).toBeInTheDocument(); // expect(fullAccessTitle).toBeInTheDocument(); expect(signinButton).toBeInTheDocument(); - expect(chooseBtns).toHaveLength(2); + expect(chooseBtns).toHaveLength(1); fireEvent.change(emailInput, {target: {value: 'jamie@example.com'}}); @@ -294,7 +295,7 @@ describe('Signup', () => { test('with default settings on monthly plan', async () => { const { ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, signinButton, chooseBtns, - siteTitle, popupIframeDocument, freePlanTitle, monthlyPlanTitle, yearlyPlanTitle + siteTitle, popupIframeDocument, freePlanTitle, monthlyPlanTitle, yearlyPlanTitle, submitButton } = await setup({ site: FixtureSite.singleTier.basic }); @@ -308,7 +309,7 @@ describe('Signup', () => { expect(monthlyPlanTitle).toBeInTheDocument(); expect(yearlyPlanTitle).toBeInTheDocument(); expect(signinButton).toBeInTheDocument(); - expect(chooseBtns).toHaveLength(2); + expect(chooseBtns).toHaveLength(1); const monthlyPlanContainer = within(popupIframeDocument).queryByText(/Monthly$/); const singleTierProduct = FixtureSite.singleTier.basic.products.find(p => p.type === 'paid'); @@ -322,7 +323,7 @@ describe('Signup', () => { await within(popupIframeDocument).findByText(benefitText); expect(emailInput).toHaveValue('jamie@example.com'); expect(nameInput).toHaveValue('Jamie Larsen'); - fireEvent.click(chooseBtns[1]); + fireEvent.click(submitButton); expect(ghostApi.member.checkoutPlan).toHaveBeenLastCalledWith({ email: 'jamie@example.com', name: 'Jamie Larsen', @@ -335,8 +336,7 @@ describe('Signup', () => { test('with default settings on yearly plan', async () => { const { - ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, signinButton, chooseBtns, - siteTitle, popupIframeDocument, freePlanTitle, monthlyPlanTitle, yearlyPlanTitle + ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, signinButton, chooseBtns, submitButton, siteTitle, popupIframeDocument, freePlanTitle, monthlyPlanTitle, yearlyPlanTitle } = await setup({ site: FixtureSite.singleTier.basic }); @@ -350,7 +350,7 @@ describe('Signup', () => { expect(monthlyPlanTitle).toBeInTheDocument(); expect(yearlyPlanTitle).toBeInTheDocument(); expect(signinButton).toBeInTheDocument(); - expect(chooseBtns).toHaveLength(2); + expect(chooseBtns).toHaveLength(1); const yearlyPlanContainer = within(popupIframeDocument).queryByText(/Yearly$/); const singleTierProduct = FixtureSite.singleTier.basic.products.find(p => p.type === 'paid'); @@ -364,7 +364,7 @@ describe('Signup', () => { await within(popupIframeDocument).findByText(benefitText); expect(emailInput).toHaveValue('jamie@example.com'); expect(nameInput).toHaveValue('Jamie Larsen'); - fireEvent.click(chooseBtns[1]); + fireEvent.click(submitButton); expect(ghostApi.member.checkoutPlan).toHaveBeenLastCalledWith({ email: 'jamie@example.com', name: 'Jamie Larsen', @@ -380,7 +380,7 @@ describe('Signup', () => { test('without name field on monthly plan', async () => { const { ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, signinButton, chooseBtns, - siteTitle, popupIframeDocument, freePlanTitle, monthlyPlanTitle, yearlyPlanTitle + siteTitle, popupIframeDocument, freePlanTitle, monthlyPlanTitle, yearlyPlanTitle, submitButton } = await setup({ site: FixtureSite.singleTier.withoutName }); @@ -398,7 +398,7 @@ describe('Signup', () => { expect(monthlyPlanTitle).toBeInTheDocument(); expect(yearlyPlanTitle).toBeInTheDocument(); expect(signinButton).toBeInTheDocument(); - expect(chooseBtns).toHaveLength(2); + expect(chooseBtns).toHaveLength(1); fireEvent.change(emailInput, {target: {value: 'jamie@example.com'}}); @@ -406,7 +406,7 @@ describe('Signup', () => { await within(popupIframeDocument).findByText(benefitText); expect(emailInput).toHaveValue('jamie@example.com'); - fireEvent.click(chooseBtns[1]); + fireEvent.click(submitButton); expect(ghostApi.member.checkoutPlan).toHaveBeenLastCalledWith({ email: 'jamie@example.com', diff --git a/ghost/portal/src/utils/api.js b/ghost/portal/src/utils/api.js index fb4bcc1ba4..83c1db7f0e 100644 --- a/ghost/portal/src/utils/api.js +++ b/ghost/portal/src/utils/api.js @@ -354,9 +354,11 @@ function setupGhostApi({siteUrl = window.location.origin, apiUrl, apiKey}) { 'Content-Type': 'application/json' }, body: JSON.stringify(body) - }).then(function (res) { + }).then(async function (res) { if (!res.ok) { - throw new Error('Could not create stripe checkout session'); + const errData = await res.json(); + const errMssg = errData?.errors?.[0]?.message || 'Failed to signup, please try again.'; + throw new Error(errMssg); } return res.json(); }).then(function (result) { @@ -402,7 +404,7 @@ function setupGhostApi({siteUrl = window.location.origin, apiUrl, apiKey}) { }) }).then(function (res) { if (!res.ok) { - throw new Error('Could not create stripe checkout session'); + throw new Error('Unable to create stripe checkout session'); } return res.json(); }).then(function (result) {