Skip to main content

Documentation Index

Fetch the complete documentation index at: https://grantmaster.dev/llms.txt

Use this file to discover all available pages before exploring further.

E2E Test Playbook

GrantMaster uses Playwright for end-to-end testing. Our goal is not 100% coverage, but 100% reliability on the “Holy Trinity” of critical paths.

🏗️ Test Architecture Visual

🎯 The “Holy Trinity” of Critical Paths

If these three pass, the platform is considered “Safe for Production.”

1. The Membership Cycle

  • Path: Landing Page -> Sign Up -> Email Verification -> Tenant Creation.
  • Success Metric: A new user can reach the Dashboard in under 60 seconds.

2. The Grant Pursuit

  • Path: Search Grants -> Claim Grant -> Change Status to “In Progress” -> Add Effort.
  • Success Metric: Data persists across page refreshes and is assigned to the correct tenant.

3. The Upgrade Loop

  • Path: Pricing -> Select Tier -> Stripe Checkout (Success) -> Redirect -> Pro Features Unlocked.
  • Success Metric: The tenant.billing.currentTier updates in Firestore via webhook.

🛠️ Running Tests

Local Execution

npx playwright test

CI/CD Trigger

Tests run automatically on every Pull Request via the playwright.yml GitHub Action. A merge is blocked if any “Holy Trinity” test fails.

📝 Test Authoring Guidelines

1. Use Data Attributes

Never use CSS selectors or XPath. Use data-testid.
  • Bad: page.click('.btn-primary')
  • Good: page.click('[data-testid="grant-claim-button"]')

2. Mocking vs. Reality

  • Mock: Use playwright.route to mock external APIs (Stripe, Novu) to avoid cost and side effects.
  • Real: Always use a real Firebase Emulator for Firestore and Auth.

3. Clean Slate Principle

Every test must start with a clean tenant. Use the test.beforeEach hook to create a temporary test organization and user.

� Troubleshooting Failures

  1. Check Screenshots: Playwright saves failure screenshots to test-results/.
  2. View Trace: Open the trace viewer:
    npx playwright show-trace path/to/trace.zip
    
  3. Timing Issues: If a test is flaky, use locator.waitFor() instead of static page.waitForTimeout().