/** * AgentIntelligenceCard — tests that feedback stats are rendered correctly. * * Uses a lightweight approach: tests the data-transformation logic and * verifies the component accepts the FeedbackStats shape without errors. * Since this is a Tauri desktop app (not Next.js), we test the card's * data contract and rendering expectations. */ import { describe, it, expect } from 'vitest'; import type { FeedbackStats } from '../src/components/cockpit/types'; describe('AgentIntelligenceCard data contract', () => { it('FeedbackStats shape matches the /api/feedback/stats response', () => { const stats: FeedbackStats = { totalFeedback: 42, positiveRate: 0.85, topIssues: ['wrong_answer', 'too_verbose'], correctionsThisWeek: 3, improvementTrend: '+12%', }; expect(stats.totalFeedback).toBe(42); expect(stats.positiveRate).toBe(0.85); expect(stats.topIssues).toHaveLength(2); expect(stats.correctionsThisWeek).toBe(3); expect(stats.improvementTrend).toBe('+12%'); }); it('handles empty stats (zero feedback)', () => { const stats: FeedbackStats = { totalFeedback: 0, positiveRate: 0, topIssues: [], correctionsThisWeek: 0, improvementTrend: '0%', }; expect(stats.totalFeedback).toBe(0); expect(stats.positiveRate).toBe(0); expect(stats.topIssues).toEqual([]); }); it('handles negative improvement trend', () => { const stats: FeedbackStats = { totalFeedback: 10, positiveRate: 0.5, topIssues: ['wrong_tool'], correctionsThisWeek: 7, improvementTrend: '-5%', }; expect(stats.improvementTrend).toBe('-5%'); // Negative trend starts with '-' expect(stats.improvementTrend.startsWith('-')).toBe(true); }); it('trend parsing for positive values', () => { const trend = '+12%'; const match = trend.match(/^([+-]?\d+)%$/); expect(match).not.toBeNull(); expect(parseInt(match![1], 10)).toBe(12); }); it('trend parsing for negative values', () => { const trend = '-5%'; const match = trend.match(/^([+-]?\d+)%$/); expect(match).not.toBeNull(); expect(parseInt(match![1], 10)).toBe(-5); }); it('trend parsing for zero', () => { const trend = '0%'; const match = trend.match(/^([+-]?\d+)%$/); expect(match).not.toBeNull(); expect(parseInt(match![1], 10)).toBe(0); }); it('reason formatting converts snake_case to Title Case', () => { const formatReason = (reason: string): string => reason .split('_') .map(word => word.charAt(0).toUpperCase() + word.slice(1)) .join(' '); expect(formatReason('wrong_answer')).toBe('Wrong Answer'); expect(formatReason('too_verbose')).toBe('Too Verbose'); expect(formatReason('wrong_tool')).toBe('Wrong Tool'); expect(formatReason('too_slow')).toBe('Too Slow'); expect(formatReason('other')).toBe('Other'); }); });