UNPKG

creevey

Version:

Cross-browser screenshot testing tool for Storybook with fancy UI Runner

81 lines (71 loc) 2.59 kB
import chalk from 'chalk'; import Logger from 'loglevel'; import prefix from 'loglevel-plugin-prefix'; import { FakeTest, isImageError, TEST_EVENTS } from '../../types.js'; import EventEmitter from 'events'; const testLevels: Record<string, string> = { INFO: chalk.green('PASS '), WARN: chalk.yellow('START'), ERROR: chalk.red('FAIL '), }; let browserName = ''; let sessionId = ''; let processId = process.pid; export class CreeveyReporter { private logger: Logger.Logger | null = null; // TODO Output in better way, like vitest, maybe constructor(runner: EventEmitter) { runner.on(TEST_EVENTS.TEST_BEGIN, (test: FakeTest) => { this.getLogger(test.creevey).warn(chalk.cyan(test.fullTitle())); }); runner.on(TEST_EVENTS.TEST_PASS, (test: FakeTest) => { this.getLogger(test.creevey).info( chalk.cyan(test.fullTitle()), test.duration ? chalk.gray(`(${test.duration} ms)`) : '', ); }); runner.on(TEST_EVENTS.TEST_FAIL, (test: FakeTest, error) => { this.getLogger(test.creevey).error( chalk.cyan(test.fullTitle()), test.duration ? chalk.gray(`(${test.duration} ms)`) : '', '\n ', this.getErrors( error, (error, imageName) => `${chalk.bold(imageName ?? test.creevey.browserName)}:${error}`, (error) => error.stack ?? error.message, ).join('\n '), ); }); } private getLogger(options: { sessionId: string; browserName: string; workerId: number }) { ({ sessionId, browserName, workerId: processId = process.pid } = options); if (this.logger) return this.logger; const testLogger = Logger.getLogger(sessionId); this.logger = prefix.apply(testLogger, { format(level) { return `[${browserName}:${chalk.gray(processId)}] ${testLevels[level]} => ${chalk.gray(sessionId)}`; }, }); return this.logger; } private getErrors( error: unknown, imageErrorToString: (error: string, imageName?: string) => string, errorToString: (error: Error) => string, ): string[] { const errors = []; if (!(error instanceof Error)) { errors.push(error as string); } else if (!isImageError(error)) { errors.push(errorToString(error)); } else if (typeof error.images == 'string') { errors.push(imageErrorToString(error.images)); } else { const imageErrors = error.images ?? {}; Object.keys(imageErrors).forEach((imageName) => { errors.push(imageErrorToString(imageErrors[imageName] ?? '', imageName)); }); } return errors; } }