/** * Subscription & Purchase Flow E2E Tests * * Critical flows tested: * 1. Subscription page loads correctly * 2. Subscription status display * 3. Subscribe button functionality * 4. Stripe payment sheet opens (if available) * 5. Demo mode activation * 6. Subscription management */ import { test, expect } from '@playwright/test'; import { LoginPage, OtpPage, BeneficiaryDetailPage, SubscriptionPage, } from '../helpers/page-objects'; import { enableConsoleLogging, TEST_CREDENTIALS, BASE_URL, } from '../helpers/test-helpers'; // Run tests serially test.describe.configure({ mode: 'serial' }); test.describe('Subscription Flow', () => { test.beforeEach(async ({ page }) => { enableConsoleLogging(page); // Login const loginPage = new LoginPage(page); await loginPage.goto(); const isOnLogin = await loginPage.welcomeText.isVisible({ timeout: 2000 }).catch(() => false); if (isOnLogin) { await loginPage.loginWithEmail(TEST_CREDENTIALS.existingUser.email); const otpPage = new OtpPage(page); await otpPage.expectLoaded(); await otpPage.enterCode(TEST_CREDENTIALS.existingUser.bypassOtp); await page.waitForTimeout(3000); } }); test('1. Subscription page loads correctly', async ({ page }) => { await page.goto(BASE_URL); await page.waitForLoadState('networkidle'); await page.waitForTimeout(3000); // Navigate to beneficiary const firstCard = page.locator('[data-testid="beneficiary-card"]').first(); if (await firstCard.isVisible({ timeout: 3000 })) { await firstCard.click(); await page.waitForTimeout(2000); // Navigate to subscription const subscriptionButton = page.getByText('Subscription'); if (await subscriptionButton.isVisible({ timeout: 2000 })) { await subscriptionButton.click(); await page.waitForTimeout(2000); const subscriptionPage = new SubscriptionPage(page); await subscriptionPage.expectLoaded(); console.log('✅ Subscription page loaded'); } else { console.log('⚠️ Subscription button not visible'); } } else { console.log('⚠️ No beneficiary to test'); } }); test('2. Subscription shows current status', async ({ page }) => { await page.goto(BASE_URL); await page.waitForLoadState('networkidle'); await page.waitForTimeout(3000); const firstCard = page.locator('[data-testid="beneficiary-card"]').first(); if (await firstCard.isVisible({ timeout: 3000 })) { await firstCard.click(); await page.waitForTimeout(2000); const subscriptionButton = page.getByText('Subscription'); if (await subscriptionButton.isVisible({ timeout: 2000 })) { await subscriptionButton.click(); await page.waitForTimeout(2000); const subscriptionPage = new SubscriptionPage(page); // Check for status indicators const isActive = await subscriptionPage.isSubscriptionActive(); const isDemo = await subscriptionPage.isDemoMode(); const hasSubscribeButton = await subscriptionPage.subscribeButton.isVisible({ timeout: 2000 }).catch(() => false); console.log(`Active: ${isActive}, Demo: ${isDemo}, Subscribe button: ${hasSubscribeButton}`); // At least one status should be visible expect(isActive || isDemo || hasSubscribeButton).toBe(true); console.log('✅ Subscription status displayed'); } } }); test('3. Subscribe button is clickable', async ({ page }) => { await page.goto(BASE_URL); await page.waitForLoadState('networkidle'); await page.waitForTimeout(3000); const firstCard = page.locator('[data-testid="beneficiary-card"]').first(); if (await firstCard.isVisible({ timeout: 3000 })) { await firstCard.click(); await page.waitForTimeout(2000); const subscriptionButton = page.getByText('Subscription'); if (await subscriptionButton.isVisible({ timeout: 2000 })) { await subscriptionButton.click(); await page.waitForTimeout(2000); const subscriptionPage = new SubscriptionPage(page); const hasSubscribeButton = await subscriptionPage.subscribeButton.isVisible({ timeout: 2000 }).catch(() => false); if (hasSubscribeButton) { // Click subscribe but don't complete payment await subscriptionPage.subscribe(); await page.waitForTimeout(3000); // Should open payment sheet or show payment options const hasPaymentUI = await Promise.race([ page.getByText(/Card number|Payment/i).isVisible({ timeout: 5000 }).catch(() => false), page.getByText(/Stripe/i).isVisible({ timeout: 5000 }).catch(() => false), page.locator('[data-testid="payment-sheet"]').isVisible({ timeout: 5000 }).catch(() => false), ]); console.log(`Payment UI visible: ${hasPaymentUI}`); console.log('✅ Subscribe button works'); } else { console.log('⚠️ No subscribe button (already subscribed)'); } } } }); test('4. Demo mode option available', async ({ page }) => { await page.goto(BASE_URL); await page.waitForLoadState('networkidle'); await page.waitForTimeout(3000); const firstCard = page.locator('[data-testid="beneficiary-card"]').first(); if (await firstCard.isVisible({ timeout: 3000 })) { await firstCard.click(); await page.waitForTimeout(2000); const subscriptionButton = page.getByText('Subscription'); if (await subscriptionButton.isVisible({ timeout: 2000 })) { await subscriptionButton.click(); await page.waitForTimeout(2000); // Check for demo mode option const hasDemoOption = await page.getByText(/Demo|Try.*Free|Free Trial/i).isVisible({ timeout: 2000 }).catch(() => false); console.log(`Demo option visible: ${hasDemoOption}`); console.log('✅ Demo mode check complete'); } } }); test('5. Subscription plan options displayed', async ({ page }) => { await page.goto(BASE_URL); await page.waitForLoadState('networkidle'); await page.waitForTimeout(3000); const firstCard = page.locator('[data-testid="beneficiary-card"]').first(); if (await firstCard.isVisible({ timeout: 3000 })) { await firstCard.click(); await page.waitForTimeout(2000); const subscriptionButton = page.getByText('Subscription'); if (await subscriptionButton.isVisible({ timeout: 2000 })) { await subscriptionButton.click(); await page.waitForTimeout(2000); // Check for pricing/plan info const hasPricing = await page.getByText(/\$|€|month|year|plan/i).isVisible({ timeout: 2000 }).catch(() => false); console.log(`Pricing info visible: ${hasPricing}`); console.log('✅ Plan options check complete'); } } }); }); test.describe('Purchase Flow (Auth)', () => { test.beforeEach(async ({ page }) => { enableConsoleLogging(page); }); test('Purchase screen accessible from auth flow', async ({ page }) => { const loginPage = new LoginPage(page); await loginPage.goto(); await loginPage.expectLoaded(); // Use new email to trigger new user flow const newEmail = `purchase.test.${Date.now()}@test.com`; await loginPage.loginWithEmail(newEmail); const otpPage = new OtpPage(page); await otpPage.expectLoaded(); await otpPage.enterCode(TEST_CREDENTIALS.newUser.bypassOtp); await page.waitForTimeout(5000); // New user should eventually reach purchase screen or see purchase option const hasPurchaseOption = await Promise.race([ page.getByText(/Purchase|Buy|Subscribe|Equipment/i).isVisible({ timeout: 10000 }).catch(() => false), page.getByText(/Demo/i).isVisible({ timeout: 10000 }).catch(() => false), page.getByText('Add a Loved One').isVisible({ timeout: 10000 }).catch(() => false), ]); console.log(`Purchase/onboarding option visible: ${hasPurchaseOption}`); console.log('✅ Purchase flow accessible'); }); }); test.describe('Stripe Integration', () => { test.beforeEach(async ({ page }) => { enableConsoleLogging(page); const loginPage = new LoginPage(page); await loginPage.goto(); const isOnLogin = await loginPage.welcomeText.isVisible({ timeout: 2000 }).catch(() => false); if (isOnLogin) { await loginPage.loginWithEmail(TEST_CREDENTIALS.existingUser.email); const otpPage = new OtpPage(page); await otpPage.expectLoaded(); await otpPage.enterCode(TEST_CREDENTIALS.existingUser.bypassOtp); await page.waitForTimeout(3000); } }); test('Stripe payment elements load correctly', async ({ page }) => { await page.goto(BASE_URL); await page.waitForLoadState('networkidle'); await page.waitForTimeout(3000); const firstCard = page.locator('[data-testid="beneficiary-card"]').first(); if (await firstCard.isVisible({ timeout: 3000 })) { await firstCard.click(); await page.waitForTimeout(2000); const subscriptionButton = page.getByText('Subscription'); if (await subscriptionButton.isVisible({ timeout: 2000 })) { await subscriptionButton.click(); await page.waitForTimeout(2000); const subscribeButton = page.getByText('Subscribe'); if (await subscribeButton.isVisible({ timeout: 2000 })) { await subscribeButton.click(); await page.waitForTimeout(5000); // Check for Stripe elements const hasCardInput = await page.getByPlaceholder(/Card number/i).isVisible({ timeout: 5000 }).catch(() => false); const hasStripeFrame = await page.locator('iframe[name*="stripe"]').isVisible({ timeout: 5000 }).catch(() => false); console.log(`Card input: ${hasCardInput}, Stripe frame: ${hasStripeFrame}`); console.log('✅ Stripe integration check complete'); } else { console.log('⚠️ Subscribe button not visible'); } } } }); test('Payment sheet can be closed', async ({ page }) => { await page.goto(BASE_URL); await page.waitForLoadState('networkidle'); await page.waitForTimeout(3000); const firstCard = page.locator('[data-testid="beneficiary-card"]').first(); if (await firstCard.isVisible({ timeout: 3000 })) { await firstCard.click(); await page.waitForTimeout(2000); const subscriptionButton = page.getByText('Subscription'); if (await subscriptionButton.isVisible({ timeout: 2000 })) { await subscriptionButton.click(); await page.waitForTimeout(2000); const subscribeButton = page.getByText('Subscribe'); if (await subscribeButton.isVisible({ timeout: 2000 })) { await subscribeButton.click(); await page.waitForTimeout(3000); // Try to close payment sheet const closeButton = page.getByText(/Close|Cancel|X/i); if (await closeButton.isVisible({ timeout: 2000 })) { await closeButton.click(); await page.waitForTimeout(1000); // Should be back on subscription page const backOnSubscription = await page.getByText('Subscribe').isVisible({ timeout: 2000 }).catch(() => false); console.log(`Back on subscription page: ${backOnSubscription}`); } console.log('✅ Payment sheet close check complete'); } } } }); });