Testing Guide
New in v2.2! SaaSavant includes 148 comprehensive tests covering all critical functionality. Run them locally or in CI/CD pipelines.
Overview
SaaSavant comes with a complete test suite that ensures all critical features work correctly:
- 125 Unit Tests - Individual component and function testing
- 23 Integration Tests - Complete user flow testing
- E2E Tests - Browser-based UI testing with Playwright
Running Tests
Quick Start
# Run all tests in watch mode
npm test
# Press 'a' to run all tests
Test Commands
# Run all tests with coverage (CI mode)
npm run test:ci
# Run only unit tests
npm run test:unit
# Run only integration tests
npm run test:integration
# Run E2E tests with Playwright
npm run test:e2e
# Run E2E tests with Playwright UI (visual mode)
npm run test:e2e:ui
What's Tested
Authentication (27 tests)
- ✅ Sign up flow with email/password
- ✅ Sign in validation
- ✅ Password reset functionality
- ✅ User creation in Firestore
- ✅ Error handling
Subscriptions (54 tests)
- ✅ Stripe checkout session creation
- ✅ Subscription lifecycle management
- ✅ Payment success/failure handling
- ✅ Subscription updates and cancellations
- ✅ Premium status validation
Support System (16 tests)
- ✅ Ticket creation
- ✅ Ticket status updates
- ✅ Ticket retrieval
- ✅ Admin ticket management
Account Management (12 tests)
- ✅ Account deletion
- ✅ Data cleanup
- ✅ Subscription cancellation on deletion
API Routes (16 tests)
- ✅ Webhook event processing
- ✅ Checkout endpoint
- ✅ Portal endpoint
- ✅ Email sending
Utilities (16 tests)
- ✅ Stripe client functions
- ✅ Premium status checker
- ✅ Helper functions
Test Structure
__tests__/
├── unit/ # Unit tests (125 tests)
│ ├── auth/ # Authentication tests
│ ├── subscriptions/ # Subscription tests
│ ├── support/ # Support ticket tests
│ ├── account/ # Account management tests
│ ├── api/ # API route tests
│ └── lib/ # Utility tests
├── integration/ # Integration tests (23 tests)
│ ├── auth-flow.test.tsx
│ └── subscription-flow.test.ts
├── e2e/ # E2E tests (Playwright)
│ ├── auth.spec.ts
│ ├── subscription.spec.ts
│ └── support-tickets.spec.ts
├── mocks/ # Test mocks
│ ├── firebase.ts
│ └── stripe.ts
└── utils/ # Test utilities
└── test-utils.tsx
Writing Tests
Unit Test Example
import { render, screen } from '@testing-library/react';
import SignUpForm from '@/components/user/SignUp';
describe('SignUpForm', () => {
it('renders sign up form', () => {
render(<SignUpForm />);
expect(screen.getByText('Sign Up')).toBeInTheDocument();
});
it('validates email format', async () => {
render(<SignUpForm />);
// Test email validation
});
});
Integration Test Example
describe('Authentication Flow', () => {
it('completes full sign up and sign in flow', async () => {
// 1. Sign up new user
// 2. Verify user in Firestore
// 3. Sign out
// 4. Sign in with same credentials
// 5. Verify authenticated state
});
});
Test Configuration
Jest Configuration
Tests use Jest with the following setup:
- Environment: jsdom (browser-like environment)
- Transform: Next.js SWC compiler
- Coverage: Enabled with thresholds
- Mocks: Firebase and Stripe automatically mocked
Playwright Configuration
E2E tests use Playwright with:
- Browsers: Chromium, Firefox, WebKit
- Base URL: http://localhost:3000 (opens in a new tab)
- Screenshots: On failure
- Videos: On first retry
Troubleshooting
Tests Failing
Check environment variables:
# Make sure .env.local is configured
cp .env.example .env.local
Clear Jest cache:
macOS/Linux:
npx jest --clearCache
npm test
Windows:
npx jest --clearCache
npm test
E2E Tests Failing
Install Playwright browsers:
npx playwright install
Run with UI mode for debugging:
npm run test:e2e:ui
Mock Issues
If Firebase or Stripe mocks aren't working:
- Check
__tests__/mocks/firebase.ts
- Check
__tests__/mocks/stripe.ts
- Verify
jest.setup.js
is loading mocks
Coverage Reports
After running npm run test:ci
, view coverage:
macOS:
# Coverage report is in coverage/ directory
open coverage/lcov-report/index.html
Windows:
# Coverage report is in coverage/ directory
Start-Process coverage/lcov-report/index.html
Linux:
# Coverage report is in coverage/ directory
xdg-open coverage/lcov-report/index.html
Coverage Thresholds:
- Branches: 70%
- Functions: 70%
- Lines: 70%
- Statements: 70%
Best Practices
1. Test Behavior, Not Implementation
❌ Bad:
expect(component.state.count).toBe(5);
✅ Good:
expect(screen.getByText('Count: 5')).toBeInTheDocument();
2. Use Descriptive Test Names
❌ Bad:
it('works', () => { ... });
✅ Good:
it('creates checkout session with correct price ID', () => { ... });
3. Arrange, Act, Assert
it('updates subscription status', async () => {
// Arrange
const userId = 'test-user';
const subscription = { status: 'active' };
// Act
await updateSubscription(userId, subscription);
// Assert
expect(mockFirestore.update).toHaveBeenCalledWith(...);
});
4. Clean Up After Tests
afterEach(() => {
jest.clearAllMocks();
cleanup();
});
Continuous Integration
Tests run automatically on:
- Push to
main
ordevelop
branches - Pull requests
Note: GitHub Actions CI/CD was removed in v2.2.1, but you can easily add it back by creating .github/workflows/ci.yml
.
Additional Resources
- Jest Documentation: https://jestjs.io/ (opens in a new tab)
- React Testing Library: https://testing-library.com/react (opens in a new tab)
- Playwright: https://playwright.dev/ (opens in a new tab)
- Testing Best Practices: https://kentcdodds.com/blog/common-mistakes-with-react-testing-library (opens in a new tab)
Your tests are ready! Run npm test
to start testing your application.