Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions packages/cypress/src/integration/supporter.spec.ts
Original file line number Diff line number Diff line change
@@ -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');
});
});
5 changes: 5 additions & 0 deletions src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand Down
4 changes: 3 additions & 1 deletion src/pages/Supporter/SupporterCTA.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}) => (
<Box
as="button"
{...({ type, disabled } as any)}
{...({ type, disabled, 'data-cy': dataCy } as any)}
onClick={onClick}
sx={{
width: '100%',
Expand Down
10 changes: 9 additions & 1 deletion src/pages/Supporter/SupporterForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ export const SupporterForm = () => {
<Box
key={price.id}
as="button"
data-cy="price-option"
onClick={() => setSelectedPriceId(price.id)}
sx={{
display: 'flex',
Expand Down Expand Up @@ -214,6 +215,7 @@ export const SupporterForm = () => {
<Text sx={{ fontSize: '14px', color: 'error' }}>{fieldErrors.name}</Text>
)}
<Input
data-cy="supporter-name"
placeholder="Your name"
value={name}
onChange={(e) => {
Expand All @@ -234,6 +236,7 @@ export const SupporterForm = () => {
<Text sx={{ fontSize: '14px', color: 'error' }}>{fieldErrors.email}</Text>
)}
<Input
data-cy="supporter-email"
type="email"
placeholder="Email"
value={email}
Expand Down Expand Up @@ -262,7 +265,12 @@ export const SupporterForm = () => {
alignSelf: 'stretch',
}}
>
<SupporterCTA onClick={handleSupport} disabled={disabled} color={tierColor}>
<SupporterCTA
dataCy="supporter-submit"
onClick={handleSupport}
disabled={disabled}
color={tierColor}
>
{isLoading ? (
'Processing...'
) : (
Expand Down
5 changes: 4 additions & 1 deletion src/pages/Supporter/ThankYouAccountForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export const ThankYouAccountForm = () => {
return (
<ThankYouLayout>
<Card
data-cy="supporter-account-form"
sx={{
bg: 'white',
border: '2px solid',
Expand Down Expand Up @@ -98,6 +99,7 @@ export const ThankYouAccountForm = () => {
Password
</Text>
<Input
data-cy="supporter-password"
type={showPassword ? 'text' : 'password'}
value={password}
onChange={(e) => setPassword(e.target.value)}
Expand Down Expand Up @@ -125,6 +127,7 @@ export const ThankYouAccountForm = () => {
{error && <Text sx={{ color: 'red', fontSize: 1 }}>{error}</Text>}

<Button
data-cy="supporter-set-password"
type="submit"
variant="primary"
disabled={isSubmitting || password.length < 6}
Expand All @@ -146,7 +149,7 @@ export const ThankYouAccountForm = () => {
<form
ref={signInFormRef}
method="post"
action={`/sign-in?returnUrl=${encodeURIComponent('/settings/account')}`}
action={`/sign-in?returnUrl=${encodeURIComponent('/setup-email-preferences')}`}
style={{ display: 'none' }}
>
<input type="hidden" name="email" value={email} />
Expand Down
3 changes: 2 additions & 1 deletion src/services/stripeService.server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { SupabaseClient } from '@supabase/supabase-js';
import { isTestEnvironment } from 'src/config/config';
import { logger } from 'src/logger';
import { createSupabaseAdminServerClient } from 'src/repository/supabaseAdmin.server';
import { getSecret } from 'src/services/secretsService.server';
Expand Down Expand Up @@ -416,7 +417,7 @@ export class StripeServiceServer {
async getPrices(): Promise<SupporterPrice[]> {
const stripe = await getStripe();
if (!stripe) {
return process.env.NODE_ENV === 'development' ? STUB_PRICES : [];
return process.env.NODE_ENV === 'development' || isTestEnvironment() ? STUB_PRICES : [];
}
const tierMap = await this.getProductTierMap();
const productIds = [...tierMap.keys()];
Expand Down
Loading