mirror of
https://github.com/azaion/ui.git
synced 2026-06-21 10:31:10 +00:00
434854bf3c
- Design system: v2 CSS variables (surface-0/1/2, border-hair, accent-amber/cyan/red/green/blue)
and utility classes (.btn, .inp, .pill, .chip, .bracket, .panel, .seg, .swatch,
.type-sq, .grid-bg, .ibtn, .checkbox, .tab); v1 az-* names aliased to v2 vars
so other pages still render. Google Fonts (IBM Plex Sans + JetBrains Mono)
loaded via <link> in index.html <head> to avoid FOUT.
- Header rebuilt to v2: amber wordmark + // divider, amber-bordered flight pill
with cyan live dot, tab-style nav with amber underline on active, LINK status
pill, cog + sign-out icon buttons.
- AdminPage rewritten to 3-column layout (340 / flex / 280):
- Detection Classes: search + ADD button, table with #/Name/Hex/Ops columns,
name-only inline edit with ringed swatch, sibling-row error alert.
- AI Recognition Engine + GPS Device Link panels with corner-bracket borders,
number steppers, segmented protocol control, dashed telemetry footers.
Hooks (useAiSettings, useGpsSettings) seed factory defaults so the UI is
interactive when GET fails (no backend).
- Default Aircrafts: P/C/F type chips, isDefault star toggle, + ADD AIRCRAFT
modal with model/type/resolution/maxMinutes/default fields.
- Co-located components: Modal (backdrop + ESC + body-scroll-lock),
NumberStepper (▲▼ with clamp on click but not on typing), ClassEditRow.
- Types: Aircraft extended with FixedWing + optional resolution/maxMinutes;
new AiRecognitionSettings/Telemetry, GpsDeviceSettings/Telemetry, GpsProtocol.
- Endpoints: /api/admin/ai-settings, /api/admin/gps-settings (+ /ping, /reconnect).
POST /api/flights/aircrafts (plural REST collection).
- MSW: stateful admin-settings handler with resetAdminSettingsSeed() wired into
tests/setup.ts. Aircraft seed expanded to 6 entries matching the mockup.
- i18n: full admin.{classes,aiEngine,gpsDevice,aircrafts} key sets in en+ua;
nav.dataset shortened to "Dataset"; obsolete users-management keys removed.
- Tests: new AdminPage AI/GPS/aircraft test suites; admin_class_edit selectors
updated for the name-only inline editor and the modal-based add flow.
72 lines
2.4 KiB
TypeScript
72 lines
2.4 KiB
TypeScript
import '@testing-library/jest-dom/vitest'
|
|
import { afterAll, afterEach, beforeAll } from 'vitest'
|
|
import { cleanup } from '@testing-library/react'
|
|
import { server } from './msw/server'
|
|
import { setToken, setNavigateToLogin } from '../src/api'
|
|
import { __resetBootstrapInflightForTests } from '../src/auth'
|
|
import { resetAdminSettingsSeed } from './msw/handlers/admin-settings'
|
|
|
|
// JSDOM polyfills for browser APIs production code touches at mount time.
|
|
// These are no-op stubs — tests that exercise the actual behavior install
|
|
// richer fakes per-suite (e.g. `tests/sse_lifecycle.test.tsx` overrides
|
|
// `globalThis.EventSource` and restores it; that pattern still works).
|
|
class NoopResizeObserver {
|
|
observe(): void {}
|
|
unobserve(): void {}
|
|
disconnect(): void {}
|
|
}
|
|
|
|
class NoopEventSource extends EventTarget {
|
|
url: string
|
|
readyState: 0 | 1 | 2 = 0
|
|
onopen: ((e: Event) => void) | null = null
|
|
onmessage: ((e: MessageEvent) => void) | null = null
|
|
onerror: ((e: Event) => void) | null = null
|
|
constructor(url: string | URL) {
|
|
super()
|
|
this.url = String(url)
|
|
}
|
|
close(): void {
|
|
this.readyState = 2
|
|
}
|
|
static readonly CONNECTING = 0
|
|
static readonly OPEN = 1
|
|
static readonly CLOSED = 2
|
|
}
|
|
|
|
const g = globalThis as unknown as {
|
|
ResizeObserver?: typeof NoopResizeObserver
|
|
EventSource?: typeof NoopEventSource
|
|
}
|
|
if (!g.ResizeObserver) g.ResizeObserver = NoopResizeObserver
|
|
if (!g.EventSource) g.EventSource = NoopEventSource
|
|
|
|
// MSW boundary configured per AZ-456 AC-3:
|
|
// - All outbound /api/<service>/... fetches MUST be intercepted.
|
|
// - A test missing a handler for a network request is a HARD failure
|
|
// (onUnhandledRequest: 'error'). This is how AC-3 is enforced for
|
|
// fast-profile tests; a leaked external request would otherwise
|
|
// escape the test environment silently.
|
|
beforeAll(() => {
|
|
server.listen({ onUnhandledRequest: 'error' })
|
|
})
|
|
|
|
afterEach(() => {
|
|
cleanup()
|
|
server.resetHandlers()
|
|
setToken(null)
|
|
setNavigateToLogin(() => {
|
|
/* default no-op for tests; production accessor restored implicitly
|
|
on next module reload — tests must re-seed if they assert on it. */
|
|
})
|
|
// AZ-510 — clear AuthProvider's module-scoped in-flight bootstrap promise so
|
|
// a never-resolving fixture in test N does not leak into test N+1.
|
|
__resetBootstrapInflightForTests()
|
|
// v2 admin settings — module-scoped seed mutates on PATCH; reset between tests.
|
|
resetAdminSettingsSeed()
|
|
})
|
|
|
|
afterAll(() => {
|
|
server.close()
|
|
})
|