UNPKG

@90poe/jest-performant-warnings-stats-reporter

Version:

A flexible jest reporter that provides ability to show statistics of warnings and group them

218 lines (176 loc) 5.91 kB
import { Context, Test } from '@jest/reporters'; import { AggregatedResult, TestResult } from '@jest/test-result'; import { Config } from '@jest/types'; import { bold, green, red } from 'chalk'; import { table } from 'table'; import { DEFAULT_MAX_SLOW_TESTS, DEFAULT_SHOW_SLOWEST, DEFAULT_SHOW_WARNING_SUMMARY, DEFAULT_TEST_DURATION, DEFAULT_WARN_ON_SLOWER_THAN, DEFAULT_WARNINGS_CONFIG, TABLE_HEADER_WITH_WARNINGS_DATA, TABLE_HEADER_WITHOUT_WARNINGS_DATA, } from './constants'; import { recursiveLogger } from './recursiveLogger'; import { CustomLogEntry, IJestReporterConfig, LogsObj, SlowTest, Warning, } from './types'; import { addFilesSetToWarningConfig, getFileName, log, omitWarningsData, prepareGreetingMessage, prepareTableRow, prepareWarnings, } from './utils'; class CustomReporter { private showWarningSummary: boolean; private warningsConfig: Array<Warning>; private maxSlowTests: number; private globalConfig: Config.InitialOptions; private logs: LogsObj; private showSlowest: boolean; private slowTests: Array<SlowTest>; private finalTable: Array<Array<string | number>>; private warnOnSlowerThan: number; constructor( public globalConfiguration: Config.InitialOptions, private options: IJestReporterConfig, ) { this.globalConfig = globalConfiguration; this.showWarningSummary = options.showWarningSummary ?? DEFAULT_SHOW_WARNING_SUMMARY; this.warningsConfig = options.warningsConfig?.map(addFilesSetToWarningConfig) ?? DEFAULT_WARNINGS_CONFIG; this.maxSlowTests = options.maxSlowTests ?? DEFAULT_MAX_SLOW_TESTS; this.logs = {}; this.showSlowest = options.showSlowest ?? DEFAULT_SHOW_SLOWEST; this.slowTests = []; this.warnOnSlowerThan = options.warnOnSlowerThan ?? DEFAULT_WARN_ON_SLOWER_THAN; this.finalTable = omitWarningsData(globalConfiguration) ? [TABLE_HEADER_WITHOUT_WARNINGS_DATA] : [TABLE_HEADER_WITH_WARNINGS_DATA]; } onRunStart({ numTotalTestSuites }: AggregatedResult): void { const greetingMessage = prepareGreetingMessage(numTotalTestSuites); console.log(greetingMessage); } onTestResult(_: Test, testResult: TestResult): void { const fileName = getFileName(testResult.testFilePath); const warningsPerTest: Record<string, number> = {}; const tableRow = prepareTableRow( testResult, this.warnOnSlowerThan, this.globalConfig, ); this.logs[fileName] = { filePath: testResult.testFilePath, warnings: [], }; this.finalTable.push(tableRow); if (testResult.console) { testResult.console.forEach((value) => { let isOther = true; this.warningsConfig.forEach(({ regex, name }) => { if (regex.test(value.message)) { warningsPerTest[name] = warningsPerTest[name] + 1 || 1; isOther = false; } }); if (isOther) { warningsPerTest.Other = warningsPerTest.Other + 1 || 1; } this.logs[fileName].warnings.push(value); }); } if (this.showSlowest) { this.collectSlowTests(testResult); } if (this.showWarningSummary && !this.globalConfig.verbose) { const warningsInfo = prepareWarnings(warningsPerTest); this.finalTable.push(...warningsInfo); } } onRunComplete( _: Set<Context>, { numFailedTests, numPassedTests, testResults }: AggregatedResult, ): void { testResults.forEach( ({ testFilePath, testResults: innerTestResults, failureMessage }) => { recursiveLogger(testFilePath, innerTestResults, 0, 0); if (failureMessage) { console.log(failureMessage); } }, ); if (numPassedTests !== 0) { console.log(green(`${numPassedTests} passed`)); } if (numFailedTests !== 0) { console.log(bold(red(`${numFailedTests} failed`))); } if (this.globalConfig.verbose || this.globalConfig.watch) { Object.entries(this.logs).forEach(([filename, data]) => { const { warnings } = data; if (warnings.length) { console.log(bold(filename)); } (warnings as CustomLogEntry[]).forEach(log); }); } const shouldShowTable = this.finalTable.length > 1; if (shouldShowTable) { console.log(table(this.finalTable)); } if ( this.showSlowest && !this.globalConfig.watch && !this.globalConfig.watchAll ) { this.consoleSlowTests(); } } // Idea taken from [jest-slow-test-reporter](https://github.com/jodonnell/jest-slow-test-reporter) private collectSlowTests(result: TestResult): void { result.testResults.forEach((test) => { this.slowTests.push({ duration: test.duration ?? DEFAULT_TEST_DURATION, fullName: test.fullName, filePath: result.testFilePath, }); }); } private consoleSlowTests(): void { this.slowTests.sort(function sort(a, b) { return b.duration - a.duration; }); const rootPathRegex = new RegExp(`^${process.cwd()}`); const slowestTests = this.slowTests.slice(0, this.maxSlowTests); const slowTestTime = this.calcTestTime(slowestTests); const allTestTime = this.calcTestTime(this.slowTests); const percentTime = (slowTestTime / allTestTime) * 100; console.log( `Top ${slowestTests.length} slowest examples (${ slowTestTime / 1000 } seconds, ${percentTime.toFixed(1)}% of total time):`, ); slowestTests.forEach(({ duration, fullName, filePath }) => { const path = filePath.replace(rootPathRegex, '.'); console.log(` ${fullName}`); console.log(` ${duration / 1000} seconds ${path}`); }); } private calcTestTime(slowestTests: Array<SlowTest>) { return slowestTests.reduce((acc, curr) => acc + curr.duration, 0); } } export default CustomReporter;