> For the complete documentation index, see [llms.txt](https://klassdocs.gitbook.io/klassapp-documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://klassdocs.gitbook.io/klassapp-documentation/e2e/onboarding.md).

# E2E onboarding suite (staging only)

Six journeys: **3 school types × 2 modes** (manual wizard, Toshi-assisted), each starting from the public sign-up page and ending on the new school's admin dashboard, fully set up.

**School types**

| id        | type                  | category          | classes created                                          |
| --------- | --------------------- | ----------------- | -------------------------------------------------------- |
| `primary` | Nursery & Primary     | `primary_nursery` | Baby/Middle/Top + Primary One–Seven                      |
| `olevel`  | Secondary O-Level     | `o_level`         | Senior One–Four                                          |
| `oalevel` | Secondary O & A-Level | `o_a_level`       | Senior One–Six (streams used for combinations, e.g. PCM) |

**Journey ids (for `--journey=`)**: `primary-manual`, `primary-toshi`, `olevel-manual`, `olevel-toshi`, `oalevel-manual`, `oalevel-toshi`

## Commands

```bash
# Play one journey slowly in a visible browser (headed, slowMo):
npm run e2e:onboarding -- --headed --journey=primary-manual

# Playwright UI mode — pick a journey, step through it, watch each click:
npm run e2e:onboarding -- --ui

# Full run: all 6 journeys × both widths (1280 desktop + 375 mobile):
npm run e2e:onboarding

# Final gate: those six plus the MVP journey, both widths (14 runs), from a
# worktree pinned to a commit. Purges this run's throwaway schools afterwards
# (dry run first). --dry-run prints the 14 runs and does not open a browser.
node e2e/onboarding/final-gate.mjs --pin "$(git rev-parse --short=12 HEAD)" --dry-run
node e2e/onboarding/final-gate.mjs --pin "$(git rev-parse --short=12 HEAD)"

# One journey, one width:
npm run e2e:onboarding -- --journey=oalevel-toshi --project=desktop-1280

# Open the HTML report after a run:
npx playwright show-report e2e/onboarding/report
```

Every run records **video, per-step screenshots and a trace** (Playwright defaults in this config). Artifacts (per journey): `e2e/onboarding/artifacts/<journey>-<stamp>/` — `summary.json`, `conversation.md` (Toshi), `health.json`, `outcomes.json`.

## Safety rules baked in

* **Passwords come from the environment.** Set `E2E_ACCOUNT_PASSWORD` before a journey run. Demo Junior logins are not hard-coded in this suite. The role crawl reads `DEMO_JUNIOR_ADMIN_EMAIL`, `DEMO_JUNIOR_ADMIN_PASSWORD`, `DEMO_JUNIOR_EMAIL_DOMAIN`, and `ROLE_CRAWL_PASSWORD`.
* **Staging only.** The config hard-guards the base URL to the staging host (see the private repo KlassApp-Foundation/internal or the Cloud dashboard); anything else aborts before a single test runs.
* **No real people contacted.** Test accounts use `example.com` emails and non-real `070…` phone numbers. Staging's mail driver is `log` (no mail leaves the app). Email OTP is read from Cloud runtime logs (`klassapp.email_verification_code` marker), with Commands re-issue as fallback — **never** by pre-setting `email_verified`. WhatsApp verification codes are produced **in-UI** by design.
* **Nightwatch note:** staging `LOG_STACK` includes `nightwatch`; agent logs show `Ingest failed: No authentication details` / `403 Exceeded quota`. That is Nightwatch APM ingest, not Laravel Cloud API auth. OTP sandbox uses `laravel-cloud-socket` + the structured marker above. Rasta: fix Nightwatch quota/token or drop `nightwatch` from staging `LOG_STACK` if those errors should stop.
* **Test data is marked.** Every school is named `E2E <type> <mode> <date>` and flagged `is_test`; the suite can purge its own schools (see below).
* The only direct DB access is a small staging bridge (`lib/stg_bridge.py`, Node wrapper `lib/stg-bridge.js`). It runs tinker snippets and reads the Cloud log stream against the **staging** environment, and refuses any other environment id. The token comes from the Cloud API token named in the private repo KlassApp-Foundation/internal or the Cloud dashboard. There is no SSH path.

## Cleaning up E2E schools

```bash
# On staging (via the bridge or the Cloud console):
php artisan test:purge-schools --school=<id>            # dry run, prints inventory
php artisan test:purge-schools --school=<id> --force    # delete
```

Refuses schools that are not `is_test=1` or not named `E2E …`.

## Layout

```
e2e/onboarding/
  playwright.config.js   # staging guard, 2 viewports, video/trace/report
  run.mjs                # command launcher (--journey / --headed / --ui / passthrough)
  lib/                   # signup battery, wizard driver, toshi driver, outcomes, health, bridge
  journeys/              # manual.spec.js + toshi.spec.js (tagged @<journey-id>)
  artifacts/             # per-run output (gitignored)
  report/                # HTML report (gitignored)
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://klassdocs.gitbook.io/klassapp-documentation/e2e/onboarding.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
