Stage 0

Make the App Testable

This is a one-time setup step. Copy the prompt below, paste it into Lovable, and let it audit your app and make the changes needed for reliable automated testing.

Prompt

Paste this into Lovable to prepare your app for testing

You are a senior developer preparing a Lovable app for automated testing. Your job is to audit the app and make the changes needed so that a browser automation tool can reliably navigate, interact with, and verify every feature. You are NOT running tests — you are making the app ready to be tested.

### Step 1: Audit the App

Read through all source files — components, pages, routes, auth config, API calls, and environment setup. Build a mental map of the app's architecture, then create a `testability-report.md` in the project root documenting your findings across the categories below.

### Step 2: Authentication Readiness

**Check what auth method the app uses.** This is the most critical item — if the test runner can't log in, most tests are dead on arrival.

| Auth Type | What To Do |
|-----------|-----------|
| **Email/password** | Good to go. No changes needed. Note the login route in the report. |
| **OAuth only** (Google, GitHub, etc.) | **Add an email/password login method.** This can be limited to a test/dev environment or behind a feature flag. Browser automation cannot complete third-party OAuth redirects. Without this, all authenticated tests will be blocked. |
| **Magic link / passwordless** | **Add a password-based login fallback** for test accounts. Magic links require inbox access which automation tools don't have. |
| **Invite-only registration** | Note this in the report. If you can programmatically create users via the auth provider's admin API, do so. Otherwise flag it for the user. |
| **No auth** | Note in report. Skip this section. |

**Implementation rules for adding email/password auth:**
- Wire it into the existing auth provider (Supabase, Firebase, etc.) — don't create a separate auth system.
- The login form should be on the same login page or accessible via a visible tab/toggle (e.g., "Sign in with email" tab alongside the OAuth buttons).
- Registration should work via the same email/password method so test accounts can be created.
- If you add a dev-only flag, use an environment variable like `VITE_ENABLE_TEST_AUTH=true` or equivalent and document it.
- Make sure the email/password flow goes through the same post-login redirect as OAuth so authenticated routes work identically.

### Step 2b: Create Test Accounts

Once email/password auth is available, create the test accounts yourself by using the app's registration flow or the auth provider's admin API. Do NOT leave this for the user.

Identify the roles the app supports by reading the codebase — look for role checks, permission guards, admin routes, and user type fields. Create one account per distinct role.

Use this naming convention for test accounts:

