Merge pull request #107 from AmanTahiliani/feat/issue-103-admin-a11y

Fix Admin accessibility and allow pinch-zoom (#103)
This commit is contained in:
Aman Tahiliani
2026-10-03 10:24:23 -04:00
committed by GitHub
4 changed files with 36 additions and 11 deletions

View File

@@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#0d0d0d" /> <meta name="theme-color" content="#0d0d0d" />
<meta name="description" content="box-box: A premium Live F1 Dashboard and Timing Tower" /> <meta name="description" content="box-box: A premium Live F1 Dashboard and Timing Tower" />

View File

@@ -21,7 +21,9 @@ const rootRoute = createRootRoute({
component: () => ( component: () => (
<> <>
<Nav /> <Nav />
<Outlet /> <main>
<Outlet />
</main>
</> </>
), ),
}) })

View File

@@ -1434,7 +1434,7 @@ a { color: inherit; text-decoration: none; }
font-weight: 700; font-weight: 700;
letter-spacing: 0.14em; letter-spacing: 0.14em;
text-transform: uppercase; text-transform: uppercase;
color: var(--text-3); color: var(--text-2);
} }
.dl-page-title { .dl-page-title {
@@ -1444,7 +1444,7 @@ a { color: inherit; text-decoration: none; }
.dl-page-sub { .dl-page-sub {
font-size: 11px; font-size: 11px;
color: var(--text-3); color: var(--text-2);
} }
.dl-page-banner { .dl-page-banner {
@@ -1470,7 +1470,7 @@ a { color: inherit; text-decoration: none; }
flex-wrap: wrap; flex-wrap: wrap;
gap: var(--s5); gap: var(--s5);
font-size: 11px; font-size: 11px;
color: var(--text-3); color: var(--text-2);
letter-spacing: 0.05em; letter-spacing: 0.05em;
text-transform: uppercase; text-transform: uppercase;
} }
@@ -1554,7 +1554,7 @@ a { color: inherit; text-decoration: none; }
font-size: 9px; font-size: 9px;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.08em; letter-spacing: 0.08em;
color: var(--text-3); color: var(--text-2);
} }
.dl-stat-val { .dl-stat-val {
@@ -1592,7 +1592,7 @@ a { color: inherit; text-decoration: none; }
.dl-content-meta { .dl-content-meta {
font-size: 12px; font-size: 12px;
color: var(--text-3); color: var(--text-2);
font-family: var(--f-mono); font-family: var(--f-mono);
} }

View File

@@ -1,7 +1,9 @@
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { describe, it, expect, vi, beforeEach } from 'vitest' import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, waitFor, fireEvent } from '@testing-library/react' import { render, screen, waitFor } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { RouterProvider, createRouter, createRootRoute, createRoute } from '@tanstack/react-router' import { RouterProvider, createRouter, createRootRoute, createRoute, Outlet } from '@tanstack/react-router'
import { DataLibraryPage } from '../pages/DataLibraryPage' import { DataLibraryPage } from '../pages/DataLibraryPage'
import type { DatasetInfo, Meeting, Weekend } from '../types' import type { DatasetInfo, Meeting, Weekend } from '../types'
@@ -75,14 +77,16 @@ function renderPage() {
const rootRoute = createRootRoute({ const rootRoute = createRootRoute({
component: () => ( component: () => (
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<DataLibraryPage /> <main>
<Outlet />
</main>
</QueryClientProvider> </QueryClientProvider>
), ),
}) })
const indexRoute = createRoute({ const indexRoute = createRoute({
getParentRoute: () => rootRoute, getParentRoute: () => rootRoute,
path: '/', path: '/',
component: () => null, component: DataLibraryPage,
}) })
const router = createRouter({ routeTree: rootRoute.addChildren([indexRoute]) }) const router = createRouter({ routeTree: rootRoute.addChildren([indexRoute]) })
@@ -103,6 +107,9 @@ describe('DataLibraryPage', () => {
renderPage() renderPage()
expect(await screen.findByTestId('data-library-empty')).toBeInTheDocument() expect(await screen.findByTestId('data-library-empty')).toBeInTheDocument()
expect(screen.getByRole('main')).toContainElement(screen.getByTestId('data-library-empty'))
expect(screen.getByText('box-box · admin')).toBeInTheDocument()
expect(screen.getByText(/Local SQLite domain store/i)).toBeInTheDocument()
expect(screen.getByText(/No ingested seasons yet/i)).toBeInTheDocument() expect(screen.getByText(/No ingested seasons yet/i)).toBeInTheDocument()
expect(screen.getByText('box-box --ingest-year 2025')).toBeInTheDocument() expect(screen.getByText('box-box --ingest-year 2025')).toBeInTheDocument()
}) })
@@ -115,10 +122,15 @@ describe('DataLibraryPage', () => {
renderPage() renderPage()
expect(await screen.findByTestId('data-library')).toBeInTheDocument() expect(await screen.findByTestId('data-library')).toBeInTheDocument()
expect(screen.getByRole('main')).toContainElement(screen.getByTestId('data-library'))
await waitFor(() => { await waitFor(() => {
expect(mockFetchLocalMeetings).toHaveBeenCalledWith(2025) expect(mockFetchLocalMeetings).toHaveBeenCalledWith(2025)
}) })
expect(screen.getByText('box-box · admin')).toBeInTheDocument()
const statLabels = [...document.querySelectorAll('.dl-stat-label')].map((el) => el.textContent)
expect(statLabels).toEqual(expect.arrayContaining(['Full', 'Partial', 'Cancelled', 'Missing', 'Total']))
expect(document.querySelector('.dl-content-meta')).toHaveTextContent(/1 meeting/)
expect(await screen.findByTestId('meeting-detail')).toBeInTheDocument() expect(await screen.findByTestId('meeting-detail')).toBeInTheDocument()
expect(screen.getAllByText('Monaco').length).toBeGreaterThan(0) expect(screen.getAllByText('Monaco').length).toBeGreaterThan(0)
expect(screen.getByText('11/11')).toBeInTheDocument() expect(screen.getByText('11/11')).toBeInTheDocument()
@@ -126,6 +138,17 @@ describe('DataLibraryPage', () => {
expect(screen.getByText('box-box --ingest-session 9472')).toBeInTheDocument() expect(screen.getByText('box-box --ingest-session 9472')).toBeInTheDocument()
}) })
it('does not disable pinch-zoom in the viewport meta', () => {
const html = readFileSync(resolve(__dirname, '../../index.html'), 'utf8')
const match = html.match(/<meta name="viewport" content="([^"]+)"/)
expect(match).not.toBeNull()
const content = match![1]
expect(content).toMatch(/width\s*=\s*device-width/)
expect(content).toMatch(/initial-scale\s*=\s*1/)
expect(content).not.toMatch(/user-scalable\s*=\s*no/i)
expect(content).not.toMatch(/maximum-scale/i)
})
it('shows partial badge for partial weekends', async () => { it('shows partial badge for partial weekends', async () => {
const partialWeekend: Weekend = { const partialWeekend: Weekend = {
...weekend, ...weekend,