test: Add E2E test framework with Playwright
feat: Basic Homepage elements
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# Session Handoff: Auth Tests + Backend Ansible Plan
|
||||
**Date:** 2026-04-12
|
||||
**Session Focus:** Fix broken auth unit tests; plan bab-backend-ansible rewrite; update EE dependencies
|
||||
|
||||
## What Was Accomplished
|
||||
|
||||
1. **Deleted `tests/unit/auth-callback.test.ts`** — low-value component test per agreed test strategy; E2E covers this
|
||||
2. **Extracted pure auth logic** → `app/utils/auth.ts` (`checkAuthRedirect(userValue, path): string | null`)
|
||||
3. **Simplified `app/middleware/auth.ts`** — delegates to `checkAuthRedirect`; Nuxt-specific code is now minimal
|
||||
4. **Rewrote `tests/unit/auth-middleware.test.ts`** — tests `checkAuthRedirect` directly, no mocking, node env; **7/7 passing**
|
||||
5. **Documented Nuxt testing lessons** → memory `feedback_nuxt_testing.md`
|
||||
6. **Wrote backend rewrite plan** → `docs/summaries/plan-bab-backend-ansible-rewrite.md`
|
||||
7. **Updated `ee-demo` EE** with: `amazon.aws` collection, `boto3`/`botocore`, `postgresql` RPM, `supabase` CLI install via `SUPABASE_VERSION` build arg; updated `build.sh` (user also added `--redhat` flag)
|
||||
8. **Resolved all plan open questions** except one (see below)
|
||||
|
||||
## Exact State of Work in Progress
|
||||
|
||||
- `tests/integration/auth-session.test.ts` — written last session, not yet run (requires local Supabase + `SUPABASE_SERVICE_ROLE_KEY`)
|
||||
- Playwright E2E — not yet set up; `tests/e2e/` directory does not exist
|
||||
- `.gitea/workflows/build.yaml` — not yet created
|
||||
|
||||
## Key Technical Decisions This Session
|
||||
|
||||
- **Extract-don't-mock pattern**: Nuxt auto-imports compile to concrete dist paths; `vi.mock('#imports')` doesn't intercept them. Pattern: extract logic to `app/utils/` with no Nuxt deps, test directly. CONFIRMED.
|
||||
- **Skip unit tests for simple page components**: Ionic component registration + Supabase init failures make `mountSuspended` too brittle. Cover with Playwright E2E instead. CONFIRMED.
|
||||
|
||||
## Files Created or Modified
|
||||
|
||||
| File Path | Action | Description |
|
||||
|-----------|--------|-------------|
|
||||
| `app/utils/auth.ts` | Created | `checkAuthRedirect` pure function; `PUBLIC_ROUTES` constant |
|
||||
| `app/middleware/auth.ts` | Modified | Now delegates to `checkAuthRedirect` |
|
||||
| `tests/unit/auth-middleware.test.ts` | Rewritten | Tests pure function; 7/7 passing |
|
||||
| `tests/unit/auth-callback.test.ts` | Deleted | Low-value component test |
|
||||
| `docs/summaries/plan-bab-backend-ansible-rewrite.md` | Created | Full rewrite plan with implementation sequence |
|
||||
| `docs/context/sdlc-architecture.md` | Updated | Dev URL, nginx webroot, Gitea URL, artifact token path |
|
||||
| `/home/ptoal/Dev/ExecutionEnvironments/ee-demo/execution-environment.yml` | Modified | Added `postgresql` RPM, `supabase` CLI build step |
|
||||
| `/home/ptoal/Dev/ExecutionEnvironments/ee-demo/requirements.yml` | Modified | Added `amazon.aws >= 9.0.0` |
|
||||
| `/home/ptoal/Dev/ExecutionEnvironments/ee-demo/requirements.txt` | Modified | Added `boto3`, `botocore` |
|
||||
| `/home/ptoal/Dev/ExecutionEnvironments/ee-demo/build.sh` | Modified | Added `SUPABASE_VERSION` guard; user added `--redhat` flag |
|
||||
|
||||
## What the NEXT Session Should Do
|
||||
|
||||
**If continuing oysqn.app frontend:**
|
||||
1. Set up Playwright — `yarn add -D @playwright/test`, create `tests/e2e/`, write login flow E2E test
|
||||
2. Create `.gitea/workflows/build.yaml` following bab-app pattern (semantic-release + artifact)
|
||||
|
||||
**If starting bab-backend-ansible rewrite:**
|
||||
1. Read `docs/summaries/plan-bab-backend-ansible-rewrite.md` — full scope and implementation sequence
|
||||
2. Start with step 3: `sync_gitea_secrets.yml` (lowest risk, standalone)
|
||||
3. Note: work in `/home/ptoal/Dev/Projects/bab-backend-ansible`, not oysqn.app
|
||||
|
||||
## Open Questions Requiring User Input
|
||||
|
||||
- [ ] **`kv/oys/dev/supabase/postgres_url`** — not in Vault; needed before `migrate_supabase.yml` can run rollback SQL via `psql` against dev. Add to Vault before first dev migration run.
|
||||
|
||||
## Confirmed Infrastructure Values
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Dev URL | `https://bab.toal.ca` |
|
||||
| nginx webroot (bab1) | `/usr/share/nginx/html/` |
|
||||
| Gitea URL | `https://gitea.toal.ca/` |
|
||||
| Gitea artifact token | `kv/oys/bab_gitea` |
|
||||
| Backup path (bab1) | `/var/backups/oysqn/` (assumed — confirm before first prod backup) |
|
||||
|
||||
## Files to Load Next Session
|
||||
|
||||
- **Frontend session:** `docs/summaries/handoff-2026-04-12-splash-and-login.md` (prior UI work context)
|
||||
- **Backend session:** `docs/summaries/plan-bab-backend-ansible-rewrite.md`; `docs/context/sdlc-architecture.md`
|
||||
@@ -1,78 +0,0 @@
|
||||
# Session Handoff: Splash Page & Magic Link Login
|
||||
**Date:** 2026-04-12
|
||||
**Session Duration:** ~30 minutes
|
||||
**Session Focus:** Implement unauthenticated splash page with logo and login button; implement magic link login page
|
||||
**Context Usage at Handoff:** Low
|
||||
|
||||
## What Was Accomplished
|
||||
|
||||
1. **Splash page implemented** → `app/pages/index.vue` — unauthenticated users see centered logo + "Log In" button; authenticated users see home content with header/menu
|
||||
2. **Login page implemented** → `app/pages/login.vue` — email input, sends magic link via `auth.sendMagicLink()`, shows confirmation state with mail icon after send
|
||||
3. **Auth middleware updated** → `app/middleware/auth.ts` — added `/` to public routes; unauthenticated users redirected to `/` (not `/login`)
|
||||
4. **Supabase redirect config updated** → `nuxt.config.ts` — `login` redirect changed from `/login` to `/`; `/` added to `exclude` list
|
||||
|
||||
## Exact State of Work in Progress
|
||||
|
||||
- Splash + login pages coded but not yet tested end-to-end against local Supabase
|
||||
- `auth/callback.vue` still a skeleton — magic link redirect will land there; not yet implemented
|
||||
|
||||
## Decisions Made This Session
|
||||
|
||||
- USE `/` as the unauthenticated landing route INSTEAD OF `/login` BECAUSE the splash/logo page IS the unauthenticated entry point; `/login` is a detail page reached from it — STATUS: confirmed
|
||||
- MAGIC LINK ONLY on login page (not OTP) BECAUSE user stated "sends a magic link" — STATUS: confirmed; OTP flow (`sendOtp` + `verifyOtp`) exists in auth store but unused by login page
|
||||
|
||||
## Key Numbers Generated or Discovered This Session
|
||||
|
||||
- Logo file: `public/oysqn_logo.png` (confirmed present)
|
||||
- Max logo display width: 280px (CSS)
|
||||
- Max login form width: 400px (CSS)
|
||||
|
||||
## Files Created or Modified
|
||||
|
||||
| File Path | Action | Description |
|
||||
|-----------|--------|-------------|
|
||||
| `app/pages/index.vue` | Modified | Splash (unauthenticated) + home (authenticated) in single page, toggled by `useSupabaseUser()` |
|
||||
| `app/pages/login.vue` | Modified | Email input → `sendMagicLink()` → confirmation state; uses `IonBackButton` to return to splash |
|
||||
| `app/middleware/auth.ts` | Modified | Added `/` to public routes; redirects unauthenticated to `/` |
|
||||
| `nuxt.config.ts` | Modified | `supabase.redirectOptions.login` = `/`; added `/` to `exclude` |
|
||||
|
||||
## What the NEXT Session Should Do
|
||||
|
||||
1. **First**: Test the auth flow end-to-end: load app → confirm splash shows logo + Login button → tap Login → enter email → check Mailpit (http://127.0.0.1:54324) for magic link → click link → confirm redirect to `/auth/callback` → confirm redirect to `/` (home state)
|
||||
2. **Then**: Implement `app/pages/auth/callback.vue` — handle magic link redirect (Supabase sets session from URL hash; page should show a spinner, then navigate to `/`)
|
||||
3. **Then**: Verify `useAuthStore` is auto-imported by Pinia Nuxt module (currently explicitly imported in `login.vue` with `import { useAuthStore } from '~/stores/auth'` — check if explicit import is still needed or if auto-import covers it)
|
||||
4. **Then**: Run `npx supabase gen types typescript --local > app/types/supabase.ts` to replace placeholder types
|
||||
5. **Then**: Implement `app/pages/index.vue` home content (authenticated state) — boat list or welcome state
|
||||
|
||||
## Open Questions Requiring User Input
|
||||
|
||||
- [ ] Should the login page also support OTP (enter token from email) as a fallback, or magic link only? — `sendOtp` + `verifyOtp` exist in auth store but unused — impacts login page UI
|
||||
- [ ] Should `auth/callback.vue` redirect to a specific page after login (e.g., boats list) or always to `/`? — impacts callback implementation
|
||||
|
||||
## Assumptions That Need Validation
|
||||
|
||||
- ASSUMED: `@nuxtjs/ionic` + `@pinia/nuxt` auto-imports `useAuthStore` — currently explicitly imported; validate by removing explicit import and testing
|
||||
- ASSUMED: `sendMagicLink()` in auth store correctly sets `emailRedirectTo` to `/auth/callback` — validate by clicking the email link and checking where it lands
|
||||
- ASSUMED: `IonRouterOutlet` handles `router-link` on `IonButton` correctly — validate by tapping Login button in browser
|
||||
|
||||
## Files to Load Next Session
|
||||
|
||||
- `app/pages/auth/callback.vue` — primary implementation target
|
||||
- `app/pages/index.vue` — may need home content (authenticated state) built out
|
||||
- `app/stores/auth.ts` — reference for `sendMagicLink` signature and redirect URL
|
||||
|
||||
## Dev Environment Reference
|
||||
|
||||
```
|
||||
# Start local Supabase (if not running):
|
||||
DOCKER_HOST=unix:///run/user/1000/podman/podman.sock npx supabase start
|
||||
|
||||
# Start app:
|
||||
yarn dev
|
||||
|
||||
# Mailpit (view magic link emails):
|
||||
http://127.0.0.1:54324
|
||||
|
||||
# Supabase Studio:
|
||||
http://127.0.0.1:54323
|
||||
```
|
||||
66
docs/summaries/handoff-2026-04-19-playwright-e2e-setup.md
Normal file
66
docs/summaries/handoff-2026-04-19-playwright-e2e-setup.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# Session Handoff: Playwright E2E Setup
|
||||
**Date:** 2026-04-19
|
||||
**Session Focus:** Set up Playwright E2E testing; write and pass auth flow tests
|
||||
|
||||
## What Was Accomplished
|
||||
|
||||
1. **Installed `@playwright/test` 1.59.1** + Chromium headless shell binary
|
||||
2. **Created `playwright.config.ts`** — Pixel 5 viewport, `reuseExistingServer` for local dev, `github` reporter in CI, 30s timeout, 1 worker (serial)
|
||||
3. **Created `tests/e2e/helpers/mailpit.ts`** — `deleteAllMail()` and `getMagicLink(email)` against Mailpit at `http://127.0.0.1:54324`
|
||||
4. **Created `tests/e2e/auth.spec.ts`** — 2 tests: full magic link flow + protected route redirect
|
||||
5. **Fixed `supabase/config.toml`** — `site_url` changed from `http://127.0.0.1:3000` to `http://localhost:3000`; `additional_redirect_urls` updated to include `http://localhost:3000/auth/callback` and `http://127.0.0.1:3000/auth/callback`
|
||||
6. **Added scripts to `package.json`**: `test:e2e`, `test:e2e:ui`, `test:e2e:headed`
|
||||
7. **Both tests pass: 2/2**
|
||||
|
||||
## Key Debugging Discoveries
|
||||
|
||||
| Problem | Root Cause | Fix |
|
||||
|---------|-----------|-----|
|
||||
| `getByRole('button', { name: 'Log In' })` not found | `IonButton` with `router-link` renders as `<a>` (role=`link`) | Changed to `getByRole('link', { name: 'Log In' })` |
|
||||
| `getByLabel('Email address')` not found | `IonLabel` is not associated via `for`/`id` with `IonInput` | Changed to `getByPlaceholder('you@example.com')` |
|
||||
| `page.goto(magicLink)` → `ERR_CONNECTION_REFUSED` to `127.0.0.1:54321` | Playwright's Chromium headless shell cannot reach Supabase local auth server directly | Use Node.js `fetch(magicLink, { redirect: 'manual' })` to follow redirect server-side; navigate browser to the resulting app callback URL |
|
||||
| Callback URL was `/?code=` instead of `/auth/callback?code=` | `emailRedirectTo` not whitelisted in `supabase/config.toml`; Supabase fell back to `site_url` | Fixed `config.toml` redirect URLs; required `supabase stop && supabase start` |
|
||||
|
||||
## Ionic-Specific Playwright Patterns (confirmed working)
|
||||
|
||||
- `IonButton` with `router-link` → use `getByRole('link', { name: '...' })`
|
||||
- `IonButton` without `router-link` → use `getByRole('button', { name: '...' })`
|
||||
- `IonInput` → use `getByPlaceholder(...)` (label association not standard HTML)
|
||||
- Never navigate browser directly to Supabase local auth URL — follow redirect server-side first
|
||||
|
||||
## Files Created or Modified
|
||||
|
||||
| File | Action |
|
||||
|------|--------|
|
||||
| `playwright.config.ts` | Created |
|
||||
| `tests/e2e/helpers/mailpit.ts` | Created |
|
||||
| `tests/e2e/auth.spec.ts` | Created |
|
||||
| `supabase/config.toml` | Modified — site_url and redirect URLs |
|
||||
| `package.json` | Modified — added test:e2e scripts |
|
||||
|
||||
## What the NEXT Session Should Do
|
||||
|
||||
**Option A — CI pipeline:**
|
||||
1. Create `.gitea/workflows/build.yaml` — unit tests + build + E2E (read bab-app pipeline as reference)
|
||||
2. Note: E2E in CI requires local Supabase running in the pipeline — confirm if feasible or skip E2E in CI for now
|
||||
|
||||
**Option B — Home page content:**
|
||||
1. Implement authenticated home content in `app/pages/index.vue` (currently "Welcome to OYS Borrow a Boat" placeholder)
|
||||
2. Likely a boat list or dashboard — check `docs/planning/` for persona requirements
|
||||
|
||||
## Open Questions
|
||||
|
||||
- [ ] Should E2E tests run in CI (requires Supabase in pipeline) or local-only? — OPEN
|
||||
- [ ] What is the authenticated home content? Boat list, dashboard, or something else? — check planning docs
|
||||
|
||||
## Dev Environment Reference
|
||||
|
||||
```bash
|
||||
# Required before running E2E:
|
||||
DOCKER_HOST=unix:///run/user/1000/podman/podman.sock npx supabase start
|
||||
|
||||
# Run E2E:
|
||||
yarn test:e2e # headless
|
||||
yarn test:e2e:headed # visible browser
|
||||
yarn test:e2e:ui # Playwright UI mode
|
||||
```
|
||||
Reference in New Issue
Block a user