corde
Version:
A simple library for Discord bot tests
306 lines (239 loc) • 7.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.TestExecutor = void 0;
const tslib_1 = require("tslib");
const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
const runtime_1 = require("../common/runtime");
const testCollector_1 = require("../common/testCollector");
const printHookError_1 = require("../common/printHookError");
const consts_1 = require("../consts");
const utils_1 = require("../utils");
class TestExecutor {
constructor(logUpdate) {
this._logUpdate = logUpdate;
}
async runTestsAndPrint(testMatches) {
const testsTimer = new utils_1.Timer();
testsTimer.start();
const semiReport = {
totalTests: 0,
totalTestFiles: 0,
totalTestsPassed: 0,
totalTestsFailed: 0,
totalTestFilesPassed: 0,
totalTestFilesFailed: 0,
totalEmptyTestFiles: 0,
totalEmptyTests: 0,
};
for (const testFile of testMatches) {
if (testFile.isEmpty) {
this._logUpdate.append(`${(0, consts_1.TAG_PENDING)("EMPTY")} ${testFile.path}`);
this._logUpdate.persist();
semiReport.totalEmptyTestFiles++;
semiReport.totalTestFiles++;
} else {
if (await this.executeTestFile(testFile, semiReport)) {
semiReport.totalTestFilesPassed++;
} else {
semiReport.totalTestFilesFailed++;
}
}
}
const testsDiff = testsTimer.stop();
return {
testTimer: testsDiff[0],
...semiReport,
};
}
async executeTestFile(testFile, semiReport) {
const testFileTimer = new utils_1.Timer();
semiReport.totalTestFiles++;
let fileHasPassed = true;
testFileTimer.start();
const logIndex = this._logUpdate.append(`${(0, consts_1.TAG_PENDING)()} ${testFile.path}`);
for (const group of testFile.groups) {
if (!(await this.executeGroup(group, semiReport))) {
fileHasPassed = false;
}
}
const _diff = testFileTimer.stop();
let fileLabel = (0, consts_1.TAG_PASS)();
let fileNameLabel = testFile.path;
if (!fileHasPassed) {
fileLabel = (0, consts_1.TAG_FAIL)();
fileNameLabel = chalk_1.default.red(fileNameLabel);
}
this._logUpdate.updateLine(
logIndex,
`${fileLabel} ${fileNameLabel} ${chalk_1.default.cyan(_diff[0])}`,
);
this._logUpdate.persist();
return fileHasPassed;
}
async executeGroup(group, semiReport) {
const tests = this.getAssertionPropsFromGroup(group);
let fileHasPassed = true;
for (const test of tests) {
if (!(await this.executeTest(test, semiReport, group.name))) {
fileHasPassed = false;
}
}
return fileHasPassed;
}
async executeTest(test, semiReport, groupName) {
const testTimer = new utils_1.Timer();
let fileHasPassed = true;
testTimer.start();
let logPosition = 0;
const testText = this.createTestText(test.name);
logPosition = this._logUpdate.appendLine(testText);
const reports = await this.runTest(test);
if (reports.length === 0) {
semiReport.totalEmptyTests++;
semiReport.totalTests++;
}
const testDiff = testTimer.stop();
const testNameLabel = this.ITestReportLabelFunction(reports);
const formatedGroupName = !(0, utils_1.stringIsNullOrEmpty)(groupName)
? groupName + " -> "
: "";
if ((0, utils_1.stringIsNullOrEmpty)(test.name)) {
this._logUpdate.updateLine(
logPosition,
`${consts_1.MESSAGE_TAB_SPACE}${testNameLabel(
formatedGroupName + "<empty test name>",
)} ${chalk_1.default.cyan(testDiff[0])}`,
);
} else {
this._logUpdate.updateLine(
logPosition,
`${consts_1.MESSAGE_TAB_SPACE}${testNameLabel(
formatedGroupName + test.name,
)} ${chalk_1.default.cyan(testDiff[0])}`,
);
}
if (!this.printTestsReportAndUpdateRunnerReport(reports, semiReport)) {
fileHasPassed = false;
}
test.testsReports = reports;
return fileHasPassed;
}
printTestsReportAndUpdateRunnerReport(reports, semiReport) {
let fileHasPassed = true;
for (const report of reports) {
semiReport.totalTests++;
if (!this.printReportAndUpdateRunnerReport(report, semiReport)) {
fileHasPassed = false;
}
}
return fileHasPassed;
}
ITestReportLabelFunction(reports) {
if (reports.length === 0) {
return (text) =>
(0, consts_1.TEXT_EMPTY)(" " + consts_1.TEST_RUNNING_ICON + " " + text + " (empty)");
}
if (reports.some((report) => !report.pass)) {
return (text) => (0, consts_1.TEXT_FAIL)(consts_1.TEST_FAIL_ICON + " " + text);
}
return (text) => (0, consts_1.TEXT_PASS)(consts_1.TEST_PASSED_ICON + " " + text);
}
printReportAndUpdateRunnerReport(report, semiReport) {
if (report.pass) {
semiReport.totalTestsPassed++;
return true;
}
semiReport.totalTestsFailed++;
this.printReportData(report);
return false;
}
printReportData(report) {
if (report.message) {
this._logUpdate.appendLine(report.message);
}
if (!report.pass && report.trace) {
this._logUpdate.appendLine(report.trace);
}
}
createTestText(testName) {
if ((0, utils_1.stringIsNullOrEmpty)(testName)) {
return this.createTestTextByStatus("<empty test name>");
}
return this.createTestTextByStatus(testName);
}
createTestTextByStatus(testName) {
const icon = consts_1.TEST_RUNNING_ICON;
return `${consts_1.MESSAGE_TAB_SPACE}${icon} ${testName}`;
}
async runTest(test) {
const reports = [];
let keepRunningBeforeEachFunctions = true;
let keepRunningAfterEachFunctions = true;
for (const testfn of test.testsFunctions) {
keepRunningBeforeEachFunctions = await this.executeHookFunctionIfPossible(
keepRunningBeforeEachFunctions,
testCollector_1.testCollector.beforeEachFunctions,
);
let _report;
try {
_report = await runtime_1.runtime.injectBot(testfn);
} catch (error) {
_report = {
testName: "",
pass: false,
message: this.getErrorMessage(error),
};
}
keepRunningAfterEachFunctions = await this.executeHookFunctionIfPossible(
keepRunningAfterEachFunctions,
testCollector_1.testCollector.afterEachFunctions,
);
reports.push(_report);
}
return reports;
}
async executeHookFunctionIfPossible(keepRunning, queues) {
if (keepRunning) {
const _functionErrors = await queues.executeWithCatchCollectAsync();
if (_functionErrors && _functionErrors.length) {
(0, printHookError_1.printHookErrors)(_functionErrors);
return false;
}
return true;
}
return false;
}
getErrorMessage(error) {
if (error instanceof Error) {
return error.message;
}
return (0, utils_1.formatObject)(error);
}
getAssertionPropsFromGroup(group) {
const assertions = [];
if (group.tests) {
group.tests.forEach((test) => {
assertions.push(...this.getAssertionsPropsFromTest(test));
});
}
if (group.subGroups) {
group.subGroups.forEach((subGroup) => {
const subGroupTests = this.getAssertionPropsFromGroup(subGroup);
assertions.push(...subGroupTests);
});
}
return assertions;
}
getAssertionsPropsFromTest(test) {
const tests = [test];
if (test.subTests) {
test.subTests.forEach((subtest) => {
tests.push(...this.getAssertionsPropsFromTest(subtest));
});
}
return tests;
}
}
exports.TestExecutor = TestExecutor;