fix(tstest-logging): Improve log file handling with log rotation and diff reporting
This commit is contained in:
parent
3eb8ef22e5
commit
aa10fc4ab3
@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-05-24 - 1.10.2 - fix(tstest-logging)
|
||||
Improve log file handling with log rotation and diff reporting
|
||||
|
||||
- Add .claude/settings.local.json to configure allowed shell and web operations
|
||||
- Introduce movePreviousLogFiles function to archive previous log files when --logfile is used
|
||||
- Enhance logging to generate error copies and diff reports between current and previous logs
|
||||
- Add type annotations for console overrides in browser evaluations for improved stability
|
||||
|
||||
## 2025-05-23 - 1.10.1 - fix(tstest)
|
||||
Improve file range filtering and summary logging by skipping test files outside the specified range and reporting them in the final summary.
|
||||
|
||||
|
@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@git.zone/tstest',
|
||||
version: '1.10.1',
|
||||
version: '1.10.2',
|
||||
description: 'a test utility to run tests that match test/**/*.ts'
|
||||
}
|
||||
|
@ -38,6 +38,11 @@ export class TsTest {
|
||||
}
|
||||
|
||||
async run() {
|
||||
// Move previous log files if --logfile option is used
|
||||
if (this.logger.options.logFile) {
|
||||
await this.movePreviousLogFiles();
|
||||
}
|
||||
|
||||
const testGroups = await this.testDir.getTestFileGroups();
|
||||
const allFiles = [...testGroups.serial, ...Object.values(testGroups.parallelGroups).flat()];
|
||||
|
||||
@ -167,7 +172,7 @@ export class TsTest {
|
||||
});
|
||||
server.addRoute(
|
||||
'/test',
|
||||
new plugins.typedserver.servertools.Handler('GET', async (req, res) => {
|
||||
new plugins.typedserver.servertools.Handler('GET', async (_req, res) => {
|
||||
res.type('.html');
|
||||
res.write(`
|
||||
<html>
|
||||
@ -202,7 +207,7 @@ export class TsTest {
|
||||
|
||||
// lets do the browser bit
|
||||
await this.smartbrowserInstance.start();
|
||||
const evaluation = await this.smartbrowserInstance.evaluateOnPage(
|
||||
await this.smartbrowserInstance.evaluateOnPage(
|
||||
`http://localhost:3007/test?bundleName=${bundleFileName}`,
|
||||
async () => {
|
||||
// lets enable real time comms
|
||||
@ -215,12 +220,12 @@ export class TsTest {
|
||||
const originalError = console.error;
|
||||
|
||||
// Override console methods to capture the logs
|
||||
console.log = (...args) => {
|
||||
console.log = (...args: any[]) => {
|
||||
logStore.push(args.join(' '));
|
||||
ws.send(args.join(' '));
|
||||
originalLog(...args);
|
||||
};
|
||||
console.error = (...args) => {
|
||||
console.error = (...args: any[]) => {
|
||||
logStore.push(args.join(' '));
|
||||
ws.send(args.join(' '));
|
||||
originalError(...args);
|
||||
@ -271,4 +276,40 @@ export class TsTest {
|
||||
}
|
||||
|
||||
public async runInDeno() {}
|
||||
|
||||
private async movePreviousLogFiles() {
|
||||
const logDir = plugins.path.join('.nogit', 'testlogs');
|
||||
const previousDir = plugins.path.join('.nogit', 'testlogs', 'previous');
|
||||
|
||||
try {
|
||||
// Get all files in log directory
|
||||
const files = await plugins.smartfile.fs.listFileTree(logDir, '*.log');
|
||||
if (files.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure previous directory exists
|
||||
await plugins.smartfile.fs.ensureDir(previousDir);
|
||||
|
||||
// Move each file to previous directory
|
||||
for (const file of files) {
|
||||
const filename = plugins.path.basename(file);
|
||||
const sourcePath = plugins.path.join(logDir, filename);
|
||||
const destPath = plugins.path.join(previousDir, filename);
|
||||
|
||||
try {
|
||||
// Read file content and write to new location
|
||||
const content = await plugins.smartfile.fs.toStringSync(sourcePath);
|
||||
await plugins.smartfile.fs.toFs(content, destPath);
|
||||
// Remove original file
|
||||
await plugins.smartfile.fs.remove(sourcePath);
|
||||
} catch (error) {
|
||||
// Silently continue if a file can't be moved
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// Directory might not exist, which is fine
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ export interface TestSummary {
|
||||
}
|
||||
|
||||
export class TsTestLogger {
|
||||
private options: LogOptions;
|
||||
public readonly options: LogOptions;
|
||||
private startTime: number;
|
||||
private fileResults: TestFileResult[] = [];
|
||||
private currentFileResult: TestFileResult | null = null;
|
||||
@ -247,6 +247,36 @@ export class TsTestLogger {
|
||||
this.log(this.format(` Summary: ${passed}/${total} ${status}`, color));
|
||||
}
|
||||
|
||||
// If using --logfile, handle error copy and diff detection
|
||||
if (this.options.logFile && this.currentTestLogFile) {
|
||||
try {
|
||||
const logContent = fs.readFileSync(this.currentTestLogFile, 'utf-8');
|
||||
const logDir = path.dirname(this.currentTestLogFile);
|
||||
const logBasename = path.basename(this.currentTestLogFile);
|
||||
|
||||
// Create error copy if there were failures
|
||||
if (failed > 0) {
|
||||
const errorLogPath = path.join(logDir, `00err_${logBasename}`);
|
||||
fs.writeFileSync(errorLogPath, logContent);
|
||||
}
|
||||
|
||||
// Check for previous version and create diff if changed
|
||||
const previousLogPath = path.join(logDir, 'previous', logBasename);
|
||||
if (fs.existsSync(previousLogPath)) {
|
||||
const previousContent = fs.readFileSync(previousLogPath, 'utf-8');
|
||||
|
||||
// Simple check if content differs
|
||||
if (previousContent !== logContent) {
|
||||
const diffLogPath = path.join(logDir, `00diff_${logBasename}`);
|
||||
const diffContent = this.createDiff(previousContent, logContent, logBasename);
|
||||
fs.writeFileSync(diffLogPath, diffContent);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// Silently fail to avoid disrupting the test run
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the current test log file reference only if using --logfile
|
||||
if (this.options.logFile) {
|
||||
this.currentTestLogFile = null;
|
||||
@ -254,7 +284,7 @@ export class TsTestLogger {
|
||||
}
|
||||
|
||||
// TAP output forwarding (for TAP protocol messages)
|
||||
tapOutput(message: string, isError: boolean = false) {
|
||||
tapOutput(message: string, _isError: boolean = false) {
|
||||
if (this.options.json) return;
|
||||
|
||||
// Never show raw TAP protocol messages in console
|
||||
@ -424,4 +454,48 @@ export class TsTestLogger {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a diff between two log contents
|
||||
private createDiff(previousContent: string, currentContent: string, filename: string): string {
|
||||
const previousLines = previousContent.split('\n');
|
||||
const currentLines = currentContent.split('\n');
|
||||
|
||||
let diff = `DIFF REPORT: ${filename}\n`;
|
||||
diff += `Generated: ${new Date().toISOString()}\n`;
|
||||
diff += '='.repeat(80) + '\n\n';
|
||||
|
||||
// Simple line-by-line comparison
|
||||
const maxLines = Math.max(previousLines.length, currentLines.length);
|
||||
let hasChanges = false;
|
||||
|
||||
for (let i = 0; i < maxLines; i++) {
|
||||
const prevLine = previousLines[i] || '';
|
||||
const currLine = currentLines[i] || '';
|
||||
|
||||
if (prevLine !== currLine) {
|
||||
hasChanges = true;
|
||||
if (i < previousLines.length && i >= currentLines.length) {
|
||||
// Line was removed
|
||||
diff += `- [Line ${i + 1}] ${prevLine}\n`;
|
||||
} else if (i >= previousLines.length && i < currentLines.length) {
|
||||
// Line was added
|
||||
diff += `+ [Line ${i + 1}] ${currLine}\n`;
|
||||
} else {
|
||||
// Line was modified
|
||||
diff += `- [Line ${i + 1}] ${prevLine}\n`;
|
||||
diff += `+ [Line ${i + 1}] ${currLine}\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasChanges) {
|
||||
diff += 'No changes detected.\n';
|
||||
}
|
||||
|
||||
diff += '\n' + '='.repeat(80) + '\n';
|
||||
diff += `Previous version had ${previousLines.length} lines\n`;
|
||||
diff += `Current version has ${currentLines.length} lines\n`;
|
||||
|
||||
return diff;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user