import assert from 'node:assert/strict'; import fs from 'node:fs'; import path from 'node:path'; import test from 'node:test'; import { fileURLToPath } from 'node:url'; import { formatByteString, formatLastSeen, positiveByteDelta, sortDevicesByTraffic, trafficAxisMid, trafficSampleMetrics, } from '../../src/web/utils/format.js'; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..'); const overview = fs.readFileSync(path.join(root, 'src/web/components/ClientOverviewPage.jsx'), 'utf8'); const panel = fs.readFileSync(path.join(root, 'src/web/components/DevicesPanel.jsx'), 'utf8'); const api = fs.readFileSync(path.join(root, 'src/web/api.js'), 'utf8'); const server = fs.readFileSync(path.join(root, 'src/server/index.js'), 'utf8'); const styles = fs.readFileSync(path.join(root, 'src/web/styles.css'), 'utf8'); test('Gateway device inventory uses the existing accessible responsive drawer', () => { assert.match(overview, /isGateway && latestDevice\[key\] !== device\[key\]\)[\s\S]*api\.devices\.update\(device\.id, patch, latest\.revision\)/); assert.match(panel, /deviceNodes\.current\.get\(id\)\?\.animate/); assert.match(panel, /movementAnimations\.current\.get\(id\)\?\.cancel\(\)/); assert.match(panel, /prefers-reduced-motion: reduce/); assert.match(api, /refresh: \(\) => request\('\/api\/devices\/refresh', \{ method: 'POST' \}\)/); assert.match(api, /setPolicy: \(id, mode, expectedRevision\) => request\(`\/api\/devices\/\$\{id\}\/policy`/); assert.match(server, /requestUrl\.pathname === '\/api\/devices\/refresh'[\s\S]*deviceInventory\.refresh\(\)/); assert.match(server, /\/api\\\/devices\\\/\(dev_\[a-f0-9\]\{16\}\)\\\/policy\$[\s\S]*deviceInventory\.setPolicy/); assert.match(panel, /Изменить название<\/Tooltip>/); assert.match(panel, /copyText\(device\.ip\)/); assert.match(panel, /client-device-name-primary[\s\S]*client-device-name-ip[\s\S]*client-device-name-feedback/); assert.match(panel, /client-device-name-feedback[\s\S]*'copied!'/); assert.match(panel, /COPY_FEEDBACK_MS = 5_000/); assert.match(panel, /client-device-name-feedback[\s\S]*client-device-edit-wrap[\s\S]*client-device-last-seen/); assert.doesNotMatch(panel, /client-device-title/); assert.match(panel, /online \? 'В сети' : /); assert.match(panel, /aria-label=\{`\$\{online \? 'В сети' : 'Не в сети'\}\. Последний контакт: \$\{seen\.tooltip\}`\}/); assert.doesNotMatch(panel, /client-device-status|STATUS_LABELS/); assert.doesNotMatch(panel, /client-text-morph-goo/); assert.doesNotMatch(panel, /client-device-addresses|client-device-manufacturer|client-device-meta/); assert.doesNotMatch(panel, /device\.interface/); assert.doesNotMatch(panel, /device\.mac/); assert.doesNotMatch(panel, /client-device-identity|Пояснение идентификации устройства|ⓘ/); assert.match(panel, /device\.confidence === 'ambiguous'/); assert.match(panel, /sortDevicesByTraffic\(snapshot\?\.devices, sortDirection\)/); assert.match(panel, /Трафик временно не обновляется/); assert.match(panel, /Учитывается только трафик, который прошёл через Harbor/); assert.match(panel, /client-device-traffic-total[\s\S]*Всего<\/b>Gateway<\/b> 0n/); assert.match(panel, /client-device-traffic-breakdown[\s\S]*\{hasProxyTraffic && Прокси<\/b>\{time\}<\/time>[\s\S]*Всего \{formatByteString\(total\)\}<\/strong>/); assert.match(panel, /trafficAxisMid\(max, scale\)[\s\S]*client-device-traffic-axis[\s\S]*is-max[\s\S]*is-mid[\s\S]*is-zero/); assert.match(panel, /routeLabel=\{device\.appliedPolicy === 'direct' \? 'Напрямую' : 'Gateway'\}/); assert.match(panel, /\{proxy > 0n && Proxy \{formatByteString\(proxy\)\}<\/span>\}/); assert.match(panel, /