Files
textbee/web/test
isra el 1999593e07 fix: day header overlap, mobile footer alignment, modal animation
Day headers in message history could cover message rows. Two distinct causes,
both reproduced before fixing:
- On mobile the header was pinned to top-14, the same sticky band the mobile
  search bar already occupies, so it detached and landed on top of rows.
  Being bg-muted/70 with a backdrop blur, row text bled through it, which is
  the distortion that was reported.
- On desktop it was pinned to top-0, behind the app header, and it covered
  rows scrolled beneath it and swallowed their clicks. Playwright surfaced
  this second one: a row click failed with "h3 intercepts pointer events".

Day headers are no longer sticky. A page holds 20 messages, so groups are
short and pinning bought little in exchange for those failures.

Footer links are left-aligned on mobile. Centred links in a single column had
no common edge to scan down.

Modal animation is now a quick fade. Dialogs slid in from the left and top
while zooming, which is the movement that read badly; the slide and zoom are
gone and the duration drops from 200ms to 150ms, applied to both the dialog
and alert-dialog primitives so every modal matches. Sheets still slide, since
that is what a drawer should do.

Guards: the overlap check runs at both mobile and desktop widths and also
asserts a row is still clickable after scrolling. Verified it fails against
the old markup rather than assuming a green test means coverage.

Fixture dates now anchor to local midnight instead of "N hours ago". A
2-hour-old message falls on the previous day when the suite runs shortly
after midnight, which made the Today/Yesterday assertions depend on the wall
clock. It failed exactly that way during this session.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 00:07:29 +03:00
..

Testing

The web app has two test layers. Both run against mocked API data. Tests must never point at a real backend.

Unit / component tests (Vitest + React Testing Library + MSW)

  • Runner: Vitest with jsdom.
  • API mocking: MSW node server (test/msw/server.ts) with handlers in test/msw/handlers.ts. Unhandled requests throw (onUnhandledRequest: 'error'), so a test can never silently reach a live backend.
  • Render helper: test/render.tsx exposes renderWithProviders / render, which wrap components in the app providers (react-query with retries off, a mock SessionProvider). Import render, screen, userEvent from @/test/render.
  • Fixtures: test/fixtures.ts is the single source of truth for mocked API data, shared with the e2e layer.

Commands:

pnpm test          # run once
pnpm test:watch    # watch mode
pnpm coverage      # with coverage report

Place tests next to the code as *.test.tsx or under __tests__/.

End-to-end tests (Playwright)

  • Runner: Playwright, specs in e2e/.
  • The real Next dev server boots on port 3100 with a fixed NEXTAUTH_SECRET and a backend URL (localhost:3999) that nothing listens on.
  • e2e/mock-api.ts intercepts every /api/v1/** request and serves the shared fixtures, so no request can reach a real backend.
  • e2e/session.ts mints a valid NextAuth session cookie so tests run authenticated without the real login flow.

Commands:

pnpm test:e2e      # headless
pnpm test:e2e:ui   # interactive UI

First-time setup downloads the browser: pnpm exec playwright install chromium.

The rule

If a new screen calls a new endpoint, add a handler in test/msw/handlers.ts and a branch in e2e/mock-api.ts, both backed by a fixture in test/fixtures.ts. Never let a test hit the network.