fix(logging): handle mid-line streaming output in test logger and add streaming tests
This commit is contained in:
@@ -1,5 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 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)
|
## 2026-01-19 - 3.1.5 - fix(tstest)
|
||||||
preserve streaming console output and correctly buffer incomplete TAP lines
|
preserve streaming console output and correctly buffer incomplete TAP lines
|
||||||
|
|
||||||
|
|||||||
12
test/tstest/test.gap-debug.ts
Normal file
12
test/tstest/test.gap-debug.ts
Normal 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();
|
||||||
14
test/tstest/test.gap-debug2.ts
Normal file
14
test/tstest/test.gap-debug2.ts
Normal 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();
|
||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@git.zone/tstest',
|
name: '@git.zone/tstest',
|
||||||
version: '3.1.5',
|
version: '3.1.6',
|
||||||
description: 'a test utility to run tests that match test/**/*.ts'
|
description: 'a test utility to run tests that match test/**/*.ts'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export class TsTestLogger {
|
|||||||
private currentTestLogFile: string | null = null;
|
private currentTestLogFile: string | null = null;
|
||||||
private currentTestLogs: string[] = []; // Buffer for current test logs
|
private currentTestLogs: string[] = []; // Buffer for current test logs
|
||||||
private currentTestFailed: boolean = false;
|
private currentTestFailed: boolean = false;
|
||||||
|
private isOutputMidLine: boolean = false; // Track whether we're mid-line for streaming output
|
||||||
|
|
||||||
constructor(options: LogOptions = {}) {
|
constructor(options: LogOptions = {}) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
@@ -189,6 +190,7 @@ export class TsTestLogger {
|
|||||||
// Reset test-specific state
|
// Reset test-specific state
|
||||||
this.currentTestLogs = [];
|
this.currentTestLogs = [];
|
||||||
this.currentTestFailed = false;
|
this.currentTestFailed = false;
|
||||||
|
this.isOutputMidLine = false;
|
||||||
|
|
||||||
// Only set up test log file if --logfile option is specified
|
// Only set up test log file if --logfile option is specified
|
||||||
if (this.options.logFile) {
|
if (this.options.logFile) {
|
||||||
@@ -352,17 +354,28 @@ export class TsTestLogger {
|
|||||||
testConsoleOutput(message: string) {
|
testConsoleOutput(message: string) {
|
||||||
if (this.options.json) return;
|
if (this.options.json) return;
|
||||||
|
|
||||||
|
const prefix = ' ';
|
||||||
// In verbose mode, show console output immediately
|
// In verbose mode, show console output immediately
|
||||||
if (this.options.verbose) {
|
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 {
|
} else {
|
||||||
// In non-verbose mode, buffer the logs
|
// In non-verbose mode, buffer the logs
|
||||||
|
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);
|
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
|
// Always log to test file if --logfile is specified
|
||||||
if (this.currentTestLogFile) {
|
if (this.currentTestLogFile) {
|
||||||
this.logToTestFile(` ${message}`);
|
this.logToTestFile(`${prefix}${message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,13 +384,15 @@ export class TsTestLogger {
|
|||||||
if (this.options.json) return;
|
if (this.options.json) return;
|
||||||
|
|
||||||
const prefix = ' ';
|
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) {
|
if (this.options.verbose) {
|
||||||
// Use process.stdout.write to preserve streaming without adding newlines
|
// 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 {
|
} else {
|
||||||
// Buffer without trailing newline - append to last entry if exists and incomplete
|
// Buffer mode: append to last entry if mid-line
|
||||||
if (this.currentTestLogs.length > 0) {
|
if (this.isOutputMidLine && this.currentTestLogs.length > 0) {
|
||||||
// Append to the last buffered entry (for streaming segments)
|
|
||||||
this.currentTestLogs[this.currentTestLogs.length - 1] += message;
|
this.currentTestLogs[this.currentTestLogs.length - 1] += message;
|
||||||
} else {
|
} else {
|
||||||
this.currentTestLogs.push(message);
|
this.currentTestLogs.push(message);
|
||||||
@@ -386,8 +401,11 @@ export class TsTestLogger {
|
|||||||
|
|
||||||
// Log to test file without adding newline
|
// Log to test file without adding newline
|
||||||
if (this.currentTestLogFile) {
|
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) {
|
private logToTestFileRaw(message: string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user