- **Email**: `lisa-test-{role}@test.com` (e.g., `lisa-test-user@test.com`, `lisa-test-admin@test.com`)
- **Password**: `LisaLoops-Test-2024!` (same password for all test accounts — it's strong enough and easy to reference)

**How to create them (in order of preference):**

1. **Via the app's registration page** — spin up a browser, navigate to the signup route, and register each account with the email/password above. This is preferred because it tests that registration actually works.
2. **Via the auth provider's admin API** — if the app uses Supabase, use the Supabase client's `auth.admin.createUser()`. For Firebase, use the Admin SDK. This is the fallback if registration requires email verification you can't complete.
3. **If neither works** — document what went wrong and flag it in the testability report as needing manual intervention.

After creating accounts, write `test-accounts.json` in the project root:

```json
{
  "auth_provider": "Supabase Auth",
  "login_route": "/login",
  "accounts_created_via": "registration page | admin API | manual",
  "accounts": [
    {
      "role": "user",
      "email": "lisa-test-user@test.com",
      "password": "LisaLoops-Test-2024!",
      "created": true,
      "notes": ""
    },
    {
      "role": "admin",
      "email": "lisa-test-admin@test.com",
      "password": "LisaLoops-Test-2024!",
      "created": true,
      "notes": "Admin role assigned via Supabase dashboard user metadata"
    }
  ]
}
```

**Rules for test account creation:**
- Only create accounts for roles that actually exist in the app. Don't invent roles.
- If a role requires manual assignment (e.g., flipping an `is_admin` flag in the database), do it if you have access. If not, document it.
- If the auth provider requires email confirmation and you can't auto-confirm, use the admin API to create pre-confirmed users.
- Set `"created": false` for any account you couldn't create, with a `"notes"` field explaining why.

### Step 3: Add `data-testid` Attributes

Add `data-testid` attributes to key interactive and verification elements throughout the app. This gives the test runner stable selectors that won't break when styling or text changes.

**Where to add them:**

- **Every button that triggers an action** — submit, save, delete, cancel, confirm, navigation buttons
  - Example: `<button data-testid="submit-form">Submit</button>`
- **Every form and its inputs** — the form container, each input, each error message area
  - Example: `<input data-testid="email-input" />`, `<span data-testid="email-error" />`
- **Navigation elements** — nav links, hamburger menu, sidebar items
  - Example: `<a data-testid="nav-dashboard">Dashboard</a>`
- **Data display containers** — tables, lists, cards that show dynamic content
  - Example: `<div data-testid="user-table">`, `<div data-testid="empty-state">`
- **Modals and dialogs** — the modal container, close button, confirm/cancel actions
  - Example: `<div data-testid="delete-modal">`, `<button data-testid="modal-confirm">`
- **Status indicators** — toasts, alerts, loading spinners, success/error messages
  - Example: `<div data-testid="toast-success">`, `<div data-testid="loading-spinner">`
- **Page-level containers** — a wrapper on each page/route for verifying navigation
  - Example: `<div data-testid="page-dashboard">`, `<div data-testid="page-settings">`

**Naming conventions:**
- Use kebab-case: `data-testid="submit-button"` not `data-testid="submitButton"`
- Be specific: `data-testid="delete-user-modal"` not `data-testid="modal"`
- For repeated items (list rows, cards), use a pattern: `data-testid="user-row-{id}"` or `data-testid="task-card-{index}"`
- Prefix page containers with `page-`: `data-testid="page-dashboard"`

### Step 4: Error Boundaries & Empty States

Check that the app handles edge cases gracefully rather than crashing or showing blank screens:

- **Empty states**: Every list, table, or data view should render something meaningful when there's no data. If a component just renders nothing when the array is empty, add an empty state message (e.g., "No items yet") with a `data-testid="empty-state"` attribute.
- **Error boundaries**: If the app uses React, check that there's at least a top-level error boundary. If there isn't one, add a basic one that catches render errors and shows a user-facing message instead of a white screen.
- **Loading states**: Async data fetches should show a loading indicator. If a component goes straight from nothing to rendered content with no intermediate state, add a loading state.

### Step 5: Route & Navigation Checks

- **Verify every route is defined** — check the router config and make sure there are no orphan pages or dead links in the nav.
- **Add a 404 / catch-all route** if one doesn't exist. It should render a clear "Page not found" message with `data-testid="page-not-found"`.
- **Check that deep-linking works** — each route should be directly accessible via URL, not only reachable by clicking through the app. If any route depends on in-memory state from a previous page, refactor it to read from URL params or a persistent store.

### Step 6: Console Error Cleanup

Open the app in a browser (or review the code) and identify any obvious sources of console errors:

- Missing environment variables that would cause API calls to fail
- Broken imports or missing dependencies
- Unhandled promise rejections in useEffect or data fetching hooks

Fix anything that would cause noise during testing. You don't need to achieve zero console output, but eliminate errors that would mask real test failures.

### Step 7: Output the Testability Report

Create `testability-report.md` in the project root with this structure:

```markdown
# Testability Report

> Generated by Lisa Loops Stage 0. This documents what was found and what was changed to make the app ready for automated testing.

## App Overview
- **App name**: 
- **Framework**: (React, Next.js, etc.)
- **Auth provider**: (Supabase, Firebase, Clerk, none, etc.)
- **Hosting/URL**: (Lovable preview URL, localhost, etc.)

## Authentication Status
- **Auth type detected**: (email_password / oauth_only / magic_link / none)
- **Changes made**: (describe what was added/changed, or "None needed")
- **Login route**: /login (or wherever)

## Test Accounts
- **Accounts created via**: (registration page / admin API / manual / not created)
- **Accounts file**: test-accounts.json in project root
- **Roles identified**: (list roles found in the app)
- **All accounts created successfully**: YES / NO
- **Manual steps needed**: (if any accounts couldn't be auto-created, describe what the user must do)

## data-testid Attributes Added
| Component/Page | Elements Tagged | Example |
|---------------|----------------|---------|
| Login page | email input, password input, submit button | `data-testid="login-submit"` |
| Dashboard | user table, empty state, add button | `data-testid="user-table"` |
| ... | ... | ... |

## Error Boundaries & Empty States
- **Error boundary**: (added / already existed / not applicable)
- **Empty states fixed**: (list which components got empty state treatment)
- **Loading states added**: (list which components)

## Route Health
- **Total routes**: X
- **404 handler**: (added / already existed)
- **Deep-link issues found**: (list any, or "None")

## Console Errors Fixed
- (list each fix, or "None found")

## Known Limitations
- (anything the test runner should be aware of — e.g., "third-party map widget won't be testable", "PDF export opens a new tab")

## Ready for Testing: YES / NO
_(If NO, explain what still needs manual intervention — e.g., "User must assign admin role manually in database")_
```

### Rules

- **Do NOT write or run any tests.** Your only job is to make the app testable.
- **Do NOT change application behavior or features.** Adding a test-id attribute is fine. Changing how a form validates is not (unless it's clearly broken).
- **Do NOT delete or restructure existing code.** Add to it. The auth additions should sit alongside existing auth, not replace it.
- **Be conservative.** If you're unsure whether a change is safe, document it in the report as a recommendation rather than making it.
- **Every change you make should be documented** in the testability report so the user can review what was modified.

After running — review these:

testability-report.mdReview the full audit — auth status, selectors added, routes checked, errors fixed.
test-accounts.jsonVerify test accounts were created successfully for each role in your app.
Auth changesIf your app was OAuth-only, verify the new email/password login works alongside existing auth.
data-testid attributesSpot-check a few components to confirm test IDs were added to key elements.
Error boundariesVerify the app still renders correctly — no regressions from added error boundaries or empty states.
404 routeNavigate to a nonexistent URL and confirm the catch-all page renders.

💡 Stage 0 doesn't write or run tests — it only makes the app ready. Proceed to Stage 1 when satisfied.