import { describe, it, expect, beforeEach, vi } from 'vitest' import { useTestResultStore } from '../useTestResultStore' // Mock flashcardsService const mockFlashcardsService = { recordTestCompletion: vi.fn() } vi.mock('@/lib/services/flashcards', () => ({ flashcardsService: mockFlashcardsService })) // Mock isTestMode vi.mock('@/lib/mock/reviewMockData', () => ({ isTestMode: vi.fn() })) describe('useTestResultStore', () => { beforeEach(() => { // 重置 store useTestResultStore.getState().resetScore() vi.clearAllMocks() }) describe('初始狀態', () => { it('應該有正確的初始值', () => { const state = useTestResultStore.getState() expect(state.score).toEqual({ correct: 0, total: 0 }) expect(state.isRecordingResult).toBe(false) expect(state.recordingError).toBe(null) }) }) describe('updateScore', () => { it('應該正確更新正確答案分數', () => { const store = useTestResultStore.getState() store.updateScore(true) expect(store.score).toEqual({ correct: 1, total: 1 }) store.updateScore(true) expect(store.score).toEqual({ correct: 2, total: 2 }) }) it('應該正確更新錯誤答案分數', () => { const store = useTestResultStore.getState() store.updateScore(false) expect(store.score).toEqual({ correct: 0, total: 1 }) store.updateScore(true) expect(store.score).toEqual({ correct: 1, total: 2 }) }) }) describe('recordTestResult 測試模式', () => { beforeEach(() => { vi.mocked(require('@/lib/mock/reviewMockData').isTestMode).mockReturnValue(true) }) it('應該在測試模式下跳過 API 呼叫', async () => { const store = useTestResultStore.getState() const result = await store.recordTestResult({ flashcardId: 'mock-1', testType: 'flip-memory', isCorrect: true, userAnswer: 'test', confidenceLevel: 4 }) expect(result).toBe(true) expect(mockFlashcardsService.recordTestCompletion).not.toHaveBeenCalled() }) it('應該正確設置錄製狀態', async () => { const store = useTestResultStore.getState() // 開始錄製時檢查狀態 const recordPromise = store.recordTestResult({ flashcardId: 'mock-1', testType: 'flip-memory', isCorrect: true }) expect(store.isRecordingResult).toBe(true) // 等待完成 await recordPromise expect(store.isRecordingResult).toBe(false) }) }) describe('recordTestResult 正常模式', () => { beforeEach(() => { vi.mocked(require('@/lib/mock/reviewMockData').isTestMode).mockReturnValue(false) }) it('應該成功記錄測驗結果', async () => { mockFlashcardsService.recordTestCompletion.mockResolvedValue({ success: true }) const store = useTestResultStore.getState() const testParams = { flashcardId: 'mock-1', testType: 'flip-memory' as any, isCorrect: true, userAnswer: 'hello', confidenceLevel: 4, responseTimeMs: 2000 } const result = await store.recordTestResult(testParams) expect(result).toBe(true) expect(mockFlashcardsService.recordTestCompletion).toHaveBeenCalledWith(testParams) }) it('應該處理 API 失敗', async () => { mockFlashcardsService.recordTestCompletion.mockResolvedValue({ success: false, error: 'API錯誤' }) const store = useTestResultStore.getState() const result = await store.recordTestResult({ flashcardId: 'mock-1', testType: 'flip-memory', isCorrect: true }) expect(result).toBe(false) expect(store.recordingError).toBe('記錄測驗結果失敗') }) it('應該處理網路異常', async () => { mockFlashcardsService.recordTestCompletion.mockRejectedValue( new Error('Network error') ) const store = useTestResultStore.getState() const result = await store.recordTestResult({ flashcardId: 'mock-1', testType: 'flip-memory', isCorrect: true }) expect(result).toBe(false) expect(store.recordingError).toBe('記錄測驗結果異常') }) it('應該設置預設 responseTimeMs', async () => { mockFlashcardsService.recordTestCompletion.mockResolvedValue({ success: true }) const store = useTestResultStore.getState() await store.recordTestResult({ flashcardId: 'mock-1', testType: 'flip-memory', isCorrect: true }) expect(mockFlashcardsService.recordTestCompletion).toHaveBeenCalledWith( expect.objectContaining({ responseTimeMs: 2000 }) ) }) }) describe('統計方法', () => { beforeEach(() => { const store = useTestResultStore.getState() // 設置一些分數數據 store.updateScore(true) // 1/1 store.updateScore(true) // 2/2 store.updateScore(false) // 2/3 store.updateScore(true) // 3/4 }) it('getAccuracyPercentage 應該計算正確的準確率', () => { const store = useTestResultStore.getState() const accuracy = store.getAccuracyPercentage() expect(accuracy).toBe(75) // 3/4 = 75% }) it('getTotalAttempts 應該返回總嘗試次數', () => { const store = useTestResultStore.getState() const total = store.getTotalAttempts() expect(total).toBe(4) }) it('應該在無嘗試時返回 0%', () => { const store = useTestResultStore.getState() store.resetScore() expect(store.getAccuracyPercentage()).toBe(0) expect(store.getTotalAttempts()).toBe(0) }) }) describe('resetScore', () => { it('應該重置分數和錯誤狀態', () => { const store = useTestResultStore.getState() // 設置一些狀態 store.updateScore(true) store.setRecordingError('某個錯誤') // 重置 store.resetScore() expect(store.score).toEqual({ correct: 0, total: 0 }) expect(store.recordingError).toBe(null) }) }) })