feat(logging): Improve logging output, CLI option parsing, and test report formatting.

This commit is contained in:
2025-05-15 16:39:46 +00:00
parent 3fc4cee2b1
commit 78ffad2f7d
9 changed files with 644 additions and 168 deletions

View File

@@ -8,10 +8,13 @@ import { TestDirectory } from './tstest.classes.testdirectory.js';
import { TapCombinator } from './tstest.classes.tap.combinator.js';
import { TapParser } from './tstest.classes.tap.parser.js';
import { TestExecutionMode } from './index.js';
import { TsTestLogger } from './tstest.logging.js';
import type { LogOptions } from './tstest.logging.js';
export class TsTest {
public testDir: TestDirectory;
public executionMode: TestExecutionMode;
public logger: TsTestLogger;
public smartshellInstance = new plugins.smartshell.Smartshell({
executor: 'bash',
@@ -22,62 +25,57 @@ export class TsTest {
public tsbundleInstance = new plugins.tsbundle.TsBundle();
constructor(cwdArg: string, testPathArg: string, executionModeArg: TestExecutionMode) {
constructor(cwdArg: string, testPathArg: string, executionModeArg: TestExecutionMode, logOptions: LogOptions = {}) {
this.executionMode = executionModeArg;
this.testDir = new TestDirectory(cwdArg, testPathArg, executionModeArg);
this.logger = new TsTestLogger(logOptions);
}
async run() {
const fileNamesToRun: string[] = await this.testDir.getTestFilePathArray();
console.log(cs(plugins.figures.hamburger.repeat(80), 'cyan'));
console.log('');
console.log(`${logPrefixes.TsTestPrefix} FOUND ${fileNamesToRun.length} TESTFILE(S):`);
for (const fileName of fileNamesToRun) {
console.log(`${logPrefixes.TsTestPrefix} ${cs(fileName, 'orange')}`);
}
console.log('-'.repeat(48));
console.log(''); // force new line
// Log test discovery
this.logger.testDiscovery(
fileNamesToRun.length,
this.testDir.testPath,
this.executionMode
);
const tapCombinator = new TapCombinator(); // lets create the TapCombinator
const tapCombinator = new TapCombinator(this.logger); // lets create the TapCombinator
let fileIndex = 0;
for (const fileNameArg of fileNamesToRun) {
fileIndex++;
switch (true) {
case process.env.CI && fileNameArg.includes('.nonci.'):
console.log('!!!!!!!!!!!');
console.log(
`not running testfile ${fileNameArg}, since we are CI and file name includes '.nonci.' tag`
);
console.log('!!!!!!!!!!!');
this.logger.tapOutput(`Skipping ${fileNameArg} - marked as non-CI`);
break;
case fileNameArg.endsWith('.browser.ts') || fileNameArg.endsWith('.browser.nonci.ts'):
const tapParserBrowser = await this.runInChrome(fileNameArg);
const tapParserBrowser = await this.runInChrome(fileNameArg, fileIndex, fileNamesToRun.length);
tapCombinator.addTapParser(tapParserBrowser);
break;
case fileNameArg.endsWith('.both.ts') || fileNameArg.endsWith('.both.nonci.ts'):
console.log('>>>>>>> TEST PART 1: chrome');
const tapParserBothBrowser = await this.runInChrome(fileNameArg);
this.logger.sectionStart('Part 1: Chrome');
const tapParserBothBrowser = await this.runInChrome(fileNameArg, fileIndex, fileNamesToRun.length);
tapCombinator.addTapParser(tapParserBothBrowser);
console.log(cs(`|`.repeat(16), 'cyan'));
console.log(''); // force new line
console.log('>>>>>>> TEST PART 2: node');
const tapParserBothNode = await this.runInNode(fileNameArg);
this.logger.sectionEnd();
this.logger.sectionStart('Part 2: Node');
const tapParserBothNode = await this.runInNode(fileNameArg, fileIndex, fileNamesToRun.length);
tapCombinator.addTapParser(tapParserBothNode);
this.logger.sectionEnd();
break;
default:
const tapParserNode = await this.runInNode(fileNameArg);
const tapParserNode = await this.runInNode(fileNameArg, fileIndex, fileNamesToRun.length);
tapCombinator.addTapParser(tapParserNode);
break;
}
console.log(cs(`^`.repeat(16), 'cyan'));
console.log(''); // force new line
}
tapCombinator.evaluate();
}
public async runInNode(fileNameArg: string): Promise<TapParser> {
console.log(`${cs('=> ', 'blue')} Running ${cs(fileNameArg, 'orange')} in node.js runtime.`);
console.log(`${cs(`= `.repeat(32), 'cyan')}`);
const tapParser = new TapParser(fileNameArg + ':node');
public async runInNode(fileNameArg: string, index: number, total: number): Promise<TapParser> {
this.logger.testFileStart(fileNameArg, 'node.js', index, total);
const tapParser = new TapParser(fileNameArg + ':node', this.logger);
// tsrun options
let tsrunOptions = '';
@@ -92,9 +90,8 @@ export class TsTest {
return tapParser;
}
public async runInChrome(fileNameArg: string): Promise<TapParser> {
console.log(`${cs('=> ', 'blue')} Running ${cs(fileNameArg, 'orange')} in chromium runtime.`);
console.log(`${cs(`= `.repeat(32), 'cyan')}`);
public async runInChrome(fileNameArg: string, index: number, total: number): Promise<TapParser> {
this.logger.testFileStart(fileNameArg, 'chromium', index, total);
// lets get all our paths sorted
const tsbundleCacheDirPath = plugins.path.join(paths.cwd, './.nogit/tstest_cache');
@@ -133,11 +130,17 @@ export class TsTest {
await server.start();
// lets handle realtime comms
const tapParser = new TapParser(fileNameArg + ':chrome');
const tapParser = new TapParser(fileNameArg + ':chrome', this.logger);
const wss = new plugins.ws.WebSocketServer({ port: 8080 });
wss.on('connection', (ws) => {
ws.on('message', (message) => {
tapParser.handleTapLog(message.toString());
const messageStr = message.toString();
if (messageStr.startsWith('console:')) {
const [, level, ...messageParts] = messageStr.split(':');
this.logger.browserConsole(messageParts.join(':'), level);
} else {
tapParser.handleTapLog(messageStr);
}
});
});