@vibe-validate/extractors 0.12.1 → 0.13.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.
Files changed (44) hide show
  1. package/README.md +68 -9
  2. package/dist/ava-extractor.d.ts +24 -0
  3. package/dist/ava-extractor.d.ts.map +1 -0
  4. package/dist/ava-extractor.js +367 -0
  5. package/dist/ava-extractor.js.map +1 -0
  6. package/dist/index.d.ts +6 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +6 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/jasmine-extractor.d.ts +23 -0
  11. package/dist/jasmine-extractor.d.ts.map +1 -0
  12. package/dist/jasmine-extractor.js +254 -0
  13. package/dist/jasmine-extractor.js.map +1 -0
  14. package/dist/jest-extractor.d.ts +29 -0
  15. package/dist/jest-extractor.d.ts.map +1 -0
  16. package/dist/jest-extractor.js +115 -0
  17. package/dist/jest-extractor.js.map +1 -0
  18. package/dist/junit-extractor.d.ts +24 -0
  19. package/dist/junit-extractor.d.ts.map +1 -0
  20. package/dist/junit-extractor.js +264 -0
  21. package/dist/junit-extractor.js.map +1 -0
  22. package/dist/mocha-extractor.d.ts +23 -0
  23. package/dist/mocha-extractor.d.ts.map +1 -0
  24. package/dist/mocha-extractor.js +263 -0
  25. package/dist/mocha-extractor.js.map +1 -0
  26. package/dist/playwright-extractor.d.ts +38 -0
  27. package/dist/playwright-extractor.d.ts.map +1 -0
  28. package/dist/playwright-extractor.js +230 -0
  29. package/dist/playwright-extractor.js.map +1 -0
  30. package/dist/smart-extractor.d.ts +9 -0
  31. package/dist/smart-extractor.d.ts.map +1 -1
  32. package/dist/smart-extractor.js +25 -0
  33. package/dist/smart-extractor.js.map +1 -1
  34. package/dist/tap-extractor.d.ts +24 -0
  35. package/dist/tap-extractor.d.ts.map +1 -0
  36. package/dist/tap-extractor.js +227 -0
  37. package/dist/tap-extractor.js.map +1 -0
  38. package/dist/types.d.ts +21 -2
  39. package/dist/types.d.ts.map +1 -1
  40. package/dist/vitest-extractor.d.ts +9 -1
  41. package/dist/vitest-extractor.d.ts.map +1 -1
  42. package/dist/vitest-extractor.js +112 -16
  43. package/dist/vitest-extractor.js.map +1 -1
  44. package/package.json +3 -5
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Jasmine Error Extractor
3
+ *
4
+ * Parses Jasmine test output and formats failures for LLM consumption.
5
+ *
6
+ * @package @vibe-validate/extractors
7
+ */
8
+ import { stripAnsiCodes } from './utils.js';
9
+ /**
10
+ * Extract errors from Jasmine test output
11
+ *
12
+ * @param output - Jasmine text output
13
+ * @returns Structured error information
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const jasmineOutput = execSync('jasmine tests/**\/*.spec.js', { encoding: 'utf-8' });
18
+ * const result = extractJasmineErrors(jasmineOutput);
19
+ * console.log(result.summary); // "5 test(s) failed"
20
+ * ```
21
+ */
22
+ export function extractJasmineErrors(output) {
23
+ const cleanOutput = stripAnsiCodes(output);
24
+ // Check if this looks like Jasmine output
25
+ if (!cleanOutput.includes('spec') && !cleanOutput.includes('Failures:')) {
26
+ return {
27
+ summary: 'Unable to parse Jasmine output - invalid format',
28
+ errors: [],
29
+ totalCount: 0,
30
+ cleanOutput: cleanOutput.trim(),
31
+ guidance: 'Ensure the input is valid Jasmine test output',
32
+ metadata: {
33
+ confidence: 0,
34
+ completeness: 0,
35
+ issues: ['Not Jasmine output format']
36
+ }
37
+ };
38
+ }
39
+ // Extract failure count
40
+ const failureMatch = cleanOutput.match(/(\d+) spec(?:s)?, (\d+) failure(?:s)?/);
41
+ const failureCount = failureMatch ? parseInt(failureMatch[2], 10) : 0;
42
+ if (failureCount === 0) {
43
+ return {
44
+ summary: '0 test(s) failed',
45
+ errors: [],
46
+ totalCount: 0,
47
+ cleanOutput: '',
48
+ guidance: '',
49
+ metadata: {
50
+ confidence: 100,
51
+ completeness: 100,
52
+ issues: []
53
+ }
54
+ };
55
+ }
56
+ // Extract all failures
57
+ const failures = extractFailures(cleanOutput);
58
+ const errors = [];
59
+ let completeCount = 0;
60
+ for (const failure of failures) {
61
+ const file = failure.file || 'unknown';
62
+ const message = failure.message || 'Test failed';
63
+ const context = failure.testName || '';
64
+ const isComplete = file !== 'unknown' && failure.line && message;
65
+ if (isComplete) {
66
+ completeCount++;
67
+ }
68
+ errors.push({
69
+ file,
70
+ line: failure.line,
71
+ message,
72
+ context
73
+ });
74
+ }
75
+ // Generate summary
76
+ const summary = `${failures.length} test(s) failed`;
77
+ // Generate guidance
78
+ const guidance = generateGuidance(failures);
79
+ // Calculate quality metadata
80
+ const completeness = failures.length > 0 ? (completeCount / failures.length) * 100 : 100;
81
+ const confidence = failures.length > 0 ? 95 : 100; // High confidence for Jasmine
82
+ const metadata = {
83
+ confidence,
84
+ completeness,
85
+ issues: []
86
+ };
87
+ return {
88
+ summary,
89
+ errors,
90
+ totalCount: failures.length,
91
+ cleanOutput: formatCleanOutput(errors),
92
+ guidance,
93
+ metadata
94
+ };
95
+ }
96
+ /**
97
+ * Extract failure information from Jasmine output
98
+ */
99
+ function extractFailures(output) {
100
+ const failures = [];
101
+ const lines = output.split('\n');
102
+ let i = 0;
103
+ while (i < lines.length) {
104
+ const line = lines[i];
105
+ // Look for numbered failure markers (e.g., "1) Test name")
106
+ const failureMatch = line.match(/^(\d+)\)\s+(.+)$/);
107
+ if (failureMatch) {
108
+ const _failureNumber = failureMatch[1]; // Extracted but not used (line number extracted from stack trace instead)
109
+ const testName = failureMatch[2].trim();
110
+ let j = i + 1;
111
+ let message;
112
+ let errorType;
113
+ let file;
114
+ let lineNumber;
115
+ // Scan for Message: and Stack: sections
116
+ while (j < lines.length && j < i + 30) {
117
+ const nextLine = lines[j];
118
+ // Stop if we hit the next failure
119
+ if (nextLine.match(/^\d+\)\s+/)) {
120
+ break;
121
+ }
122
+ // Extract message (comes after " Message:" line)
123
+ if (nextLine.trim() === 'Message:') {
124
+ j++;
125
+ // Collect message lines until we hit "Stack:" or empty line
126
+ const messageLines = [];
127
+ while (j < lines.length) {
128
+ const msgLine = lines[j];
129
+ if (msgLine.trim() === 'Stack:' || msgLine.trim() === '') {
130
+ break;
131
+ }
132
+ messageLines.push(msgLine.trim());
133
+ j++;
134
+ }
135
+ message = messageLines.join(' ').trim();
136
+ // Extract error type if present (e.g., "TypeError:", "Error:")
137
+ const errorMatch = message.match(/^([A-Za-z]*Error):\s*/);
138
+ if (errorMatch) {
139
+ errorType = errorMatch[1];
140
+ }
141
+ continue;
142
+ }
143
+ // Extract file location from stack trace
144
+ if (nextLine.trim() === 'Stack:') {
145
+ j++;
146
+ // Scan stack trace for file location
147
+ while (j < lines.length && j < i + 40) {
148
+ const stackLine = lines[j];
149
+ // Stop if we hit the next failure or empty section
150
+ if (stackLine.match(/^\d+\)\s+/) || (stackLine.trim() === '' && lines[j + 1]?.match(/^\d+\)\s+/))) {
151
+ break;
152
+ }
153
+ // Extract file from UserContext.<anonymous> stack lines
154
+ if (stackLine.includes('UserContext.<anonymous>')) {
155
+ const locationMatch = stackLine.match(/UserContext\.<anonymous> \(([^:)]+):(\d+)(?::(\d+))?\)/);
156
+ if (locationMatch) {
157
+ file = locationMatch[1];
158
+ lineNumber = parseInt(locationMatch[2], 10);
159
+ break;
160
+ }
161
+ }
162
+ // Also try Object.* patterns
163
+ if (!file && stackLine.includes(' (') && stackLine.includes('.js:')) {
164
+ const altMatch = stackLine.match(/\(([^:)]+):(\d+)(?::(\d+))?\)/);
165
+ if (altMatch) {
166
+ file = altMatch[1];
167
+ lineNumber = parseInt(altMatch[2], 10);
168
+ break;
169
+ }
170
+ }
171
+ j++;
172
+ }
173
+ continue;
174
+ }
175
+ j++;
176
+ }
177
+ failures.push({
178
+ testName,
179
+ message,
180
+ errorType,
181
+ file,
182
+ line: lineNumber
183
+ });
184
+ i = j; // Skip to after this failure
185
+ }
186
+ else {
187
+ i++;
188
+ }
189
+ }
190
+ return failures;
191
+ }
192
+ /**
193
+ * Generate guidance based on failure types
194
+ */
195
+ function generateGuidance(failures) {
196
+ const guidances = [];
197
+ const seen = new Set();
198
+ for (const failure of failures) {
199
+ const message = failure.message || '';
200
+ const errorType = failure.errorType;
201
+ // Assertion errors
202
+ if (message.includes('Expected') || message.includes('expected')) {
203
+ if (!seen.has('assertion')) {
204
+ guidances.push('Review test assertions and expected values');
205
+ seen.add('assertion');
206
+ }
207
+ }
208
+ // Timeout errors
209
+ if (message.includes('Timeout') || message.includes('timeout') || message.includes('did not complete')) {
210
+ if (!seen.has('timeout')) {
211
+ guidances.push('Increase test timeout or optimize async operations');
212
+ seen.add('timeout');
213
+ }
214
+ }
215
+ // Type errors
216
+ if (errorType === 'TypeError' || message.includes('Cannot read properties')) {
217
+ if (!seen.has('type')) {
218
+ guidances.push('Check for null/undefined values and type mismatches');
219
+ seen.add('type');
220
+ }
221
+ }
222
+ // File errors
223
+ if (message.includes('ENOENT') || message.includes('no such file')) {
224
+ if (!seen.has('file')) {
225
+ guidances.push('Verify file paths and ensure test fixtures exist');
226
+ seen.add('file');
227
+ }
228
+ }
229
+ // Module errors
230
+ if (message.includes('Cannot find module') || message.includes('Cannot find package')) {
231
+ if (!seen.has('module')) {
232
+ guidances.push('Install missing dependencies or check import paths');
233
+ seen.add('module');
234
+ }
235
+ }
236
+ }
237
+ return guidances.join('\n');
238
+ }
239
+ /**
240
+ * Format clean output for LLM consumption
241
+ */
242
+ function formatCleanOutput(errors) {
243
+ if (errors.length === 0) {
244
+ return '';
245
+ }
246
+ return errors
247
+ .map((error) => {
248
+ const location = error.line ? `${error.file}:${error.line}` : error.file;
249
+ const contextStr = error.context ? ` (${error.context})` : '';
250
+ return `${location}: ${error.message}${contextStr}`;
251
+ })
252
+ .join('\n');
253
+ }
254
+ //# sourceMappingURL=jasmine-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jasmine-extractor.js","sourceRoot":"","sources":["../src/jasmine-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Jest Error Extractor
3
+ *
4
+ * Parses and formats Jest test failure output for LLM consumption.
5
+ *
6
+ * @package @vibe-validate/extractors
7
+ */
8
+ import type { ErrorExtractorResult } from './types.js';
9
+ /**
10
+ * Extract Jest test failures
11
+ *
12
+ * Parses Jest output format:
13
+ * - FAIL test/file.test.ts
14
+ * - ● Test Suite › test name
15
+ * - Error message
16
+ * - at file:line:col
17
+ *
18
+ * @param output - Raw Jest command output
19
+ * @returns Structured error information with test-specific guidance
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const result = extractJestErrors(jestOutput);
24
+ * console.log(result.summary); // "3 test failure(s)"
25
+ * console.log(result.guidance); // "Fix each failing test individually..."
26
+ * ```
27
+ */
28
+ export declare function extractJestErrors(output: string): ErrorExtractorResult;
29
+ //# sourceMappingURL=jest-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jest-extractor.d.ts","sourceRoot":"","sources":["../src/jest-extractor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAUvD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,oBAAoB,CAmGtE"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Jest Error Extractor
3
+ *
4
+ * Parses and formats Jest test failure output for LLM consumption.
5
+ *
6
+ * @package @vibe-validate/extractors
7
+ */
8
+ import { stripAnsiCodes } from './utils.js';
9
+ /**
10
+ * Extract Jest test failures
11
+ *
12
+ * Parses Jest output format:
13
+ * - FAIL test/file.test.ts
14
+ * - ● Test Suite › test name
15
+ * - Error message
16
+ * - at file:line:col
17
+ *
18
+ * @param output - Raw Jest command output
19
+ * @returns Structured error information with test-specific guidance
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const result = extractJestErrors(jestOutput);
24
+ * console.log(result.summary); // "3 test failure(s)"
25
+ * console.log(result.guidance); // "Fix each failing test individually..."
26
+ * ```
27
+ */
28
+ export function extractJestErrors(output) {
29
+ const cleanOutput = stripAnsiCodes(output);
30
+ const lines = cleanOutput.split('\n');
31
+ const failures = [];
32
+ let currentFile = '';
33
+ let currentTest = null;
34
+ let currentError = null;
35
+ for (let i = 0; i < lines.length; i++) {
36
+ const line = lines[i];
37
+ // Match: FAIL test/integration/extraction-with-mocks.test.ts
38
+ // OR: FAIL project-name tests/jest/calculator.test.ts
39
+ const failMatch = line.match(/^FAIL\s+(?:[\w-]+\s+)?([\w/-]+\.test\.\w+)/);
40
+ if (failMatch) {
41
+ currentFile = failMatch[1];
42
+ continue;
43
+ }
44
+ // Match: ● TestSuite › Sub Suite › test name
45
+ const testMatch = line.match(/^\s*●\s+(.+)$/);
46
+ if (testMatch && currentFile) {
47
+ // Save previous test if we have one
48
+ if (currentTest && currentError) {
49
+ failures.push({
50
+ file: currentFile,
51
+ location: currentFile, // Jest doesn't always show line numbers in error section
52
+ testHierarchy: currentTest,
53
+ errorMessage: currentError.trim()
54
+ });
55
+ }
56
+ currentTest = testMatch[1].trim();
57
+ currentError = null;
58
+ continue;
59
+ }
60
+ // Extract error message (first non-empty line after test name, before source code)
61
+ if (currentTest && !currentError && line.trim() && !line.includes('|')) {
62
+ // Skip empty lines and source code lines (contain |)
63
+ // Look for plain error message
64
+ if (!line.match(/^\s*at\s/) && !line.match(/^\s*\d+\s*\|/)) {
65
+ currentError = line.trim();
66
+ }
67
+ }
68
+ // Extract location from stack trace: at ... (file:line:col)
69
+ const locationMatch = line.match(/at\s+.+?\((.+?):(\d+):(\d+)\)/);
70
+ if (locationMatch && currentTest && failures.length > 0) {
71
+ const lastFailure = failures[failures.length - 1];
72
+ if (lastFailure.testHierarchy === currentTest) {
73
+ lastFailure.location = `${locationMatch[1]}:${locationMatch[2]}:${locationMatch[3]}`;
74
+ }
75
+ }
76
+ }
77
+ // Save last test
78
+ if (currentTest && currentError) {
79
+ failures.push({
80
+ file: currentFile || 'unknown',
81
+ location: currentFile || 'unknown',
82
+ testHierarchy: currentTest,
83
+ errorMessage: currentError.trim()
84
+ });
85
+ }
86
+ // Build formatted errors
87
+ const errors = failures.map(f => ({
88
+ file: f.file,
89
+ line: parseInt(f.location.split(':')[1] || '0'),
90
+ column: parseInt(f.location.split(':')[2] || '0'),
91
+ message: `${f.testHierarchy}: ${f.errorMessage}`,
92
+ severity: 'error'
93
+ }));
94
+ const summary = failures.length > 0
95
+ ? `${failures.length} test failure(s)`
96
+ : 'No test failures detected';
97
+ const guidance = failures.length > 0
98
+ ? 'Fix each failing test individually. Check test setup, mocks, and assertions.'
99
+ : '';
100
+ const cleanOutputLines = [];
101
+ for (const failure of failures) {
102
+ cleanOutputLines.push(`● ${failure.testHierarchy}`);
103
+ cleanOutputLines.push(` ${failure.errorMessage}`);
104
+ cleanOutputLines.push(` Location: ${failure.location}`);
105
+ cleanOutputLines.push('');
106
+ }
107
+ return {
108
+ errors,
109
+ summary,
110
+ totalCount: failures.length,
111
+ guidance,
112
+ cleanOutput: cleanOutputLines.join('\n')
113
+ };
114
+ }
115
+ //# sourceMappingURL=jest-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jest-extractor.js","sourceRoot":"","sources":["../src/jest-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * JUnit XML Error Extractor
3
+ *
4
+ * Parses JUnit XML test reports and formats failures for LLM consumption.
5
+ * Supports Vitest, Jest, and other test frameworks that output JUnit XML.
6
+ *
7
+ * @package @vibe-validate/extractors
8
+ */
9
+ import type { ErrorExtractorResult } from './types.js';
10
+ /**
11
+ * Extract errors from JUnit XML test output
12
+ *
13
+ * @param output - JUnit XML string
14
+ * @returns Structured error information
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const junitXml = fs.readFileSync('junit.xml', 'utf-8');
19
+ * const result = extractJUnitErrors(junitXml);
20
+ * console.log(result.summary); // "5 test(s) failed"
21
+ * ```
22
+ */
23
+ export declare function extractJUnitErrors(output: string): ErrorExtractorResult;
24
+ //# sourceMappingURL=junit-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"junit-extractor.d.ts","sourceRoot":"","sources":["../src/junit-extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAsC,MAAM,YAAY,CAAC;AAG3F;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,oBAAoB,CA+FvE"}