Build and Push Lunchtime Images (Kaniko) / build-and-push (push) Successful in 1m44s
My Orders: year calendar and lunch profile first, chips and "How you compare" removed, open and paid payments merged into one table (open first, then newest). Activity is now a line chart with a cumulative switch and finer buckets (daily up to ~3 months, weekly up to ~13). Cards get subtle elevation and tighter spacing. Responsive: phone tab strip instead of the side menu, heatmap fits narrow screens, grouped column-chart labels are truncated, the manager weekday table scrolls instead of overflowing. Tooling: viewports.mjs (presets, overflow detector), shoot.mjs --sizes and --select, tests/responsive.ui.spec.ts, docs/ui-testing.md. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
4.4 KiB
4.4 KiB
UI checks: does it look right on phones and desktops?
Tools live in src/e2e/. They need the dev stack (src/dev/devenv.sh start, app on :8020).
| Tool | What it is for |
|---|---|
viewports.mjs |
Shared presets (iphone-se 375x667, android-small 360x740, iphone-14 390x844, pixel-7 412x915, ipad 768x1024, laptop 1280x800, desktop 1440x900, fhd 1920x1080), groups and findHorizontalOverflow(page) |
shoot.mjs |
Screenshots in any viewport, reports console errors, failed requests and horizontal overflow (exit code 1) |
tests/responsive.ui.spec.ts |
Regression test: no page overflows its viewport (home, create, three stats pages, order, order admin) |
The process after any layout change
- Typecheck:
cd src/frontend && npx tsc --noEmit. - Automatic overflow check, all sizes, for the pages you touched (needs a user with data,
--as=adminhas the most):Anycd src/e2e node shoot.mjs /stats/orderee /stats/manager /stats/admin --as=admin --sizes=all # light node shoot.mjs /stats/orderee /stats/manager /stats/admin --as=admin --sizes=all --dark # darkWARN OVERFLOW <size> <path>: ... offendersline is a bug: the page scrolls sideways on that device. The offenders are the elements that stick out. Fix: wrap tables inscroll={{ x: true }}, give flex childrenminWidth: 0, useminmax(min(Npx, 100%), 1fr)in grids. - Look at it. Overflow is only one kind of bug. Shoot the extremes and read the PNGs:
node shoot.mjs /stats/orderee --as=admin --sizes=iphone-se,android-small,fhd --full- Smallest phone (360 / 375): truncated or overlapping labels, tall single-column stacks, controls wrapping ("Stat us"), things that need sideways scrolling without a hint.
- Tablet (768): where the layout switches; the awkward in-between.
- Widest desktop (1920): content stays centred and readable, nothing stretched.
- Dark mode on at least one phone and one desktop size.
- Zoom on a single widget instead of reading a 14000px full-page shot:
node shoot.mjs /stats/manager --as=admin --sizes=android-small,desktop --select='.ant-card:has-text("Participants per order")' - Run the regression spec (
check= iphone-se, pixel-7, ipad, desktop;RESPONSIVE_SIZES=allfor all eight):Many parallel page loads can be slow on the Vite dev server; if you see timeouts addnpx playwright test --project=ui responsive RESPONSIVE_SIZES=all npx playwright test --project=ui responsive--workers=2.
Getting data worth looking at
A fresh user has no data and shows only the empty state. Options:
--as=adminin the dev stack usually has history.--seedor{order}/{admin}in the path create an order with two submissions.- The API can only create things "now". For charts over time, backdate rows directly in
src/backend/data/burger_orders.db(submissions.created_at,accepted,paid). Remember the original values and restore them afterwards.
Gotchas
--sizestakes preset names, groups (phones,tablets,desktops,check,all) orWxH. A name is never both a group and a preset.--mobilestill means the Pixel 7 preset;--sizessupersedes it.findHorizontalOverflowignores elements inside an intentional scroller (overflow-x: auto|scroll|hidden|clip) and fixed overlays, so heatmaps that scroll on purpose are not reported. That also means a clipped-but-unhinted scroller is not caught: look at the screenshots.- A pre-existing React warning (
useFormnot connected to a Form) appears once per page load in every shoot; it is not caused by the stats pages. - In this repo's shell,
grepis a wrapper that honours.gitignore-style ignore files and silently skips some source files (for examplelib/stats.ts). Usecommand grepwhen a search result looks suspiciously empty.
Conventions the stats pages follow (so they pass)
- Cards come from
ChartCard; grids fromCardGrid(minmax(min(Npx, 100%), 1fr)). - Wide content scrolls inside its own container (tables:
scroll={{ x: true }}; the year calendar opens scrolled to the latest week) or shrinks to fit (the weekday x hour heatmap). - Column-chart labels are truncated per group of slots (
labelEvery); the full text is in the tooltip. - Phones (<= 640px) get a tab strip (
Segmented) instead of the side menu inStatisticsView.tsx.