feat(cli): Add new timeout and file range options with enhanced logfile diff logging
This commit is contained in:
@@ -18,6 +18,7 @@ export class TsTest {
|
||||
public filterTags: string[];
|
||||
public startFromFile: number | null;
|
||||
public stopAtFile: number | null;
|
||||
public timeoutSeconds: number | null;
|
||||
|
||||
public smartshellInstance = new plugins.smartshell.Smartshell({
|
||||
executor: 'bash',
|
||||
@@ -28,13 +29,14 @@ export class TsTest {
|
||||
|
||||
public tsbundleInstance = new plugins.tsbundle.TsBundle();
|
||||
|
||||
constructor(cwdArg: string, testPathArg: string, executionModeArg: TestExecutionMode, logOptions: LogOptions = {}, tags: string[] = [], startFromFile: number | null = null, stopAtFile: number | null = null) {
|
||||
constructor(cwdArg: string, testPathArg: string, executionModeArg: TestExecutionMode, logOptions: LogOptions = {}, tags: string[] = [], startFromFile: number | null = null, stopAtFile: number | null = null, timeoutSeconds: number | null = null) {
|
||||
this.executionMode = executionModeArg;
|
||||
this.testDir = new TestDirectory(cwdArg, testPathArg, executionModeArg);
|
||||
this.logger = new TsTestLogger(logOptions);
|
||||
this.filterTags = tags;
|
||||
this.startFromFile = startFromFile;
|
||||
this.stopAtFile = stopAtFile;
|
||||
this.timeoutSeconds = timeoutSeconds;
|
||||
}
|
||||
|
||||
async run() {
|
||||
@@ -147,7 +149,30 @@ export class TsTest {
|
||||
const execResultStreaming = await this.smartshellInstance.execStreamingSilent(
|
||||
`tsrun ${fileNameArg}${tsrunOptions}`
|
||||
);
|
||||
await tapParser.handleTapProcess(execResultStreaming.childProcess);
|
||||
|
||||
// Handle timeout if specified
|
||||
if (this.timeoutSeconds !== null) {
|
||||
const timeoutMs = this.timeoutSeconds * 1000;
|
||||
const timeoutPromise = new Promise<void>((_resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
execResultStreaming.childProcess.kill('SIGTERM');
|
||||
reject(new Error(`Test file timed out after ${this.timeoutSeconds} seconds`));
|
||||
}, timeoutMs);
|
||||
});
|
||||
|
||||
try {
|
||||
await Promise.race([
|
||||
tapParser.handleTapProcess(execResultStreaming.childProcess),
|
||||
timeoutPromise
|
||||
]);
|
||||
} catch (error) {
|
||||
// Handle timeout error
|
||||
tapParser.handleTimeout(this.timeoutSeconds);
|
||||
}
|
||||
} else {
|
||||
await tapParser.handleTapProcess(execResultStreaming.childProcess);
|
||||
}
|
||||
|
||||
return tapParser;
|
||||
}
|
||||
|
||||
@@ -205,9 +230,10 @@ export class TsTest {
|
||||
});
|
||||
});
|
||||
|
||||
// lets do the browser bit
|
||||
// lets do the browser bit with timeout handling
|
||||
await this.smartbrowserInstance.start();
|
||||
await this.smartbrowserInstance.evaluateOnPage(
|
||||
|
||||
const evaluatePromise = this.smartbrowserInstance.evaluateOnPage(
|
||||
`http://localhost:3007/test?bundleName=${bundleFileName}`,
|
||||
async () => {
|
||||
// lets enable real time comms
|
||||
@@ -264,6 +290,29 @@ export class TsTest {
|
||||
return logStore.join('\n');
|
||||
}
|
||||
);
|
||||
|
||||
// Handle timeout if specified
|
||||
if (this.timeoutSeconds !== null) {
|
||||
const timeoutMs = this.timeoutSeconds * 1000;
|
||||
const timeoutPromise = new Promise<void>((_resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
reject(new Error(`Test file timed out after ${this.timeoutSeconds} seconds`));
|
||||
}, timeoutMs);
|
||||
});
|
||||
|
||||
try {
|
||||
await Promise.race([
|
||||
evaluatePromise,
|
||||
timeoutPromise
|
||||
]);
|
||||
} catch (error) {
|
||||
// Handle timeout error
|
||||
tapParser.handleTimeout(this.timeoutSeconds);
|
||||
}
|
||||
} else {
|
||||
await evaluatePromise;
|
||||
}
|
||||
|
||||
await this.smartbrowserInstance.stop();
|
||||
await server.stop();
|
||||
wss.close();
|
||||
@@ -280,28 +329,38 @@ export class TsTest {
|
||||
private async movePreviousLogFiles() {
|
||||
const logDir = plugins.path.join('.nogit', 'testlogs');
|
||||
const previousDir = plugins.path.join('.nogit', 'testlogs', 'previous');
|
||||
const errDir = plugins.path.join('.nogit', 'testlogs', '00err');
|
||||
const diffDir = plugins.path.join('.nogit', 'testlogs', '00diff');
|
||||
|
||||
try {
|
||||
// Get all files in log directory
|
||||
// Delete 00err and 00diff directories if they exist
|
||||
if (await plugins.smartfile.fs.isDirectory(errDir)) {
|
||||
await plugins.smartfile.fs.remove(errDir);
|
||||
}
|
||||
if (await plugins.smartfile.fs.isDirectory(diffDir)) {
|
||||
await plugins.smartfile.fs.remove(diffDir);
|
||||
}
|
||||
|
||||
// Get all .log files in log directory (not in subdirectories)
|
||||
const files = await plugins.smartfile.fs.listFileTree(logDir, '*.log');
|
||||
if (files.length === 0) {
|
||||
const logFiles = files.filter(file => !file.includes('/'));
|
||||
|
||||
if (logFiles.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure previous directory exists
|
||||
await plugins.smartfile.fs.ensureDir(previousDir);
|
||||
|
||||
// Move each file to previous directory
|
||||
for (const file of files) {
|
||||
// Move each log file to previous directory
|
||||
for (const file of logFiles) {
|
||||
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
|
||||
// Copy file to new location and remove original
|
||||
await plugins.smartfile.fs.copy(sourcePath, destPath);
|
||||
await plugins.smartfile.fs.remove(sourcePath);
|
||||
} catch (error) {
|
||||
// Silently continue if a file can't be moved
|
||||
|
Reference in New Issue
Block a user