-
Notifications
You must be signed in to change notification settings - Fork 242
/
BroadcastReporter.ts
105 lines (90 loc) · 3.58 KB
/
BroadcastReporter.ts
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { Reporter, SourceFile, MutantResult, MatchedMutant, ScoreResult } from 'stryker-api/report';
import { Logger } from 'stryker-api/logging';
import { isPromise } from '../utils/objectUtils';
import StrictReporter from './StrictReporter';
import { commonTokens, PluginKind } from 'stryker-api/plugin';
import { StrykerOptions } from 'stryker-api/core';
import { tokens } from 'typed-inject';
import { coreTokens } from '../di';
import { PluginCreator } from '../di/PluginCreator';
export default class BroadcastReporter implements StrictReporter {
public static readonly inject = tokens(
commonTokens.options,
coreTokens.pluginCreatorReporter,
commonTokens.logger);
public readonly reporters: {
[name: string]: Reporter;
};
constructor(
private readonly options: StrykerOptions,
private readonly pluginCreator: PluginCreator<PluginKind.Reporter>,
private readonly log: Logger) {
this.reporters = {};
this.options.reporters.forEach(reporterName => this.createReporter(reporterName));
this.logAboutReporters();
}
private createReporter(reporterName: string): void {
if (reporterName === 'progress' && !process.stdout.isTTY) {
this.log.info(
'Detected that current console does not support the "progress" reporter, downgrading to "progress-append-only" reporter'
);
reporterName = 'progress-append-only';
}
this.reporters[reporterName] = this.pluginCreator.create(reporterName);
}
private logAboutReporters(): void {
const reporterNames = Object.keys(this.reporters);
if (reporterNames.length) {
if (this.log.isDebugEnabled()) {
this.log.debug(`Broadcasting to reporters ${JSON.stringify(reporterNames)}`);
}
} else {
this.log.warn('No reporter configured. Please configure one or more reporters in the (for example: reporters: [\'progress\'])');
}
}
private broadcast(methodName: keyof Reporter, eventArgs: any): Promise<any> | void {
const allPromises: Promise<void>[] = [];
Object.keys(this.reporters).forEach(reporterName => {
const reporter = this.reporters[reporterName];
if (typeof reporter[methodName] === 'function') {
try {
const maybePromise = (reporter[methodName] as any)(eventArgs);
if (isPromise(maybePromise)) {
allPromises.push(maybePromise.catch(error => {
this.handleError(error, methodName, reporterName);
}));
}
} catch (error) {
this.handleError(error, methodName, reporterName);
}
}
});
if (allPromises.length) {
return Promise.all(allPromises);
}
}
public onSourceFileRead(file: SourceFile): void {
this.broadcast('onSourceFileRead', file);
}
public onAllSourceFilesRead(files: SourceFile[]): void {
this.broadcast('onAllSourceFilesRead', files);
}
public onAllMutantsMatchedWithTests(results: ReadonlyArray<MatchedMutant>): void {
this.broadcast('onAllMutantsMatchedWithTests', results);
}
public onMutantTested(result: MutantResult): void {
this.broadcast('onMutantTested', result);
}
public onAllMutantsTested(results: MutantResult[]): void {
this.broadcast('onAllMutantsTested', results);
}
public onScoreCalculated(score: ScoreResult): void {
this.broadcast('onScoreCalculated', score);
}
public async wrapUp(): Promise<void> {
await this.broadcast('wrapUp', undefined);
}
private handleError(error: Error, methodName: string, reporterName: string) {
this.log.error(`An error occurred during '${methodName}' on reporter '${reporterName}'. Error is: ${error}`);
}
}