All checks were successful
deploy / deploy (push) Successful in 1m0s
Proof: Added PostgreSQL-backed quote lifecycle statistics for all-time, monthly, weekly, daily, hourly, and five-minute windows; wired authenticated dashboard API, live WebSocket counters, history-writer refresh before pruning, and dashboard controls; validated with targeted tests, full npm test, and operator dashboard build. Assumptions: Unique quote counts are keyed by durable quote_id, quote windows use the first durable lifecycle timestamp in UTC with Monday UTC weeks, and missing identifiers or timestamps are represented as unavailable evidence instead of fabricated quote identities. Still fake: Fee-aware PnL, cashflow, oracle-deviation, size distribution, matched-only analytics, and reconstruction of already-pruned detail remain outside this turn.
274 lines
14 KiB
JavaScript
274 lines
14 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, /Pause freezes only the rolling table/);
|
|
assert.match(strategySource, /Pinned quote investigator/);
|
|
assert.match(strategySource, /Lookup identifier/);
|
|
assert.match(strategySource, /Inspect quote/);
|
|
assert.match(strategySource, /Refresh lookup/);
|
|
assert.match(strategySource, /fetchQuoteLifecycleLookup/);
|
|
assert.match(strategySource, /\/api\/strategy\/quote-lifecycle\//);
|
|
assert.match(strategySource, /QUOTE_LIFECYCLE_PROBLEM_FILTERS/);
|
|
assert.match(strategySource, /QUOTE_LIFECYCLE_STAT_GRAINS/);
|
|
assert.match(strategySource, /QUOTE_LIFECYCLE_STAT_BUCKETS/);
|
|
assert.match(strategySource, /fetchQuoteLifecycleStatistics/);
|
|
assert.match(strategySource, /\/api\/strategy\/quote-lifecycle\/statistics/);
|
|
assert.match(strategySource, /five_minute/);
|
|
assert.match(strategySource, /all_time/);
|
|
assert.match(strategySource, /submitted_no_reply/);
|
|
assert.match(strategySource, /submission_failed/);
|
|
assert.match(strategySource, /success/);
|
|
assert.match(strategySource, /quote_lifecycle_statistics/);
|
|
assert.match(strategySource, /Refresh stats/);
|
|
assert.match(strategySource, /awaiting_executor/);
|
|
assert.match(strategySource, /quote_not_found_or_finished/);
|
|
assert.match(strategySource, /approved_no_command/);
|
|
assert.match(strategySource, /submitted_awaiting_outcome/);
|
|
assert.match(strategySource, /updateSelectedLifecycleFromLiveRows/);
|
|
assert.match(strategySource, /shouldRefreshSelectedFromDurable/);
|
|
assert.match(strategySource, /updateSelectedLifecycleFromLookup/);
|
|
assert.match(strategySource, /Command age:/);
|
|
assert.match(strategySource, /Executor result:/);
|
|
assert.match(strategySource, /Next expected:/);
|
|
assert.match(strategySource, /visibleRows/);
|
|
assert.match(strategySource, /quote-lifecycle-placeholder-row/);
|
|
assert.match(stylesSource, /\.quote-investigator-panel/);
|
|
assert.match(stylesSource, /\.quote-statistics-panel/);
|
|
assert.match(stylesSource, /\.quote-statistics-table/);
|
|
assert.match(stylesSource, /\.quote-lifecycle-lookup/);
|
|
assert.match(stylesSource, /\.quote-lifecycle-table tbody tr\.quote-lifecycle-row\.is-selected/);
|
|
assert.match(stylesSource, /\.shell \{[\s\S]*?width: 100%;[\s\S]*?margin: 0;[\s\S]*?\}/);
|
|
assert.doesNotMatch(stylesSource, /^\s*max-width\s*:/m);
|
|
assert.doesNotMatch(strategySource, /maxWidth:/);
|
|
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.match(strategySource, /For us:/);
|
|
assert.match(strategySource, /makerPairMovementLabel/);
|
|
assert.match(strategySource, /makerPairRequestLabel/);
|
|
assert.match(strategySource, /formatInventoryCheck/);
|
|
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('service cards expose executor verifier salt and queue delay state', () => {
|
|
assert.match(serviceCardSource, /verifier_salt_cache/);
|
|
assert.match(serviceCardSource, /executor_queue_delay/);
|
|
assert.match(serviceCardSource, /Verifier salt/);
|
|
assert.match(serviceCardSource, /Salt age/);
|
|
assert.match(serviceCardSource, /Salt refresh/);
|
|
assert.match(serviceCardSource, /Salt error/);
|
|
assert.match(serviceCardSource, /Salt rejects/);
|
|
assert.match(serviceCardSource, /Queue delay/);
|
|
assert.match(serviceCardSource, /Queue p90/);
|
|
assert.match(serviceCardSource, /Queue p99/);
|
|
});
|
|
|
|
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, /persisted_rollups/);
|
|
assert.match(strategySource, /aggregate rollups/);
|
|
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('system page exposes quote lifecycle retention and storage rollup truth', () => {
|
|
assert.match(systemSource, /Retention mode/);
|
|
assert.match(systemSource, /Rollup freshness/);
|
|
assert.match(systemSource, /Preserved successes/);
|
|
assert.match(systemSource, /storage-retention-table/);
|
|
assert.match(systemSource, /quote_lifecycle_rollups/);
|
|
assert.match(systemSource, /formatBytes/);
|
|
assert.match(stylesSource, /\.storage-retention-table td/);
|
|
});
|
|
|
|
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/);
|
|
});
|