diff --git a/package.json b/package.json index fc6753e..904fe04 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "liqa", - "version": "1.11.0", + "version": "1.12.0", "private": true, "workspaces": [ "server", diff --git a/server/src/scenario/scenario-scheduler.service.ts b/server/src/scenario/scenario-scheduler.service.ts index cc0bea9..afcd559 100644 --- a/server/src/scenario/scenario-scheduler.service.ts +++ b/server/src/scenario/scenario-scheduler.service.ts @@ -515,6 +515,8 @@ export class ScenarioSchedulerService implements OnModuleInit { `Step ${(stepRun.scenarioStep as ScenarioStepEntity | undefined)?.order ?? "?"} failed: ${description}`, ); + await this.dumpPageOnFailure(stepRun); + // Cancel all remaining waiting/pending step runs in this run await this.runStepRepo .createQueryBuilder() @@ -534,4 +536,51 @@ export class ScenarioSchedulerService implements OnModuleInit { await this.runRepo.update(stepRun.runId, { status: "fail" }); this.logger.log(`Run #${stepRun.runId} → fail`); } + + // ── Page dump on failure ──────────────────────────────────────────────────── + + private async dumpPageOnFailure( + stepRun: ScenarioRunStepEntity, + ): Promise { + const handle = this.runBrowsers.get(stepRun.runId); + if (!handle) return; // no browser was ever opened for this run (e.g. setup error) + + const step = stepRun.scenarioStep as ScenarioStepEntity | undefined; + const namePrefix = `step-${step?.order ?? stepRun.id}-failure`; + + try { + const screenshot = await handle.page.screenshot({ fullPage: true }); + await this.fileStorageService.createAndSaveRunArtifact( + stepRun.runId, + screenshot, + `${namePrefix}.png`, + "image/png", + ); + } catch (err) { + this.logger.warn( + `StepRun #${stepRun.id}: failed to capture failure screenshot — ${(err as Error).message}`, + ); + } + + try { + const html = await handle.page.content(); + await this.fileStorageService.createAndSaveRunArtifact( + stepRun.runId, + Buffer.from(html, "utf-8"), + `${namePrefix}.html`, + "text/html", + ); + } catch (err) { + this.logger.warn( + `StepRun #${stepRun.id}: failed to capture failure page HTML — ${(err as Error).message}`, + ); + } + + this.persistLog( + stepRun.runId, + stepRun.id, + "log", + `Step ${step?.order ?? "?"} failed: page dump uploaded to run files`, + ); + } }