diff --git a/CLAUDE.md b/CLAUDE.md index 5d54c93..f7d200d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,9 +12,12 @@ Luncher is a lunch management app for teams — daily restaurant menus, food ord types/ → Shared OpenAPI-generated TypeScript types (source of truth: types/api.yml) server/ → Express 5 backend (Node.js 22, ts-node) client/ → React 19 frontend (Vite 7, React Bootstrap) +e2e/ → Playwright E2E tests (separate package) ``` -Each directory has its own `package.json` and `tsconfig.json`. Package manager: **Yarn Classic**. +Each of the four directories has its own `package.json`. Package manager: **Yarn Classic**. + +Deployment files at repo root: `Dockerfile`, `Dockerfile-Woodpecker`, `compose.yml`, `compose-traefik.yml`. ## Development Commands @@ -23,6 +26,7 @@ Each directory has its own `package.json` and `tsconfig.json`. Package manager: cd types && yarn install && yarn openapi-ts # Generate API types first cd ../server && yarn install cd ../client && yarn install +cd ../e2e && yarn install ``` ### Running dev environment @@ -44,11 +48,30 @@ cd client && yarn build # tsc --noEmit + vite build → client/dist ### Tests ```bash -cd server && yarn test # Jest (tests in server/src/tests/) -cd server && yarn test dates # Run one test file -cd server && yarn test -t "name" # Run by test name pattern +# Server unit tests (Jest) +cd server && yarn test # All tests in server/src/tests/ +cd server && yarn test dates # Run one file by name +cd server && yarn test -t "name" # Run by test name pattern + +# E2E (Playwright) — requires prebuilt server +cd server && yarn build +cd e2e && yarn test # chromium + firefox, baseURL 127.0.0.1:3001 +cd e2e && yarn test:ui # interactive UI mode +cd e2e && yarn report # open last HTML report ``` +Jest setup (`server/src/tests/setupEnv.ts`) forces `STORAGE=memory`, deletes `MOCK_DATA`, and sets a fixed `JWT_SECRET`. Playwright auto-starts the prebuilt server and authenticates via the `remote-user: e2e-user` trusted-header path; locally uses `STORAGE=json` + `MOCK_DATA=true`, CI uses `STORAGE=redis`. + +### CI pipeline +Gitea Actions — `.gitea/workflows/ci.yaml` (no `.github/` equivalent): + +1. `generate-types` — runs `yarn openapi-ts`, uploads artifact +2. `server-test` — Jest +3. `server-build` + `client-build` — parallel tsc/vite builds +4. `e2e` — Playwright in `mcr.microsoft.com/playwright:v1.59.1-jammy` with a Redis service container; only Firefox installed in CI +5. `docker-build` — master branch only, uses `Dockerfile-Woodpecker` +6. `notify` — Discord + ntfy webhooks + ### Formatting Prettier is installed in `client/` (devDependency only, no script or config) — invoke via `yarn prettier ` with defaults. @@ -63,10 +86,11 @@ Prettier is installed in `client/` (devDependency only, no script or config) — ### Server (server/src/) - **Entry:** `index.ts` — Express app + Socket.io setup -- **Routes:** `routes/` — modular Express route handlers (food, pizzaDay, voting, notifications, qr, stats, easterEgg, dev) +- **Routes:** `routes/` — 9 modular Express route handlers (food, pizzaDay, voting, notifications, qr, stats, easterEgg, dev, changelog) - **Services:** domain logic files at root level (`service.ts`, `pizza.ts`, `restaurants.ts`, `chefie.ts`, `voting.ts`, `stats.ts`, `qr.ts`, `notifikace.ts`) +- **Helpers:** `mock.ts` (fake menu data for `MOCK_DATA=true`), `pushReminder.ts` (push notification reminders), `utils.ts` (shared utilities) - **Auth:** `auth.ts` — JWT + optional trusted-header authentication -- **Storage:** `storage/StorageInterface.ts` defines the interface; implementations in `storage/json.ts` (file-based, dev) and `storage/redis.ts` (production). Data keyed by date (YYYY-MM-DD). +- **Storage:** `storage/index.ts` factory selects implementation; backends: `json.ts` (file-based, dev), `redis.ts` (production), `memory.ts` (tests). Data keyed by date (YYYY-MM-DD). - **Restaurant scrapers:** Cheerio-based HTML parsing for daily menus from multiple restaurants - **Pizza Chefie integration:** `chefie.ts` scrapes pizzachefie.cz for Pizza day menus and salads (only active when a Pizza day is open) - **WebSocket:** `websocket.ts` — Socket.io for real-time client updates @@ -74,10 +98,12 @@ Prettier is installed in `client/` (devDependency only, no script or config) — - **Config:** `.env.development` / `.env.production` (see `.env.template` for all options) ### Client (client/src/) -- **Entry:** `index.tsx` → `App.tsx` → `AppRoutes.tsx` +- **Entry:** `index.tsx` → `App.tsx` → `AppRoutes.tsx`; `Login.tsx` is the auth screen; `FallingLeaves.tsx` is a seasonal visual effect - **Pages:** `pages/` (StatsPage) -- **Components:** `components/` (Header, Footer, Loader, modals/, PizzaOrderList, PizzaOrderRow) -- **Context providers:** `context/` — AuthContext, SettingsContext, SocketContext, EasterEggContext +- **Components:** `components/` (Header, Footer, Loader, PizzaOrderList, PizzaOrderRow, and modals in `components/modals/`) +- **Context providers:** `context/` — `auth.tsx`, `settings.tsx`, `socket.js`, `eggs.tsx` (note: `socket.js` is the only non-TSX context file) +- **Hooks:** `hooks/` (`usePushReminder.ts`) +- **Utils:** `utils/` (`parsePrice.ts`) - **Styling:** Bootstrap 5 + React Bootstrap + custom SCSS files (co-located with components) - **API calls:** use OpenAPI-generated SDK from `types/gen/` - **Routing:** React Router DOM v7 @@ -91,7 +117,7 @@ Prettier is installed in `client/` (devDependency only, no script or config) — ## Environment - **Server env files:** `server/.env.development`, `server/.env.production` (see `server/.env.template`) -- Key vars: `JWT_SECRET`, `STORAGE` (json/redis), `MOCK_DATA`, `REDIS_HOST`, `REDIS_PORT` +- Key vars: `JWT_SECRET`, `STORAGE` (json/redis/memory), `MOCK_DATA`, `REDIS_HOST`, `REDIS_PORT` - **Docker:** multi-stage Dockerfile, `compose.yml` for app + Redis. Timezone: Europe/Prague. ## Conventions @@ -99,4 +125,4 @@ Prettier is installed in `client/` (devDependency only, no script or config) — - Czech naming for domain variables and UI strings; English for infrastructure code - TypeScript strict mode in both client and server - Server module resolution: Node16; Client: ESNext/bundler -- `TODO.md` tracks open bugs and roadmap items — worth scanning before starting non-trivial work \ No newline at end of file +- `TODO.md` tracks open bugs and roadmap items — worth scanning before starting non-trivial work