Skip to content

QA workflow

QA at this monorepo has two pillars: Linear tracks features / bugs / scenario libraries (this page), and Playwright + Bun Test run the automated checks (Running tests locally below).

Features, bugs, and QA test runs are tracked in Linear:

  • QA — prefix QA (e.g. QA-45) — holds the scenario library, rebuilt from scratch in Aug 2026 (the old RECQ team and its issues were deleted)
  • Product — prefix REC — planned but not yet created in the workspace
WhatWhere
Feature roadmap & statusLinear → Product team → Roadmap view (team not yet created)
BugsLinear → Product team → issues labeled bug (until it exists, file bugs in the QA team)
QA test scenarios (library + per-release)Linear → QA team → project QA — Pre-PRD Coverage Library
Per-feature acceptance testsLinear → Product team → the feature’s Project, labeled qa-acceptance (team not yet created)
Permanent shipped-features manifestFeatures (“implemented” section)
Architecture & planningArchitecture, Roadmap

One Linear issue = one user-flow checklist (5–12 steps). Use the QA team’s issue template:

**Surface:** web | mobile (user/agent app) | worker | shared
**Area:** auth | listings | leads | tours | search | ai | i18n | billing | chat | notifications | teams | engagement | profile | agents-directory | images | platform
**Platform cadence:** (native scenarios only) smoke → both iOS + Android every pass; otherwise one platform per pass, alternating
**Preconditions:** (e.g., logged-in agent with ≥1 published listing)
**Test data:** (specific accounts or fixtures)
## Steps
- [ ] 1. ...
- [ ] 2. ...
(5–12 total)
## Expected outcome
- ...
## Edge cases to also probe (light touch)
- ...
## Last run
- vX.Y — PASS/FAIL — YYYY-MM-DD — tester

If you need more than 12 steps, split into two scenarios. Always record the test-data identifier used so failures are reproducible.

One scenario covers both platforms of a native app: qa-smoke native scenarios run on both iOS and Android every pass; all other native scenarios run on one platform and alternate per pass, with “repeat on the other platform” as a standing light-touch edge. Each native issue’s **Platform cadence:** line states which rule applies.

LabelMeaning
qa-smokeMust pass before any prod deploy. Target ~20–25 scenarios (currently exactly 25).
qa-regressionSecondary coverage, run on demand.
qa-acceptanceFeature-launch acceptance (lives on the Product team, not QA).
qa-blockerCurrently failing → blocks next release.
Surfaceweb, mobile, worker, shared — native scenarios additionally carry mobile-user (ios-user + android/app-user) and/or mobile-agent (ios-agent + android/app-agent) for per-app run filtering
Area (one per scenario)auth, listings, leads, tours, search, ai, i18n, billing, chat, notifications, teams, engagement, profile, agents-directory, images, platform (rental exists but is dormant while Rental Companion is deferred)
  • Phase 1 — Pre-PRD launch (current): comprehensive. Run the Pre-PRD Coverage Library continuously as features land (rebuilt Aug 2026: QA-1QA-109 — 3 setup issues + 106 scenarios, 25 smoke).
  • Phase 2 — Post-PRD launch: duplicate the qa-smoke subset into a QA — Release vX.Y project per release. The regression library runs on demand (e.g., before a risky migration).

Every bug issue must include:

  1. Repro section — exact steps + environment + test account.
  2. A link to the failing QA scenario if one exists. If not, create one in the QA team before closing.
  3. A “Verified fixed” comment from a tester before the bug moves to Done.

A bug is not Done until the matching QA scenario passes again.

  1. In the Linear QA team, create an issue in the QA — Pre-PRD Coverage Library project using the template.
  2. Apply qa + surface + exactly one area label (native scenarios also get mobile-user and/or mobile-agent).
  3. Apply qa-smoke only if the scenario is critical-path (sign-up, publish listing, payment, etc.).
  4. Run it once against the current build; record the result in Last run.

A scenario earns qa-smoke after it catches a real regression in production. Scenarios that haven’t caught anything in N consecutive releases drop back to qa-regression.

This keeps the smoke set reflective of where production actually breaks, not where we thought it would.

The roster is provisioned through the real UI by the three SETUP issues at the top of the library (QA-1 account roster, QA-2 baseline listings, QA-3 team fixture) — there is no DB seeder. Email convention: plus-addressing on one controlled inbox (meouchi.jp+<handle>@gmail.com) so Resend OTPs are readable.

Account / fixturePurpose
qa-adminADMIN role — /dashboard/admin/* pages, Bull Board runs
qa-agent-smokePrimary agent (PREMIUM via admin grant, non-trial); owner of QA-L1…L6; LEAD of QA Realty
qa-agent-2 / qa-agent-3QA Realty MEMBER / team-ADMIN — invites, permissions, SLA escalation tiers
qa-agent-freeAGENT FREE, team-less — the FREE/upsell side of the plan gates + the native planGate envelope (the team-seats gate runs on QA Realty; the staging-quota/refund gate on qa-agent-smoke)
qa-customer-smoke / qa-customer-2Primary customer / second participant (qa-customer-2 runs in Spanish)
qa-homeownerDual-role with zero dashboard listings — the portal↔dashboard visibility-leak fixture
QA-L1…L6Baseline listings: single-unit · multi-unit · price-drop (backdated) · hidden-location · <80% DRAFT · RENT with full media
QA RealtyTeam fixture: SLA 30 min + 3-tier chain, branding, 3 members
Devices1× iOS 17+ and 1× Android API 26+ dev builds, push-capable
Full DB resetcd packages/database && bun run db:reset (see Conventions → Monorepo) — drop + rerun the Kysely migration chain, then flush Valkey

Record the exact ids (listing ids, team id) inside the SETUP issues once provisioned.

If the QA team passes >50 scenarios per release, or you have multiple parallel testers running the same suite, graduate the QA library to Qase (Linear-integrated test management). Until then, Linear is enough.

From apps/svelte-web/:

Terminal window
bun run test:e2e # equivalent: bun run test

Fixtures live in apps/svelte-web/e2e/. The runner reads three env vars — see Settings → Environment variables for the canonical list:

  • E2E_TEST_USER_EMAIL
  • E2E_TEST_USER_PASSWORD
  • PLAYWRIGHT_BASE_URL (defaults to http://localhost:5173)

The dev server must be reachable at PLAYWRIGHT_BASE_URL before the suite starts — either keep bun run dev running in a second terminal, or extend playwright.config.ts’s webServer block to boot it on demand.

From the repo root:

Terminal window
bun test # one-shot
bun test --watch # watch mode
bun test --coverage # with coverage

The repo-root package.json exposes these as test, test:watch, test:coverage scripts. Bun’s runner discovers *.test.ts files across the workspace automatically — no per-package configuration is needed.

CI runs unit tests across packages/, apps/api, apps/worker, and apps/svelte-web/src, but no e2e stage. One change-aware workflow selects the relevant quality, test, web-build, native-drift, Android, and iOS jobs for every PR into development and every development push; deploys are handled separately by Dokploy’s GitHub App. Playwright E2E is an author-side gate: run it locally before pushing.

WorkflowJobRuns on
ci.ymlquality, tests/invariants, web build, Core drift, Android/iOS matrices, final CI gatechange-selected PRs + development pushes
_ios-check.yml / _android-check.ymlreusable native build implementations called by ci.ymlonly affected apps
knock.ymlDevelopment sync and manual commit-specific promotionKnock changes / manual dispatch

See Deployment → CI/CD for the full pipeline shape. If a test job is added to the workflows later, surface it here and in the Deployment page.