Compare commits

..

6 Commits
v3.1.5 ... main

12 changed files with 88 additions and 18 deletions

View File

@@ -1,5 +1,26 @@
# Changelog
## 2026-01-25 - 3.1.8 - fix(tapbundle)
treat tests that call tools.allowFailure() as passing and update tests to use tools parameter
- Set testResult.ok to this.failureAllowed so allowed failures are considered passing in the tap test runner implementation (ts_tapbundle/tapbundle.classes.taptest.ts).
- Updated multiple tests to accept the tools parameter and call tools.allowFailure() where failures are intended (test/tapbundle/test.performance-metrics.ts, test/tstest/test.fail.ts, test/tstest/test.failing-with-logs.ts).
- Prevents intentionally-failing tests from skewing timing/metric calculations and preserves console logs for allowed failures.
## 2026-01-25 - 3.1.7 - fix(tap-parser)
append newline to WebSocket tap log messages to ensure proper line-by-line processing
- Fixes handling of WebSocket console.log messages by appending a trailing newline before processing to avoid merged lines.
- Modified ts/tstest.classes.tap.parser.ts: handleTapLog now calls _processLog(tapLog + '\n').
## 2026-01-19 - 3.1.6 - fix(logging)
handle mid-line streaming output in test logger and add streaming tests
- Introduce isOutputMidLine flag to track when streaming output does not end with a newline
- Only prepend the visual prefix at the start of a line and append segments to the last buffered entry when mid-line
- Write consistent output to log files for both complete lines and raw streaming segments
- Add tests to exercise streaming behavior: test/tstest/test.gap-debug.ts and test/tstest/test.gap-debug2.ts
## 2026-01-19 - 3.1.5 - fix(tstest)
preserve streaming console output and correctly buffer incomplete TAP lines

View File

@@ -9,5 +9,5 @@
"target": "ES2022"
},
"nodeModulesDir": true,
"version": "3.1.5"
"version": "3.1.8"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@git.zone/tstest",
"version": "3.1.5",
"version": "3.1.8",
"private": false,
"description": "a test utility to run tests that match test/**/*.ts",
"exports": {

View File

@@ -47,6 +47,7 @@ tap.test('metric test fast 3 - minimal work', async () => {
// Test to verify that failed tests still contribute to timing metrics
tap.test('metric test that fails - 60ms before failure', async (tools) => {
tools.allowFailure();
await tools.delayFor(60);
expect(true).toBeFalse(); // This will fail
});

View File

@@ -1,6 +1,7 @@
import { expect, tap } from '../../ts_tapbundle/index.js';
tap.test('This test should fail', async () => {
tap.test('This test should fail', async (tools) => {
tools.allowFailure();
console.log('This test will fail on purpose');
expect(true).toBeFalse();
});

View File

@@ -1,16 +1,17 @@
import { expect, tap } from '../../ts_tapbundle/index.js';
tap.test('Test that will fail with console logs', async () => {
tap.test('Test that will fail with console logs', async (tools) => {
tools.allowFailure();
console.log('Starting the test...');
console.log('Doing some setup work');
console.log('About to check assertion');
const value = 42;
console.log(`The value is: ${value}`);
// This will fail
expect(value).toEqual(100);
console.log('This log will not be reached');
});

View File

@@ -0,0 +1,12 @@
import { tap, expect } from '../../ts_tapbundle/index.js';
tap.test('check for gaps in streaming', async () => {
// This should print "ABCD" with no gaps
process.stdout.write("A");
process.stdout.write("B");
process.stdout.write("C");
process.stdout.write("D\n");
expect(true).toEqual(true);
});
export default tap.start();

View File

@@ -0,0 +1,14 @@
import { tap, expect } from '../../ts_tapbundle/index.js';
tap.test('streaming with delays', async (tools) => {
// Simulate real streaming with delays
process.stdout.write("Progress: [");
for (let i = 0; i < 10; i++) {
await tools.delayFor(50);
process.stdout.write("=");
}
process.stdout.write("]\n");
expect(true).toEqual(true);
});
export default tap.start();

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@git.zone/tstest',
version: '3.1.5',
version: '3.1.8',
description: 'a test utility to run tests that match test/**/*.ts'
}

View File

@@ -487,7 +487,9 @@ export class TapParser {
}
public async handleTapLog(tapLog: string) {
this._processLog(tapLog);
// Each WebSocket message represents a complete console.log() call,
// so append newline to ensure proper line-by-line processing
this._processLog(tapLog + '\n');
}
/**

View File

@@ -44,6 +44,7 @@ export class TsTestLogger {
private currentTestLogFile: string | null = null;
private currentTestLogs: string[] = []; // Buffer for current test logs
private currentTestFailed: boolean = false;
private isOutputMidLine: boolean = false; // Track whether we're mid-line for streaming output
constructor(options: LogOptions = {}) {
this.options = options;
@@ -189,6 +190,7 @@ export class TsTestLogger {
// Reset test-specific state
this.currentTestLogs = [];
this.currentTestFailed = false;
this.isOutputMidLine = false;
// Only set up test log file if --logfile option is specified
if (this.options.logFile) {
@@ -352,17 +354,28 @@ export class TsTestLogger {
testConsoleOutput(message: string) {
if (this.options.json) return;
const prefix = ' ';
// In verbose mode, show console output immediately
if (this.options.verbose) {
this.log(this.format(` ${message}`, 'dim'));
// Only add prefix if we're starting a new line
const output = this.isOutputMidLine ? message : prefix + message;
this.log(this.format(output, 'dim'));
} else {
// In non-verbose mode, buffer the logs
this.currentTestLogs.push(message);
if (this.isOutputMidLine && this.currentTestLogs.length > 0) {
// Append to the last buffered entry since we're mid-line
this.currentTestLogs[this.currentTestLogs.length - 1] += message;
} else {
this.currentTestLogs.push(message);
}
}
// Reset mid-line state since we just output a complete line
this.isOutputMidLine = false;
// Always log to test file if --logfile is specified
if (this.currentTestLogFile) {
this.logToTestFile(` ${message}`);
this.logToTestFile(`${prefix}${message}`);
}
}
@@ -371,13 +384,15 @@ export class TsTestLogger {
if (this.options.json) return;
const prefix = ' ';
// Only add prefix if we're starting a new line (not mid-line)
const output = this.isOutputMidLine ? message : prefix + message;
if (this.options.verbose) {
// Use process.stdout.write to preserve streaming without adding newlines
process.stdout.write(this.format(prefix + message, 'dim'));
process.stdout.write(this.format(output, 'dim'));
} else {
// Buffer without trailing newline - append to last entry if exists and incomplete
if (this.currentTestLogs.length > 0) {
// Append to the last buffered entry (for streaming segments)
// Buffer mode: append to last entry if mid-line
if (this.isOutputMidLine && this.currentTestLogs.length > 0) {
this.currentTestLogs[this.currentTestLogs.length - 1] += message;
} else {
this.currentTestLogs.push(message);
@@ -386,8 +401,11 @@ export class TsTestLogger {
// Log to test file without adding newline
if (this.currentTestLogFile) {
this.logToTestFileRaw(prefix + message);
this.logToTestFileRaw(output);
}
// We're now mid-line (no newline was written)
this.isOutputMidLine = true;
}
private logToTestFileRaw(message: string) {

View File

@@ -261,7 +261,7 @@ export class TapTest<T = unknown> {
// Final failure
const testResult = {
ok: false,
ok: this.failureAllowed, // Pass if failure is allowed
testNumber,
description: this.description,
metadata: {