tlc-claude-code 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,152 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import {
3
+ codeReviewSchema,
4
+ planReviewSchema,
5
+ validateReviewOutput,
6
+ parseMarkdownReview,
7
+ exportSchemas,
8
+ SEVERITY_LEVELS,
9
+ } from './review-schemas.js';
10
+
11
+ describe('review-schemas', () => {
12
+ describe('codeReviewSchema', () => {
13
+ it('validates correct code review output', () => {
14
+ const output = {
15
+ verdict: 'APPROVED',
16
+ score: 85,
17
+ summary: 'Clean implementation with good test coverage.',
18
+ issues: [],
19
+ };
20
+ const result = validateReviewOutput(output, codeReviewSchema);
21
+ expect(result.valid).toBe(true);
22
+ expect(result.errors).toHaveLength(0);
23
+ });
24
+
25
+ it('validates output with issues', () => {
26
+ const output = {
27
+ verdict: 'CHANGES_REQUESTED',
28
+ score: 40,
29
+ summary: 'Several issues found.',
30
+ issues: [
31
+ {
32
+ file: 'src/auth.js',
33
+ line: 42,
34
+ severity: 'high',
35
+ category: 'security',
36
+ message: 'Hardcoded password detected',
37
+ suggestion: 'Use environment variable instead',
38
+ },
39
+ ],
40
+ };
41
+ const result = validateReviewOutput(output, codeReviewSchema);
42
+ expect(result.valid).toBe(true);
43
+ });
44
+
45
+ it('rejects output missing verdict', () => {
46
+ const output = { score: 85, summary: 'Good.', issues: [] };
47
+ const result = validateReviewOutput(output, codeReviewSchema);
48
+ expect(result.valid).toBe(false);
49
+ expect(result.errors.some(e => e.includes('verdict'))).toBe(true);
50
+ });
51
+
52
+ it('rejects issue with invalid severity', () => {
53
+ const output = {
54
+ verdict: 'APPROVED',
55
+ score: 85,
56
+ summary: 'Good.',
57
+ issues: [
58
+ { file: 'a.js', line: 1, severity: 'extreme', category: 'bug', message: 'Bad', suggestion: 'Fix' },
59
+ ],
60
+ };
61
+ const result = validateReviewOutput(output, codeReviewSchema);
62
+ expect(result.valid).toBe(false);
63
+ expect(result.errors.some(e => e.includes('severity'))).toBe(true);
64
+ });
65
+
66
+ it('rejects issue without file field', () => {
67
+ const output = {
68
+ verdict: 'APPROVED',
69
+ score: 85,
70
+ summary: 'Good.',
71
+ issues: [
72
+ { line: 1, severity: 'low', category: 'style', message: 'Naming', suggestion: 'Rename' },
73
+ ],
74
+ };
75
+ const result = validateReviewOutput(output, codeReviewSchema);
76
+ expect(result.valid).toBe(false);
77
+ expect(result.errors.some(e => e.includes('file'))).toBe(true);
78
+ });
79
+ });
80
+
81
+ describe('planReviewSchema', () => {
82
+ it('validates correct plan review output', () => {
83
+ const output = {
84
+ verdict: 'APPROVED',
85
+ structureIssues: [],
86
+ scopeIssues: [],
87
+ suggestions: ['Consider adding error handling task'],
88
+ };
89
+ const result = validateReviewOutput(output, planReviewSchema);
90
+ expect(result.valid).toBe(true);
91
+ });
92
+
93
+ it('rejects plan review missing verdict', () => {
94
+ const output = { structureIssues: [], scopeIssues: [], suggestions: [] };
95
+ const result = validateReviewOutput(output, planReviewSchema);
96
+ expect(result.valid).toBe(false);
97
+ });
98
+ });
99
+
100
+ describe('SEVERITY_LEVELS', () => {
101
+ it('contains all four levels', () => {
102
+ expect(SEVERITY_LEVELS).toEqual(['critical', 'high', 'medium', 'low']);
103
+ });
104
+ });
105
+
106
+ describe('parseMarkdownReview', () => {
107
+ it('extracts APPROVED verdict', () => {
108
+ const text = '## Review\n\nLooks good!\n\nVerdict: APPROVED';
109
+ const result = parseMarkdownReview(text);
110
+ expect(result.verdict).toBe('APPROVED');
111
+ });
112
+
113
+ it('extracts CHANGES_REQUESTED verdict', () => {
114
+ const text = 'Issues found.\n\nVerdict: CHANGES_REQUESTED\n\n- Fix X\n- Fix Y';
115
+ const result = parseMarkdownReview(text);
116
+ expect(result.verdict).toBe('CHANGES_REQUESTED');
117
+ });
118
+
119
+ it('extracts issues from bullet points', () => {
120
+ const text = `Verdict: CHANGES_REQUESTED
121
+
122
+ Issues:
123
+ - src/auth.js:42 [high] Hardcoded password
124
+ - src/db.js:10 [medium] Missing error handling`;
125
+ const result = parseMarkdownReview(text);
126
+ expect(result.issues.length).toBeGreaterThanOrEqual(2);
127
+ expect(result.issues[0].file).toBe('src/auth.js');
128
+ });
129
+
130
+ it('returns UNKNOWN for ambiguous text', () => {
131
+ const text = 'Some random review text without a clear verdict.';
132
+ const result = parseMarkdownReview(text);
133
+ expect(result.verdict).toBe('UNKNOWN');
134
+ });
135
+ });
136
+
137
+ describe('exportSchemas', () => {
138
+ it('produces valid JSON Schema for code review', () => {
139
+ const schemas = exportSchemas();
140
+ expect(schemas.codeReview).toHaveProperty('$schema');
141
+ expect(schemas.codeReview).toHaveProperty('type', 'object');
142
+ expect(schemas.codeReview.required).toContain('verdict');
143
+ });
144
+
145
+ it('produces valid JSON Schema for plan review', () => {
146
+ const schemas = exportSchemas();
147
+ expect(schemas.planReview).toHaveProperty('$schema');
148
+ expect(schemas.planReview).toHaveProperty('type', 'object');
149
+ expect(schemas.planReview.required).toContain('verdict');
150
+ });
151
+ });
152
+ });