import { describe, it, expect } from 'vitest' import { ReportAnalyzer } from '../../src/main/services/report/report-analyzer' describe('ReportAnalyzer', () => { const analyzer = new ReportAnalyzer() describe('parseMarkdownReport', () => { it('should parse standard report with all fields', () => { const content = `## 执行摘要 | **操作用户** | \`admin\` | | **处理订单数** | \`150\` | | **删除物料数** | \`45\` | | **跳过物料数** | \`30\` | | **错误数量** | \`2\` | | **重试订单数** | \`10\` | | **成功重试数** | \`8\` | | **执行耗时** | \`2 分 30 秒\` | | **执行时间** | \`2026-03-25 08:30:45\` | ` const result = analyzer.parseMarkdownReport(content) expect(result).not.toBeNull() expect(result!.date).toBe('2026-03-25') expect(result!.username).toBe('admin') expect(result!.ordersProcessed).toBe(150) expect(result!.materialsDeleted).toBe(45) expect(result!.materialsSkipped).toBe(30) expect(result!.errorCount).toBe(2) expect(result!.retriedOrders).toBe(10) expect(result!.successfulRetries).toBe(8) expect(result!.durationSeconds).toBe(150) }) it('should use defaults for missing fields', () => { const content = `## 执行摘要 | **操作用户** | \`user1\` | | **处理订单数** | \`50\` | ` const result = analyzer.parseMarkdownReport(content) expect(result).not.toBeNull() expect(result!.username).toBe('user1') expect(result!.ordersProcessed).toBe(50) expect(result!.materialsDeleted).toBe(0) expect(result!.materialsSkipped).toBe(0) expect(result!.errorCount).toBe(0) expect(result!.retriedOrders).toBe(0) expect(result!.successfulRetries).toBe(0) expect(result!.durationSeconds).toBe(0) }) it('should return null for malformed format', () => { const content = `This is not a valid report format Just some random text without proper structure No execution summary section here` const result = analyzer.parseMarkdownReport(content) expect(result).toBeNull() }) it('should return null for empty content', () => { expect(analyzer.parseMarkdownReport('')).toBeNull() expect(analyzer.parseMarkdownReport(' ')).toBeNull() }) it('should handle special characters in fields', () => { const content = `## 执行摘要 | **操作用户** | \`admin@test.com\` | | **处理订单数** | \`100\` | | **删除物料数** | \`25\` | | **跳过物料数** | \`10\` | | **错误数量** | \`0\` | | **重试订单数** | \`5\` | | **成功重试数** | \`5\` | | **执行耗时** | \`1 分\` | | **执行时间** | \`2026-03-25 10:00:00\` | ` const result = analyzer.parseMarkdownReport(content) expect(result).not.toBeNull() expect(result!.username).toBe('admin@test.com') expect(result!.durationSeconds).toBe(60) }) it('should extract date from content when execution time missing', () => { const content = `## 执行摘要 | **操作用户** | \`test\` | | **处理订单数** | \`20\` | | **删除物料数** | \`5\` | | **跳过物料数** | \`2\` | | **错误数量** | \`0\` | | **重试订单数** | \`0\` | | **成功重试数** | \`0\` | | **执行耗时** | \`30 秒\` | ` const result = analyzer.parseMarkdownReport(content) expect(result).not.toBeNull() expect(result!.date).toMatch(/^\d{4}-\d{2}-\d{2}$/) }) it('should handle various duration formats', () => { // Test "2 分 30 秒" const content1 = `## 执行摘要 | **操作用户** | \`test\` | | **处理订单数** | \`10\` | | **删除物料数** | \`5\` | | **跳过物料数** | \`2\` | | **错误数量** | \`0\` | | **重试订单数** | \`0\` | | **成功重试数** | \`0\` | | **执行耗时** | \`2 分 30 秒\` | | **执行时间** | \`2026-03-25 10:00:00\` | ` const result1 = analyzer.parseMarkdownReport(content1) expect(result1!.durationSeconds).toBe(150) // Test "1 分" const content2 = `## 执行摘要 | **操作用户** | \`test\` | | **处理订单数** | \`10\` | | **删除物料数** | \`5\` | | **跳过物料数** | \`2\` | | **错误数量** | \`0\` | | **重试订单数** | \`0\` | | **成功重试数** | \`0\` | | **执行耗时** | \`1 分\` | | **执行时间** | \`2026-03-25 10:00:00\` | ` const result2 = analyzer.parseMarkdownReport(content2) expect(result2!.durationSeconds).toBe(60) // Test "30 秒" - use different time to avoid confusion const content3 = `## 执行摘要 | **操作用户** | \`test\` | | **处理订单数** | \`10\` | | **删除物料数** | \`5\` | | **跳过物料数** | \`2\` | | **错误数量** | \`0\` | | **重试订单数** | \`0\` | | **成功重试数** | \`0\` | | **执行耗时** | \`30 秒\` | | **执行时间** | \`2026-03-25 14:20:15\` | ` const result3 = analyzer.parseMarkdownReport(content3) console.log( 'Duration test - extracted duration:', result3?.durationSeconds, 'content:', content3 ) expect(result3!.durationSeconds).toBe(30) }) }) describe('analyzeReports', () => { it('should batch process multiple reports', () => { const reports = [ { content: `## 执行摘要 | **操作用户** | \`user1\` | | **处理订单数** | \`100\` | | **删除物料数** | \`20\` | | **跳过物料数** | \`10\` | | **错误数量** | \`1\` | | **重试订单数** | \`5\` | | **成功重试数** | \`4\` | | **执行耗时** | \`1 分\` | | **执行时间** | \`2026-03-25 08:00:00\` | `, filename: 'report-2026-03-25.md' }, { content: `## 执行摘要 | **操作用户** | \`user2\` | | **处理订单数** | \`200\` | | **删除物料数** | \`50\` | | **跳过物料数** | \`20\` | | **错误数量** | \`2\` | | **重试订单数** | \`10\` | | **成功重试数** | \`8\` | | **执行耗时** | \`2 分\` | | **执行时间** | \`2026-03-26 09:00:00\` | `, filename: 'report-2026-03-26.md' } ] const results = analyzer.analyzeReports(reports) expect(results.length).toBe(2) expect(results[0].username).toBe('user1') expect(results[0].date).toBe('2026-03-25') expect(results[1].username).toBe('user2') expect(results[1].date).toBe('2026-03-26') }) it('should skip invalid reports in batch', () => { const reports = [ { content: `## 执行摘要 | **操作用户** | \`valid\` | | **处理订单数** | \`50\` | | **删除物料数** | \`10\` | | **跳过物料数** | \`5\` | | **错误数量** | \`0\` | | **重试订单数** | \`0\` | | **成功重试数** | \`0\` | | **执行耗时** | \`30 秒\` | | **执行时间** | \`2026-03-25 10:00:00\` | `, filename: 'valid-report.md' }, { content: 'Invalid report content', filename: 'invalid-report.md' } ] const results = analyzer.analyzeReports(reports) expect(results.length).toBe(1) expect(results[0].username).toBe('valid') }) it('should use filename date to override content date', () => { const reports = [ { content: `## 执行摘要 | **操作用户** | \`test\` | | **处理订单数** | \`30\` | | **删除物料数** | \`5\` | | **跳过物料数** | \`2\` | | **错误数量** | \`0\` | | **重试订单数** | \`0\` | | **成功重试数** | \`0\` | | **执行耗时** | \`20 秒\` | | **执行时间** | \`2026-03-20 10:00:00\` | `, filename: 'report-2026-03-25-08-30-45.md' } ] const results = analyzer.analyzeReports(reports) expect(results.length).toBe(1) expect(results[0].date).toBe('2026-03-25') }) }) describe('date extraction', () => { it('should extract date from filename with ISO format', () => { const content = `## 执行摘要 | **操作用户** | \`test\` | | **处理订单数** | \`10\` | | **删除物料数** | \`5\` | | **跳过物料数** | \`2\` | | **错误数量** | \`0\` | | **重试订单数** | \`0\` | | **成功重试数** | \`0\` | | **执行耗时** | \`10 秒\` | | **执行时间** | \`2026-03-20 10:00:00\` | ` const report = { content, filename: 'cleaner-report-2026-03-25-08-30-45.md' } const results = analyzer.analyzeReports([report]) expect(results[0].date).toBe('2026-03-25') }) it('should extract date from filename with YYYYMMDD format', () => { const content = `## 执行摘要 | **操作用户** | \`test\` | | **处理订单数** | \`10\` | | **删除物料数** | \`5\` | | **跳过物料数** | \`2\` | | **错误数量** | \`0\` | | **重试订单数** | \`0\` | | **成功重试数** | \`0\` | | **执行耗时** | \`10 秒\` | | **执行时间** | \`2026-03-20 10:00:00\` | ` const report = { content, filename: 'report-20260325-100000.md' } const results = analyzer.analyzeReports([report]) expect(results[0].date).toBe('2026-03-25') }) }) })