codeburn/app/renderer/components/Onboarding.test.tsx
iamtoruk 300e949951 feat(app): refresh cadence, instant switching, cache coherence, telemetry v1
Performance and coherence:
- Settings > General 'Refresh every' (Manual/30s/1m/3m/5m/10m), live via
  RefreshCadenceContext; Manual polls only on demand
- usePolled memoKey LRU: provider/period switches paint the last-good
  result instantly with a switching hairline while refreshing quietly
- quota TTL 5min + honest rate-limited copy on 429 backoff
- version-suffixed cache files (session-cache.v5.json, daily-cache.v12,
  auto-minted on future bumps); legacy files never written or deleted,
  adopted once when versions match: old and new binaries coexist
  without clobbering (field-observed menubar-vs-desktop ping-pong)
- advisory hydration lock: concurrent cold starts share one scan
  (wait-then-read-warm), stale/dead locks self-heal, never a
  correctness gate

Telemetry v1 + onboarding (desktop only, per owner decisions):
- first-launch onboarding (3 feature screens + consent); region-split
  default (EU/EEA/UK/CH off, elsewhere on, unknown off); nothing sends
  before consent completion or while off; dev builds never send
- anonymous install UUID, rotated on opt-out; day-granularity events,
  cost buckets only; whitelisted names; 200-event queue, 5min flush
- Settings > Privacy live toggle replaces the static claim

Zero computed-number changes. App 316/316, root 1805.

Wire contract targets api.codeburn.app/v1/telemetry (Worker follows).
2026-07-16 11:47:05 -07:00

63 lines
2.2 KiB
TypeScript

// @vitest-environment jsdom
import { fireEvent, render, screen } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
const mocks = vi.hoisted(() => ({
openExternal: vi.fn(),
}))
vi.mock('../lib/ipc', () => ({
codeburn: { openExternal: mocks.openExternal },
normalizeCliError: (err: unknown) => err,
}))
import { Onboarding } from './Onboarding'
function next(): void {
fireEvent.click(screen.getByRole('button', { name: 'Next' }))
}
describe('Onboarding', () => {
it('walks three feature screens into the consent screen', () => {
render(<Onboarding defaultEnabled onDone={() => {}} />)
expect(screen.getByText('Every agent. One dashboard.')).toBeInTheDocument()
next()
expect(screen.getByText('Local-first by design.')).toBeInTheDocument()
next()
expect(screen.getByText('Find the waste.')).toBeInTheDocument()
next()
expect(screen.getByText('Help improve CodeBurn')).toBeInTheDocument()
// Back returns to the previous screen.
fireEvent.click(screen.getByRole('button', { name: 'Back' }))
expect(screen.getByText('Find the waste.')).toBeInTheDocument()
})
it('seeds the toggle from the regional default and reports the final choice', () => {
const onDone = vi.fn()
render(<Onboarding defaultEnabled={false} onDone={onDone} />)
next(); next(); next()
// EU-style default: switch starts off.
const toggle = screen.getByRole('switch', { name: 'Anonymous telemetry' })
expect(toggle).toHaveAttribute('aria-checked', 'false')
// The user opts in, then finishes.
fireEvent.click(toggle)
expect(toggle).toHaveAttribute('aria-checked', 'true')
fireEvent.click(screen.getByRole('button', { name: 'Get started' }))
expect(onDone).toHaveBeenCalledWith(true)
})
it('keeps the regional default when untouched and links the data policy', () => {
const onDone = vi.fn()
render(<Onboarding defaultEnabled onDone={onDone} />)
next(); next(); next()
fireEvent.click(screen.getByRole('button', { name: 'What data we collect' }))
expect(mocks.openExternal).toHaveBeenCalledWith('https://www.codeburn.app/telemetry')
fireEvent.click(screen.getByRole('button', { name: 'Get started' }))
expect(onDone).toHaveBeenCalledWith(true)
})
})