import React from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; import { describe, expect, it, vi } from 'vitest'; import type { BotState } from '../hooks/useWebSocket'; import { SignalsTab } from './SignalsTab'; import { SettingsTab } from './SettingsTab'; import { EntriesTab } from './EntriesTab'; import { AdminTab } from './AdminTab'; import { ConfigTab } from './ConfigTab'; import { HistoryTab } from './HistoryTab'; import { DEFAULT_BOT_STATE } from '../hooks/useWebSocket'; vi.mock('../components/AuthContext', () => ({ useAuth: () => ({ user: null, profile: { role: 'admin', first_name: 'Admin', last_name: 'User' }, refreshProfile: vi.fn() }) })); vi.mock('../lib/supabaseClient', () => { const query: any = { select: vi.fn(() => query), order: vi.fn(() => query), eq: vi.fn(() => query), limit: vi.fn(() => Promise.resolve({ data: [], error: null })), insert: vi.fn(() => Promise.resolve({ error: null })), update: vi.fn(() => query), upsert: vi.fn(() => Promise.resolve({ error: null })), delete: vi.fn(() => query) }; return { supabase: { from: vi.fn(() => query), auth: { getSession: vi.fn(async () => ({ data: { session: null } })) } } }; }); vi.mock('../components/EntryForm', () => ({ EntryForm: () => React.createElement('div', null, 'EntryFormMock') })); vi.mock('../components/SymbolCard', () => ({ SymbolCard: ({ symbol }: { symbol: string }) => React.createElement('div', null, `SymbolCard-${symbol}`) })); const baseBotState: BotState = { symbols: { 'BTC/USDT': { price: 70100, change24h: 2.1, changeToday: 1.2, session: 'NY', volatility: 'High', signal: 'BUY', activePosition: null, priceHistory: [], rules: { TrendBiasRule: { passed: true, reason: 'aligned' } }, indicators: { ema50_4h: 68000, ema200_4h: 66000, rsi_1h: 55 } } }, alerts: [], positions: [], orders: [], history: [], settings: { executionMode: 'Paper', riskPerTrade: 0.01, totalCapital: 15000, maxOpenTrades: 6, isAlgoEnabled: true, enabledRules: ['TrendBiasRule', 'RiskManagementRule'] }, uptime: 600000 }; describe('dashboard tabs smoke coverage', () => { it('renders SignalsTab with symbol cards and empty state branch', () => { const withSymbols = renderToStaticMarkup( React.createElement(SignalsTab, { botState: baseBotState }) ); expect(withSymbols).toContain('Market Signals'); expect(withSymbols).toContain('SymbolCard-BTC/USDT'); const emptyState = { ...baseBotState, symbols: {} }; const emptyHtml = renderToStaticMarkup( React.createElement(SignalsTab, { botState: emptyState }) ); expect(emptyHtml).toContain('No symbols available'); }); it('renders SettingsTab user config and bot status blocks', () => { const html = renderToStaticMarkup( React.createElement(SettingsTab, { botState: baseBotState }) ); expect(html).toContain('Settings & Configuration'); expect(html).toContain('User Configuration'); expect(html).toContain('Bot Internal Status (WebSocket)'); expect(html).toContain('Algorithm: ENABLED'); }); it('renders EntriesTab empty-state and primary controls', () => { const html = renderToStaticMarkup(React.createElement(EntriesTab)); expect(html).toContain('Watchlist & Entries'); expect(html).toContain('Manual Entry Injection'); expect(html).toContain('Cluster Context Null'); }); it('renders AdminTab strategy pipeline and ConfigTab loading shell', () => { const adminState = { ...DEFAULT_BOT_STATE, settings: { ...DEFAULT_BOT_STATE.settings, enabledRules: ['TrendBiasRule', 'MomentumRule', 'AIAnalysisRule'] } }; const adminHtml = renderToStaticMarkup( React.createElement(AdminTab, { botState: adminState, socket: null }) ); expect(adminHtml).toContain('Admin Panel'); expect(adminHtml).toContain('Strategy Pipeline'); expect(adminHtml).toContain('TrendBias'); expect(adminHtml).toContain('AIAnalysis'); const configHtml = renderToStaticMarkup(React.createElement(ConfigTab)); expect(configHtml).toContain('Calibrating Infrastructure'); }); it('renders HistoryTab loading state shell', () => { const html = renderToStaticMarkup( React.createElement(HistoryTab, { botState: { history: [] } }) ); expect(html).toContain('animate-spin'); }); });