import assert from 'node:assert/strict'; import { before, after, test } from 'node:test'; import { createServer } from 'vite'; import { readFile } from 'node:fs/promises'; let server, api; before(async () => { server = await createServer({ appType: 'custom', logLevel: 'silent', server: { middlewareMode: true } }); api = await server.ssrLoadModule('/src/core/observation/sessionOverview.ts'); }); after(async () => { await server?.close(); }); test('height slice delegates endpoint labels and unit-bearing value to the shared range', async () => { const source = await readFile(new URL('../src/components/observation/SessionOverviewScene.tsx', import.meta.url), 'utf8'); assert.match(source, /RangeControl orientation="vertical" limitSide="left" label="Срез"/); assert.match(source, /formatLimit=\{value => value\.toFixed\(1\)\.replace\('\.', ','\)\}/); assert.match(source, /formatValue=\{value => `\$\{value\.toFixed\(1\)\.replace\('\.', ','\)\} м`\}/); assert.doesNotMatch(source, /\{(?:high|low)\.toFixed\(1\)\} м<\/span>/); }); test('interval chart retains the largest pause and rejects invalid values', () => { const result = api.overviewChartPoints([[0, .1], [30, 1.2], [60, .1], [NaN, 5]], 100, 50); assert.equal(result.xmax, 60); assert.equal(result.ymax, 1.32); assert.equal(result.points.split(' ').length, 3); assert.doesNotMatch(result.points, /NaN/); }); test('session overview rejects a result belonging to a different session', async () => { const original = globalThis.fetch; globalThis.fetch = async () => ({ ok: true, json: async () => ({ schema_version: 'missioncore.session-overview/v1', state: 'ready', session: { session_id: 'other' } }) }); try { await assert.rejects(api.fetchSessionOverview('selected', new AbortController().signal), /некорректные/); } finally { globalThis.fetch = original; } });