-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathjest-exception-reporter.mjs
More file actions
84 lines (76 loc) · 2.54 KB
/
Copy pathjest-exception-reporter.mjs
File metadata and controls
84 lines (76 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import fs from 'fs';
import path from 'path';
import { createLogger, format, transports } from 'winston';
export default class JestExceptionReporter {
constructor(globalConfig, options = {}) {
this._globalConfig = globalConfig;
this._options = options || {};
this.logFile = this._options.logFile || path.resolve(process.cwd(), 'frodo-lib-jest-exceptions.log');
try {
fs.mkdirSync(path.dirname(this.logFile), { recursive: true });
} catch (e) {
// ignore - best effort
}
this.logger = createLogger({
level: 'info',
format: format.combine(
format.timestamp(),
format.printf(({ timestamp, level, message, ...meta }) => {
const base = { timestamp, level, message };
// pretty-print JSON with 2-space indentation and ensure a trailing newline
return JSON.stringify(Object.assign(base, meta), null, 2) + '\n';
})
),
transports: [
new transports.File({ filename: this.logFile, handleExceptions: false })
],
exitOnError: false
});
}
onRunStart() {
this.logger.info('Jest exceptions log started');
}
onTestResult(test, testResult) {
if (!testResult) return;
const filePath = testResult.testFilePath || (test && test.path) || 'unknown';
(testResult.testResults || []).forEach(assertion => {
if (assertion.status === 'failed') {
// Prefer structured failure details if available (some runners include objects)
const details = assertion.failureDetails && assertion.failureDetails.length ? assertion.failureDetails : null;
if (details) {
details.forEach(detail => {
try {
if (detail && typeof detail === 'object') {
// Check name property
if (detail.name === 'FrodoError') {
detail = detail.toString();
}
}
} catch (e) {
// ignore
}
// Log what we found
this.logger.error('test-failure', {
file: filePath,
fullName: assertion.fullName,
ancestorTitles: assertion.ancestorTitles,
title: assertion.title,
detail
});
});
}
}
});
}
onRunComplete(contexts, results) {
try {
this.logger.info('Jest run completed', {
numTotalTests: results.numTotalTests,
numFailedTests: results.numFailedTests,
success: results.numFailedTests === 0
});
} catch (e) {
// ignore
}
}
}