diff --git a/packages/cypress/src/integration/supporter.spec.ts b/packages/cypress/src/integration/supporter.spec.ts new file mode 100644 index 0000000000..3020ddb35b --- /dev/null +++ b/packages/cypress/src/integration/supporter.spec.ts @@ -0,0 +1,59 @@ +import { MOCK_DATA } from '../data'; +import { getTenantUser } from '../utils/TestUtils'; + +const supporter = getTenantUser(MOCK_DATA.users.subscriber); + +const stripeReturnUrl = (email: string) => + `/support?payment=success&customer=cus_stubbed&email=${encodeURIComponent(email)}&name=Test%20Supporter`; + +describe('[Supporter]', () => { + it('[Collects supporter details and starts checkout]', () => { + cy.step('Stub the checkout call so the flow stops at the Stripe boundary'); + cy.intercept('POST', '/api/stripe', { + statusCode: 500, + body: { error: 'stubbed at the Stripe boundary' }, + }).as('startCheckout'); + + cy.visit('/support'); + + cy.step('Choose a plan and fill in supporter details'); + cy.get('[data-cy=price-option]').first().click(); + cy.get('[data-cy=supporter-name]').clear().type('Test Supporter'); + cy.get('[data-cy=supporter-email]').clear().type(supporter.email); + + cy.step('Submitting sends the selected plan and details to the server'); + cy.get('[data-cy=supporter-submit]').click(); + + cy.wait('@startCheckout').its('request.body').should('deep.include', { + action: 'elements_subscription', + name: 'Test Supporter', + email: supporter.email, + }); + }); + + it('[Sets up the account after payment and lands on email preferences]', () => { + cy.step('Stub the account endpoints that would otherwise talk to Stripe'); + cy.intercept('POST', '/api/stripe/create-account', { + statusCode: 200, + body: { success: true }, + }).as('createAccount'); + cy.intercept('POST', '/api/stripe/set-password', { + statusCode: 200, + body: { success: true }, + }).as('setPassword'); + + cy.step('Return from Stripe as a paid supporter'); + cy.visit(stripeReturnUrl(supporter.email)); + cy.wait('@createAccount'); + + cy.step('Set a password to finish creating the account'); + cy.get('[data-cy=supporter-account-form]').should('be.visible'); + cy.get('[data-cy=supporter-password]').type(supporter.password); + cy.get('[data-cy=supporter-set-password]').click(); + cy.wait('@setPassword'); + + cy.step('New supporters are sent to their email preferences'); + cy.url().should('include', '/setup-email-preferences'); + cy.get('[data-cy=email-preferences-submit]').should('be.visible'); + }); +}); diff --git a/src/config/config.ts b/src/config/config.ts index 4dea4a9f92..28b79e53b1 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -58,6 +58,11 @@ export const isProductionEnvironment = (): boolean => { return site === 'production'; }; +export const isTestEnvironment = (): boolean => { + const site = getSiteVariant(); + return site === 'test-ci'; +}; + export const SITE = siteVariant; export const SENTRY_CONFIG: ISentryConfig = { dsn: _c('VITE_SENTRY_DSN'), diff --git a/src/pages/Supporter/SupporterCTA.tsx b/src/pages/Supporter/SupporterCTA.tsx index 3e0634c944..5b097846b5 100644 --- a/src/pages/Supporter/SupporterCTA.tsx +++ b/src/pages/Supporter/SupporterCTA.tsx @@ -7,16 +7,18 @@ export const SupporterCTA = ({ children, color, type = 'button', + dataCy, }: { onClick?: () => void; disabled?: boolean; children: ReactNode; color: string; type?: 'button' | 'submit'; + dataCy?: string; }) => ( { setSelectedPriceId(price.id)} sx={{ display: 'flex', @@ -214,6 +215,7 @@ export const SupporterForm = () => { {fieldErrors.name} )} { @@ -234,6 +236,7 @@ export const SupporterForm = () => { {fieldErrors.email} )} { alignSelf: 'stretch', }} > - + {isLoading ? ( 'Processing...' ) : ( diff --git a/src/pages/Supporter/ThankYouAccountForm.tsx b/src/pages/Supporter/ThankYouAccountForm.tsx index 30caf0d3b7..7418004b78 100644 --- a/src/pages/Supporter/ThankYouAccountForm.tsx +++ b/src/pages/Supporter/ThankYouAccountForm.tsx @@ -55,6 +55,7 @@ export const ThankYouAccountForm = () => { return ( { Password setPassword(e.target.value)} @@ -125,6 +127,7 @@ export const ThankYouAccountForm = () => { {error && {error}}