diff --git a/CLAUDE.md b/CLAUDE.md index 3684a84..78319c6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -23,6 +23,7 @@ Without Docker (native stack: uvicorn `--reload` on :5000, Vite HMR on **:8020** ```bash src/dev/devenv.sh setup # backend venv (src/backend/.venv), npm ci for frontend + e2e, Mailpit binary into src/.devenv/bin src/dev/devenv.sh start # idempotent; waits until everything answers. Also: stop | restart | status | logs [service] | reset (wipes DB + uploads) +src/dev/devenv.sh seed # sample users (admin, alice, bob, carol @example.com), an open and a closed order; local only, idempotent cd src/frontend && npx tsc --noEmit # type checking (vite build does not run tsc) ``` diff --git a/src/dev/devenv.sh b/src/dev/devenv.sh index 418a8fc..ab9ac71 100755 --- a/src/dev/devenv.sh +++ b/src/dev/devenv.sh @@ -2,7 +2,7 @@ # Native dev stack (no Docker): backend (uvicorn --reload), frontend (Vite HMR, proxies /api), Mailpit. # App: http://localhost:8020 API: http://localhost:8020/api (or :5000 directly) Mailpit: http://localhost:8025 # -# Usage: src/dev/devenv.sh setup|start|stop|restart|status|logs [service]|reset +# Usage: src/dev/devenv.sh setup|start|stop|restart|status|logs [service]|reset|seed set -euo pipefail SRC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" @@ -135,6 +135,12 @@ cmd_reset() { if ((was_running)); then cmd_start; fi } +# Sample users/orders via the API (src/dev/seed.mjs); local stack only, idempotent. +cmd_seed() { + is_running backend || cmd_start + (cd "$E2E_DIR" && node "$SRC_DIR/dev/seed.mjs") +} + case "${1:-}" in setup) cmd_setup ;; start) cmd_start ;; @@ -143,5 +149,6 @@ case "${1:-}" in status) cmd_status ;; logs) cmd_logs "${2:-}" ;; reset) cmd_reset ;; - *) echo "Usage: $0 setup|start|stop|restart|status|logs [mailpit|backend|frontend]|reset" >&2; exit 2 ;; + seed) cmd_seed ;; + *) echo "Usage: $0 setup|start|stop|restart|status|logs [mailpit|backend|frontend]|reset|seed" >&2; exit 2 ;; esac diff --git a/src/dev/seed.mjs b/src/dev/seed.mjs new file mode 100644 index 0000000..155bf42 --- /dev/null +++ b/src/dev/seed.mjs @@ -0,0 +1,39 @@ +// Seeds the local dev stack with sample users, orders and submissions (run via `src/dev/devenv.sh seed`). +// Goes through the public API + Mailpit like a real user, so it only works against a stack with Mailpit, +// and refuses any BASE_URL that is not localhost. +import { BASE_URL, ADMIN_EMAIL, api, createOrder, signIn, submit } from "../e2e/lib.mjs"; + +if (!/^https?:\/\/(localhost|127\.0\.0\.1)(:|\/|$)/.test(BASE_URL)) { + console.error(`Refusing to seed ${BASE_URL}: dev seed data is for local stacks only.`); + process.exit(1); +} + +const SEED_TITLE = "Burger Friday"; + +const admin = await signIn(ADMIN_EMAIL); +const existing = await api("/api/orders/me?limit=100", { userId: admin.userId }); +if (existing.orders?.some((o) => o.title === SEED_TITLE)) { + console.log("Seed data already present, nothing to do."); + process.exit(0); +} + +const [alice, bob, carol] = await Promise.all(["alice", "bob", "carol"].map((n) => signIn(`${n}@example.com`))); + +// Open order with a mix of submission states +const open = await createOrder(admin.userId, { title: SEED_TITLE, description: "Order by **11:30**, pickup at noon." }); +const a = await submit(alice.userId, open.id, { burger: "Classic", sides: ["Fries"] }); +await submit(bob.userId, open.id, { burger: "Veggie", sides: ["Fries", "Side salad"] }); +await submit(carol.userId, open.id, { burger: "Cheeseburger" }); +await api(`/api/orders/${open.id}/admin/submissions/${a.id}/status`, { + userId: admin.userId, + method: "PUT", + body: { accepted: true, paid: true }, +}); + +// Closed order, owned by alice, where the admin participated +const closed = await createOrder(alice.userId, { title: "Pizza Wednesday", description: "Done." }); +await submit(admin.userId, closed.id, { burger: "Classic" }); +await submit(bob.userId, closed.id, { burger: "Veggie", sides: ["Side salad"] }); +await api(`/api/orders/${closed.id}/admin/status`, { userId: alice.userId, method: "PUT", body: { closed: true } }); + +console.log(`Seeded. Admin ${ADMIN_EMAIL}, users alice/bob/carol@example.com. Open ${BASE_URL}/order/${open.id}`);