@travetto/test
Version:
Declarative test framework
92 lines (83 loc) • 2.68 kB
text/typescript
import { existsSync } from 'node:fs';
import { type Class, RuntimeIndex } from '@travetto/runtime';
import type { TestConsumerShape } from '../types';
import type { TestEvent } from '../../model/event';
import type { TestResult } from '../../model/test';
import type { SuiteResult } from '../../model/suite';
import { SuiteRegistry } from '../../registry/suite';
import { DelegatingConsumer } from './delegating';
/**
* Cumulative Summary consumer
*/
export class CumulativeSummaryConsumer extends DelegatingConsumer {
/**
* Total state of all tests run so far
*/
#state: Record<string, Record<string, TestResult['status']>> = {};
constructor(target: TestConsumerShape) {
super([target]);
}
/**
* Summarize a given test suite using the new result and the historical
* state
*/
summarizeSuite(test: TestResult): SuiteResult {
// Was only loading to verify existence (TODO: double-check)
if (existsSync(RuntimeIndex.getFromImport(test.import)!.sourceFile)) {
(this.#state[test.classId] ??= {})[test.methodName] = test.status;
const SuiteCls = SuiteRegistry.getClasses().find(x => x.Ⲑid === test.classId);
return SuiteCls ? this.computeTotal(SuiteCls) : this.removeClass(test.classId);
} else {
return this.removeClass(test.classId);
}
}
/**
* Remove a class
*/
removeClass(clsId: string): SuiteResult {
this.#state[clsId] = {};
return {
classId: clsId, passed: 0, failed: 0, skipped: 0, total: 0, tests: [], duration: 0, import: '', lineStart: 0, lineEnd: 0
};
}
/**
* Compute totals
*/
computeTotal(cls: Class): SuiteResult {
const suite = SuiteRegistry.get(cls);
const total = suite.tests.reduce((acc, x) => {
const status = this.#state[x.classId][x.methodName] ?? 'unknown';
acc[status] += 1;
return acc;
}, { skipped: 0, passed: 0, failed: 0, unknown: 0 });
return {
classId: suite.classId,
passed: total.passed,
failed: total.failed,
skipped: total.skipped,
import: suite.import,
lineStart: suite.lineStart,
lineEnd: suite.lineEnd,
total: total.failed + total.passed,
tests: [],
duration: 0
};
}
/**
* Listen for event, process the full event, and if the event is an after test,
* send a full suite summary
*/
onEventDone(e: TestEvent): void {
try {
if (e.type === 'test' && e.phase === 'after') {
this.onEvent({
type: 'suite',
phase: 'after',
suite: this.summarizeSuite(e.test),
});
}
} catch (err) {
console.warn('Summarization Error', { error: err });
}
}
}