mirror of
https://github.com/vernu/textbee.git
synced 2026-07-30 17:07:46 -04:00
Top bar (app-header): - Removed the Contribute button. It stays reachable from the footer. - Removed the theme selector; it moves to the sidebar footer. - Removed the mobile sheet for signed-in users: it duplicated the bottom tab bar for navigation and the avatar menu for identity. Signed-out visitors keep it, since auth pages have no tab bar. The header is now brand on the left, account on the right. Footer: - Rebuilt as a slim single bar. A logged-in user is already converted, so the app does not need the marketing site's multi-column link farm. It borrows that footer's visual language (muted surface, muted-to-foreground hovers, green status pill) so the two still read as one product. - Fixed the "cut by the side nav" bug. The footer was rendered in (app)/layout.tsx as a sibling of <main>, so it spanned the full viewport while the dashboard's fixed sidebar painted over its left 240px, and the fixed mobile tab bar covered its bottom edge. It is now rendered per section, inside each content column, with the dashboard copy padded clear of the tab bar. Theme control: - Moved to the sidebar footer and restyled from a dropdown into a three-way Light/Dark/System segmented control, which now has room to show all three states at once. Sidebar icon: - Dashboard uses LayoutDashboard instead of Home, matching the icon the avatar menu already uses for the same destination. E2e harness, two real fixes found while verifying: - The suite ran against `next dev`, which compiles routes on demand, so parallel workers hitting cold routes timed out at random. Switched to a production build; the suite went from 1.3m to ~31s. - The survey modal (a Math.random() coin flip) and the update-app prompt (whenever a mocked device reports an old version) could open over any page. A Radix dialog marks the rest of the page aria-hidden while open, so every getByRole query found nothing and a different test failed each run. Both are now suppressed deterministically in the session helper. Full suite: 16/16 on four consecutive runs. New chrome.spec.ts guards the footer geometry against both the sidebar and the mobile tab bar, asserts the top bar stays reduced, and asserts the sidebar theme control actually toggles the dark class. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
49 lines
1.8 KiB
TypeScript
49 lines
1.8 KiB
TypeScript
import { defineConfig, devices } from '@playwright/test'
|
|
|
|
// E2e runs the real Next app but every backend call is intercepted with mocked
|
|
// fixtures (see e2e/mock-api.ts). No real backend is ever contacted. The dev
|
|
// server is started with a fixed test secret so we can mint a valid NextAuth
|
|
// session cookie in tests.
|
|
export const TEST_AUTH_SECRET = 'e2e-test-secret-do-not-use-in-prod'
|
|
const PORT = 3100
|
|
export const BASE_URL = `http://localhost:${PORT}`
|
|
|
|
export default defineConfig({
|
|
testDir: './e2e',
|
|
fullyParallel: true,
|
|
forbidOnly: !!process.env.CI,
|
|
retries: process.env.CI ? 2 : 0,
|
|
workers: process.env.CI ? 1 : undefined,
|
|
reporter: process.env.CI ? 'github' : 'list',
|
|
// Headroom for pages that server-redirect, hydrate, then settle several
|
|
// intercepted API calls while workers share one server.
|
|
expect: { timeout: 10_000 },
|
|
use: {
|
|
baseURL: BASE_URL,
|
|
trace: 'on-first-retry',
|
|
},
|
|
projects: [
|
|
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
|
|
],
|
|
webServer: {
|
|
// Production build, not `next dev`. The dev server compiles routes on
|
|
// demand, so parallel workers hitting cold routes paid a multi-second
|
|
// first-compile cost and timed out at random. Which tests failed varied
|
|
// run to run. `next start` serves prebuilt routes, so the suite is
|
|
// deterministic.
|
|
command: 'pnpm build && pnpm start',
|
|
url: BASE_URL,
|
|
reuseExistingServer: !process.env.CI,
|
|
timeout: 240_000,
|
|
env: {
|
|
PORT: String(PORT),
|
|
NEXTAUTH_URL: BASE_URL,
|
|
NEXTAUTH_SECRET: TEST_AUTH_SECRET,
|
|
// Point the app at a backend host that only exists to be intercepted.
|
|
NEXT_PUBLIC_API_BASE_URL: 'http://localhost:3999/api/v1',
|
|
NEXT_PUBLIC_GOOGLE_CLIENT_ID: 'e2e-google-client-id',
|
|
NEXT_PUBLIC_TURNSTILE_SITE_KEY: '1x00000000000000000000AA',
|
|
},
|
|
},
|
|
})
|