unrip/test/operator-dashboard-ui-static.test.mjs
philipp 7b2f31fd4d
All checks were successful
deploy / deploy (push) Successful in 1m3s
Keep dashboard updates live without jitter
Proof: Quote lifecycle and competitiveness now update live while unpaused, with fixed row slots and clamped cells carrying the jitter prevention; static UI coverage, full npm test, and the operator dashboard build validate the correction.

Assumptions: this is a UI-only operator cleanup for the active maker timing and competitiveness turn; it does not change strategy decisions, execution, DB config, persistence, live funds, or response policy.

Still fake: venue-native terminal fill ids and fee-complete realized PnL remain unavailable.
2026-05-19 18:15:05 +02:00

209 lines
11 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
const strategySource = readFileSync(new URL('../src/operator-dashboard/static/pages/StrategyPage.jsx', import.meta.url), 'utf8');
const fundsSource = readFileSync(new URL('../src/operator-dashboard/static/pages/FundsPage.jsx', import.meta.url), 'utf8');
const stylesSource = readFileSync(new URL('../src/operator-dashboard/static/styles.css', import.meta.url), 'utf8');
const serviceCardSource = readFileSync(new URL('../src/operator-dashboard/static/components/ServiceCard.jsx', import.meta.url), 'utf8');
const statusBarSource = readFileSync(new URL('../src/operator-dashboard/static/components/StatusBar.jsx', import.meta.url), 'utf8');
const systemSource = readFileSync(new URL('../src/operator-dashboard/static/pages/SystemPage.jsx', import.meta.url), 'utf8');
const appSource = readFileSync(new URL('../src/operator-dashboard/static/App.jsx', import.meta.url), 'utf8');
const navSource = readFileSync(new URL('../src/operator-dashboard/static/components/NavRail.jsx', import.meta.url), 'utf8');
test('strategy page owns consolidated quote lifecycle and successful trade tables', () => {
assert.match(strategySource, /Quote lifecycle/);
assert.match(strategySource, /Incoming quotes and what happened next/);
assert.match(strategySource, /Responded\?/);
assert.match(strategySource, /Successful trades only/);
assert.match(strategySource, /Gross edge est\./);
assert.match(strategySource, /successful_trade_gross_edge_estimate_eure/);
assert.match(strategySource, /before fees/);
assert.match(strategySource, /Show lifecycle/);
assert.match(strategySource, /formatAgeFromTimestamp/);
assert.match(strategySource, /quote-row-flash/);
assert.match(strategySource, /showStrategyRejected/);
assert.match(strategySource, /Rejected by strategy/);
assert.match(strategySource, /quoteDisplayPaused/);
assert.match(strategySource, /Pause display/);
assert.match(strategySource, /Resume display/);
assert.match(strategySource, /QUOTE_LIFECYCLE_ROW_COUNT/);
assert.match(strategySource, /latestItemsRef/);
assert.match(strategySource, /setDisplayItems\(items \|\| \[\]\)/);
assert.match(strategySource, /useNow\(\)/);
assert.match(strategySource, /Live updates/);
assert.match(strategySource, /Live rows update as they arrive/);
assert.match(strategySource, /visibleRows/);
assert.match(strategySource, /quote-lifecycle-placeholder-row/);
assert.match(stylesSource, /\.quote-lifecycle-table tbody tr\.quote-lifecycle-row/);
assert.match(stylesSource, /\.quote-lifecycle-placeholder-row td/);
assert.match(stylesSource, /\.lifecycle-clamp-one/);
assert.match(stylesSource, /\.lifecycle-clamp-two/);
assert.match(strategySource, /item\.execution\?\.error_message/);
assert.match(strategySource, /item\.execution\?\.note/);
assert.match(strategySource, /formatExecutionTiming/);
assert.match(strategySource, /item\.execution\?\.timing/);
assert.match(strategySource, /current_salt_ms/);
assert.match(strategySource, /current_salt_source/);
assert.match(strategySource, /current_salt_age_ms/);
assert.match(strategySource, /relay_response_ms/);
assert.match(strategySource, /Timing:/);
assert.match(strategySource, /item\.execution\?\.status === 'submitted'/);
assert.match(strategySource, /Submitted means the relay accepted the response; it does not prove a trade\./);
assert.doesNotMatch(strategySource, /Actionable|actionable/);
});
test('funds page no longer renders duplicate quote and submission tables', () => {
assert.doesNotMatch(fundsSource, /Recent incoming quotes/);
assert.doesNotMatch(fundsSource, /Recent submitted quote terms/);
assert.doesNotMatch(fundsSource, /Submitted quote responses/);
assert.doesNotMatch(fundsSource, /Durable ledger/);
});
test('request UI uses pair-native source amount fields and copy', () => {
assert.match(fundsSource, /name="source_amount"/);
assert.match(fundsSource, /pair_id: form\.pair_id/);
assert.match(fundsSource, /Pair request creation/);
assert.match(fundsSource, /Quoted \$\{item\.quoted_destination_amount\} \$\{destinationSymbol\}/);
assert.doesNotMatch(fundsSource, /EURe to BTC request creation/);
assert.doesNotMatch(fundsSource, /EURe-to-BTC/);
assert.doesNotMatch(fundsSource, /Quoted \$\{item\.quoted_destination_amount\} BTC/);
assert.doesNotMatch(fundsSource, /source_symbol \|\| 'EURe'/);
assert.doesNotMatch(fundsSource, /destination_symbol \|\| 'BTC'/);
});
test('funds balance rows expose unvalued valuation reasons', () => {
assert.match(fundsSource, /valuation_status === 'unvalued'/);
assert.match(fundsSource, /valuation_route_missing/);
});
test('status bar labels reference routes instead of a single BTC\\/EUR tile', () => {
assert.match(statusBarSource, /Reference Route/);
assert.match(statusBarSource, /active_pairs/);
assert.doesNotMatch(statusBarSource, /Reference BTC\/EUR/);
});
test('dashboard freshness surfaces show age and exact timestamp evidence', () => {
assert.match(serviceCardSource, /formatAgeFromTimestamp\(service\.freshness_at, now\)/);
assert.match(serviceCardSource, /formatTimestamp\(service\.freshness_at\)/);
assert.match(serviceCardSource, /Freshness at/);
assert.match(stylesSource, /\.quote-row-flash td/);
assert.match(stylesSource, /@keyframes quote-row-flash-cell/);
});
test('mobile status bar uses normal document flow instead of sticky viewport positioning', () => {
assert.match(
stylesSource,
/@media \(max-width: 720px\)[\s\S]*?\.status-bar \{[\s\S]*?position: static;[\s\S]*?top: auto;[\s\S]*?z-index: auto;[\s\S]*?\}/,
);
});
test('dashboard UI exposes official NEAR upstream status separately from local freshness', () => {
assert.match(statusBarSource, /NEAR Intents/);
assert.match(statusBarSource, /near_intents_upstream_label/);
assert.match(statusBarSource, /near_intents_upstream_reason/);
assert.match(statusBarSource, /Official status at/);
assert.match(serviceCardSource, /upstream_status/);
assert.match(serviceCardSource, /Upstream at/);
assert.match(serviceCardSource, /decisive_reason/);
});
test('asset registry table renders the loaded catalog without a hidden 20 row cap', () => {
assert.match(strategySource, /items\.map\(\(asset\)/);
assert.doesNotMatch(strategySource, /items\.slice\(0,\s*20\)\.map/);
});
test('strategy page exposes pair activation, pause, edge, and deposit address controls', () => {
assert.match(strategySource, /set-pair-mode/);
assert.match(strategySource, /pause-pair/);
assert.match(strategySource, /Add, pause, and tune directed pairs/);
assert.match(strategySource, /Add \/ activate pair/);
assert.match(strategySource, /pair-edge-bps/);
assert.match(strategySource, /pair-min-notional/);
assert.match(strategySource, /pair-max-notional/);
assert.match(strategySource, /Edge bps for/);
assert.match(strategySource, /Min notional for/);
assert.match(strategySource, /Max notional for/);
assert.match(strategySource, /min_notional/);
assert.match(strategySource, /maker_max_quote_age_enabled/);
assert.match(strategySource, /maker_max_quote_age_ms/);
assert.match(strategySource, /Age policy/);
assert.match(strategySource, /Max age/);
assert.match(strategySource, /Init/);
assert.match(strategySource, /deposit_address/);
assert.match(strategySource, /Copy/);
});
test('strategy page exposes maker timing waterfall and competitiveness summaries', () => {
assert.match(strategySource, /Maker competitiveness/);
assert.match(strategySource, /TimingWaterfall/);
assert.match(strategySource, /quote_to_relay_result_ms/);
assert.match(strategySource, /quote_not_found_or_finished/);
assert.match(strategySource, /maker_competitiveness/);
assert.match(strategySource, /pairDisplayLabel/);
assert.match(strategySource, /group\.edge_bps/);
assert.match(strategySource, /Pause updates/);
assert.match(strategySource, /Resume updates/);
assert.match(strategySource, /displaySummary/);
assert.match(strategySource, /fixedRows/);
assert.match(strategySource, /latestSummaryRef/);
assert.match(strategySource, /Live updates/);
assert.match(strategySource, /latencyStageRows/);
assert.match(stylesSource, /\.metric-stack/);
assert.match(stylesSource, /\.competitiveness-table-stack/);
assert.match(stylesSource, /\.competitiveness-table tbody tr/);
assert.match(stylesSource, /\.competitiveness-detail-table tbody tr/);
assert.match(stylesSource, /\.competitiveness-error-text/);
assert.match(stylesSource, /\.competitiveness-placeholder-row td/);
assert.match(stylesSource, /\.timing-waterfall-table/);
});
test('strategy page distinguishes configured bps from gross quote edge percent', () => {
assert.match(strategySource, /formatConfiguredEdgeBps/);
assert.match(strategySource, /Configured edge/);
assert.match(strategySource, /Gross edge/);
assert.match(strategySource, /number \/ 100/);
assert.doesNotMatch(strategySource, /Edge \$\{item\.edge_bps\}%/);
});
test('strategy section panels are split into separate menu destinations', () => {
assert.match(navSource, /Strategy overview/);
assert.match(navSource, /Pair config/);
assert.match(navSource, /Competitiveness/);
assert.match(navSource, /Asset registry/);
assert.match(navSource, /Successful trades/);
assert.match(navSource, /Quote lifecycle/);
assert.match(navSource, /page: 'strategy-pairs'/);
assert.match(navSource, /page: 'strategy-competitiveness'/);
assert.match(navSource, /page: 'strategy-assets'/);
assert.match(navSource, /page: 'strategy-trades'/);
assert.match(navSource, /page: 'strategy-lifecycle'/);
assert.match(appSource, /currentPage\.startsWith\('strategy-'\)/);
assert.match(appSource, /page=\{currentPage\}/);
assert.match(strategySource, /case 'strategy-pairs'/);
assert.match(strategySource, /case 'strategy-competitiveness'/);
assert.match(strategySource, /case 'strategy-assets'/);
assert.match(strategySource, /case 'strategy-trades'/);
assert.match(strategySource, /case 'strategy-lifecycle'/);
});
test('system page exposes deduped environmental conditions history', () => {
assert.match(systemSource, /Environmental conditions/);
assert.match(systemSource, /Stored only when the normalized official status changes/);
assert.match(systemSource, /NEAR Intents upstream status changes/);
assert.match(systemSource, /status_fingerprint/);
});
test('dashboard loading state exposes API failures and retry action', () => {
assert.match(appSource, /Dashboard unavailable/);
assert.match(appSource, /<LoadingPanel[\s\S]*error=\{state\.error\}/);
assert.match(appSource, /Retry/);
assert.match(appSource, /bootDashboard\(\)\.catch/);
});
test('dashboard bootstrap uses an explicit long timeout for slow live state aggregation', () => {
assert.match(appSource, /const BOOTSTRAP_TIMEOUT_MS = 45_000/);
assert.match(appSource, /timeoutMs: BOOTSTRAP_TIMEOUT_MS/);
});