import { test, expect } from '@playwright/test'; import { Page } from '@playwright/test'; test.describe('Subscription Flow', () => { let page: Page; test.beforeEach(async ({ page }) => { page = page; }); test('should display pricing page', async () => { await page.goto('/pricing'); // Check page title await expect(page).toHaveTitle(/Pricing/); // Check pricing plans await expect(page.locator('[data-testid="pricing-plans"]')).toBeVisible(); await expect(page.locator('[data-testid="plan-basic"]')).toBeVisible(); await expect(page.locator('[data-testid="plan-pro"]')).toBeVisible(); await expect(page.locator('[data-testid="plan-enterprise"]')).toBeVisible(); }); test('should show plan details', async () => { await page.goto('/pricing'); // Click on Pro plan await page.locator('[data-testid="plan-pro"]').click(); // Check modal opens with details await expect(page.locator('[data-testid="plan-modal"]')).toBeVisible(); await expect(page.locator('text=Pro Plan Features')).toBeVisible(); // Check features list await expect(page.locator('[data-testid="feature-list"]')).toBeVisible(); await expect(page.locator('text=Unlimited users')).toBeVisible(); await expect(page.locator('text=100GB storage')).toBeVisible(); await expect(page.locator('text=Priority support')).toBeVisible(); }); test('should select plan and proceed to checkout', async () => { await page.goto('/pricing'); // Select Pro plan await page.locator('[data-testid="plan-pro"] [data-testid="select-plan"]').click(); // Should redirect to checkout await expect(page).toHaveURL(/checkout/); // Check checkout page elements await expect(page.locator('[data-testid="checkout-form"]')).toBeVisible(); await expect(page.locator('[data-testid="plan-summary"]')).toBeVisible(); await expect(page.locator('[data-testid="payment-method"]')).toBeVisible(); }); test('should fill payment form', async () => { // Mock user is logged in await page.goto('/checkout?plan=pro'); // Fill card details await page.locator('[data-testid="card-number"]').fill('4242424242424242'); await page.locator('[data-testid="card-expiry"]').fill('12/25'); await page.locator('[data-testid="card-cvc"]').fill('123'); await page.locator('[data-testid="card-name"]').fill('John Doe'); // Fill billing address await page.locator('[data-testid="billing-address"]').fill('123 Main St'); await page.locator('[data-testid="billing-city"]').fill('New York'); await page.locator('[data-testid="billing-zip"]').fill('10001'); await page.locator('[data-testid="billing-country"]').selectOption('US'); // Accept terms await page.locator('[data-testid="accept-terms"]').check(); // Enable auto-renew await page.locator('[data-testid="auto-renew"]').check(); }); test('should validate payment form', async () => { await page.goto('/checkout?plan=pro'); // Submit empty form await page.locator('[data-testid="submit-payment"]').click(); // Check validation errors await expect(page.locator('text=Card number is required')).toBeVisible(); await expect(page.locator('text=Expiry date is required')).toBeVisible(); await expect(page.locator('text=CVC is required')).toBeVisible(); await expect(page.locator('text=Name on card is required')).toBeVisible(); }); test('should validate card number format', async () => { await page.goto('/checkout?plan=pro'); // Enter invalid card number await page.locator('[data-testid="card-number"]').fill('123456'); await page.locator('[data-testid="submit-payment"]').click(); await expect(page.locator('text=Please enter a valid card number')).toBeVisible(); }); test('should process subscription successfully', async () => { // Mock Stripe success response await page.route('/api/billing/subscribe', route => { route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ success: true, subscription: { id: 'sub_123', status: 'active', plan: 'pro', current_period_end: '2026-02-20', }, }), }); }); await page.goto('/checkout?plan=pro'); // Fill valid payment details await page.locator('[data-testid="card-number"]').fill('4242424242424242'); await page.locator('[data-testid="card-expiry"]').fill('12/25'); await page.locator('[data-testid="card-cvc"]').fill('123'); await page.locator('[data-testid="card-name"]').fill('John Doe'); await page.locator('[data-testid="accept-terms"]').check(); // Submit payment await page.locator('[data-testid="submit-payment"]').click(); // Should show success message await expect(page.locator('[data-testid="success-message"]')).toBeVisible(); await expect(page.locator('text=Subscription successful!')).toBeVisible(); // Should redirect to dashboard await expect(page).toHaveURL(/dashboard/); }); test('should handle payment failure', async () => { // Mock Stripe error response await page.route('/api/billing/subscribe', route => { route.fulfill({ status: 400, contentType: 'application/json', body: JSON.stringify({ error: { message: 'Your card was declined.', code: 'card_declined', }, }), }); }); await page.goto('/checkout?plan=pro'); // Fill payment details await page.locator('[data-testid="card-number"]').fill('4000000000000002'); await page.locator('[data-testid="card-expiry"]').fill('12/25'); await page.locator('[data-testid="card-cvc"]').fill('123'); await page.locator('[data-testid="card-name"]').fill('John Doe'); await page.locator('[data-testid="accept-terms"]').check(); // Submit payment await page.locator('[data-testid="submit-payment"]').click(); // Should show error message await expect(page.locator('[data-testid="error-message"]')).toBeVisible(); await expect(page.locator('text=Your card was declined')).toBeVisible(); }); test('should support multiple payment methods', async () => { await page.goto('/checkout?plan=pro'); // Check available payment methods await expect(page.locator('[data-testid="payment-card"]')).toBeVisible(); await expect(page.locator('[data-testid="payment-paypal"]')).toBeVisible(); await expect(page.locator('[data-testid="payment-bank-transfer"]')).toBeVisible(); // Select PayPal await page.locator('[data-testid="payment-paypal"]').click(); // Should show PayPal form await expect(page.locator('[data-testid="paypal-form"]')).toBeVisible(); await expect(page.locator('[data-testid="paypal-email"]')).toBeVisible(); }); test('should apply discount code', async () => { await page.goto('/checkout?plan=pro'); // Enter discount code await page.locator('[data-testid="discount-code"]').fill('SAVE20'); await page.locator('[data-testid="apply-discount"]').click(); // Should show discount applied await expect(page.locator('[data-testid="discount-applied"]')).toBeVisible(); await expect(page.locator('text=20% discount applied')).toBeVisible(); // Check updated price await expect(page.locator('[data-testid="final-price"]')).toContainText('$79.20'); }); test('should handle invalid discount code', async () => { await page.goto('/checkout?plan=pro'); // Enter invalid discount code await page.locator('[data-testid="discount-code"]').fill('INVALID'); await page.locator('[data-testid="apply-discount"]').click(); // Should show error await expect(page.locator('[data-testid="discount-error"]')).toBeVisible(); await expect(page.locator('text=Invalid discount code')).toBeVisible(); }); test('should show subscription management', async () => { // Mock authenticated user with active subscription await page.goto('/settings/billing'); // Check subscription details await expect(page.locator('[data-testid="current-plan"]')).toBeVisible(); await expect(page.locator('text=Pro Plan')).toBeVisible(); await expect(page.locator('[data-testid="subscription-status"]')).toContainText('Active'); await expect(page.locator('[data-testid="next-billing"]')).toBeVisible(); // Check management options await expect(page.locator('[data-testid="update-payment"]')).toBeVisible(); await expect(page.locator('[data-testid="cancel-subscription"]')).toBeVisible(); await expect(page.locator('[data-testid="download-invoices"]')).toBeVisible(); }); test('should handle subscription upgrade', async () => { await page.goto('/settings/billing'); // Click upgrade button await page.locator('[data-testid="upgrade-plan"]').click(); // Should show upgrade options await expect(page.locator('[data-testid="upgrade-modal"]')).toBeVisible(); await expect(page.locator('[data-testid="plan-enterprise"]')).toBeVisible(); // Select Enterprise plan await page.locator('[data-testid="select-enterprise"]').click(); // Should show prorated billing info await expect(page.locator('[data-testid="prorated-amount"]')).toBeVisible(); await expect(page.locator('text=Prorated amount due today')).toBeVisible(); }); test('should handle subscription cancellation', async () => { await page.goto('/settings/billing'); // Click cancel subscription await page.locator('[data-testid="cancel-subscription"]').click(); // Should show cancellation modal await expect(page.locator('[data-testid="cancel-modal"]')).toBeVisible(); await expect(page.locator('text=Are you sure you want to cancel?')).toBeVisible(); // Select cancellation reason await page.locator('[data-testid="cancellation-reason"]').selectOption('too_expensive'); // Add feedback await page.locator('[data-testid="cancellation-feedback"]').fill('Found a cheaper alternative'); // Confirm cancellation await page.locator('[data-testid="confirm-cancellation"]').click(); // Should show confirmation await expect(page.locator('[data-testid="cancellation-success"]')).toBeVisible(); await expect(page.locator('text=Subscription will be cancelled at the end of the billing period')).toBeVisible(); }); test('should handle subscription reactivation', async () => { // Mock cancelled subscription await page.goto('/settings/billing'); // Check reactivation option is available await expect(page.locator('[data-testid="reactivate-subscription"]')).toBeVisible(); // Click reactivate await page.locator('[data-testid="reactivate-subscription"]').click(); // Should show reactivation modal await expect(page.locator('[data-testid="reactivate-modal"]')).toBeVisible(); await expect(page.locator('text=Reactivate your subscription')).toBeVisible(); // Confirm reactivation await page.locator('[data-testid="confirm-reactivation"]').click(); // Should process reactivation await expect(page.locator('[data-testid="reactivation-success"]')).toBeVisible(); }); test('should display invoice history', async () => { await page.goto('/settings/billing'); // Click invoices tab await page.locator('[data-testid="invoices-tab"]').click(); // Check invoice list await expect(page.locator('[data-testid="invoice-list"]')).toBeVisible(); await expect(page.locator('[data-testid="invoice-item"]')).toHaveCount(3); // Check invoice details await expect(page.locator('[data-testid="invoice-date"]')).toBeVisible(); await expect(page.locator('[data-testid="invoice-amount"]')).toBeVisible(); await expect(page.locator('[data-testid="invoice-status"]')).toBeVisible(); await expect(page.locator('[data-testid="download-invoice"]')).toBeVisible(); }); test('should download invoice', async () => { // Mock download const downloadPromise = page.waitForEvent('download'); await page.goto('/settings/billing'); await page.locator('[data-testid="invoices-tab"]').click(); // Click download button await page.locator('[data-testid="download-invoice"]').first().click(); // Wait for download const download = await downloadPromise; expect(download.suggestedFilename()).toMatch(/invoice-\d+\.pdf/); }); test('should update payment method', async () => { await page.goto('/settings/billing'); // Click update payment method await page.locator('[data-testid="update-payment"]').click(); // Should show payment form await expect(page.locator('[data-testid="payment-form"]')).toBeVisible(); // Fill new card details await page.locator('[data-testid="card-number"]').fill('5555555555554444'); await page.locator('[data-testid="card-expiry"]').fill('10/26'); await page.locator('[data-testid="card-cvc"]').fill('456'); await page.locator('[data-testid="card-name"]').fill('Jane Smith'); // Submit update await page.locator('[data-testid="update-payment-submit"]').click(); // Should show success message await expect(page.locator('[data-testid="update-success"]')).toBeVisible(); await expect(page.locator('text=Payment method updated successfully')).toBeVisible(); }); });