creevey
Version:
Cross-browser screenshot testing tool for Storybook with fancy UI Runner
130 lines • 6.19 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TeamcityReporter = exports.CreeveyReporter = void 0;
const chalk_1 = __importDefault(require("chalk"));
const loglevel_1 = __importDefault(require("loglevel"));
const loglevel_plugin_prefix_1 = __importDefault(require("loglevel-plugin-prefix"));
const mocha_1 = require("mocha");
const types_js_1 = require("../../types.js");
const testLevels = {
INFO: chalk_1.default.green('PASS'),
WARN: chalk_1.default.yellow('START'),
ERROR: chalk_1.default.red('FAIL'),
};
class CreeveyReporter extends mocha_1.reporters.Base {
// TODO Output in better way, like vitest, maybe
constructor(runner, options) {
super(runner);
const { sessionId, topLevelSuite } = options.reporterOptions;
const testLogger = loglevel_1.default.getLogger(sessionId);
loglevel_plugin_prefix_1.default.apply(testLogger, {
format(level) {
return `[${topLevelSuite}:${chalk_1.default.gray(process.pid)}] ${testLevels[level]} => ${chalk_1.default.gray(sessionId)}`;
},
});
runner.on('test', (test) => {
testLogger.warn(chalk_1.default.cyan(test.titlePath().join('/')));
});
runner.on('pass', (test) => {
testLogger.info(chalk_1.default.cyan(test.titlePath().join('/')));
});
runner.on('fail', (test, error) => {
testLogger.error(chalk_1.default.cyan(test.titlePath().join('/')), '\n ', getErrors(error, (error, imageName) => `${chalk_1.default.bold(imageName ?? topLevelSuite)}:${error}`, (error) => error.stack ?? error.message).join('\n '));
});
}
}
exports.CreeveyReporter = CreeveyReporter;
class TeamcityReporter extends mocha_1.reporters.Base {
constructor(runner, options) {
super(runner);
const topLevelSuite = this.escape(options.reporterOptions.topLevelSuite);
const reporterOptions = options.reporterOptions;
runner.on('suite', (suite) => {
if (suite.root)
console.log(`##teamcity[testSuiteStarted name='${topLevelSuite}' flowId='${process.pid}']`);
else
console.log(`##teamcity[testSuiteStarted name='${this.escape(suite.title)}' flowId='${process.pid}']`);
});
runner.on('test', (test) => {
console.log(`##teamcity[testStarted name='${this.escape(test.title)}' flowId='${process.pid}']`);
});
runner.on('fail', (test, error) => {
Object.entries(reporterOptions.images).forEach(([name, image]) => {
if (!image)
return;
const filePath = test
.titlePath()
.concat(name == topLevelSuite ? [] : [topLevelSuite])
.map(this.escape)
.join('/');
const { error: _, ...rest } = image;
Object.values(rest)
.filter(types_js_1.isDefined)
.forEach((fileName) => {
console.log(`##teamcity[publishArtifacts '${reporterOptions.reportDir}/${filePath}/${fileName} => report/${filePath}']`);
console.log(`##teamcity[testMetadata testName='${this.escape(test.title)}' type='image' value='report/${filePath}/${fileName}' flowId='${process.pid}']`);
});
});
// Output failed test as passed due TC don't support retry mechanic
// https://teamcity-support.jetbrains.com/hc/en-us/community/posts/207216829-Count-test-as-successful-if-at-least-one-try-is-successful?page=1#community_comment_207394125
if (reporterOptions.willRetry)
console.log(`##teamcity[testFinished name='${this.escape(test.title)}' flowId='${process.pid}']`);
else
console.log(`##teamcity[testFailed name='${this.escape(test.title)}' message='${this.escape(error.message)}' details='${this.escape(error.stack ?? '')}' flowId='${process.pid}']`);
});
runner.on('pending', (test) => {
console.log(`##teamcity[testIgnored name='${this.escape(test.title)}' message='${this.escape(typeof test.skipReason == 'boolean' ? test.title : test.skipReason)}' flowId='${process.pid}']`);
});
runner.on('test end', (test) => {
console.log(`##teamcity[testFinished name='${this.escape(test.title)}' flowId='${process.pid}']`);
});
runner.on('suite end', (suite) => {
if (!suite.root)
console.log(`##teamcity[testSuiteFinished name='${this.escape(suite.title)}' flowId='${process.pid}']`);
});
runner.on('end', () => {
console.log(`##teamcity[testSuiteFinished name='${topLevelSuite}' flowId='${process.pid}']`);
});
}
escape = (str) => {
if (!str)
return '';
return (str
.toString()
// eslint-disable-next-line no-control-regex
.replace(/\x1B.*?m/g, '')
.replace(/\|/g, '||')
.replace(/\n/g, '|n')
.replace(/\r/g, '|r')
.replace(/\[/g, '|[')
.replace(/\]/g, '|]')
.replace(/\u0085/g, '|x')
.replace(/\u2028/g, '|l')
.replace(/\u2029/g, '|p')
.replace(/'/g, "|'"));
};
}
exports.TeamcityReporter = TeamcityReporter;
function getErrors(error, imageErrorToString, errorToString) {
const errors = [];
if (!(error instanceof Error)) {
errors.push(error);
}
else if (!(0, types_js_1.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;
}
//# sourceMappingURL=reporter.js.map