donobu
Version:
Create browser automations with an LLM agent and replay them as Playwright scripts.
70 lines • 2.94 kB
JavaScript
;
/**
* @fileoverview Shared state-file helper for Donobu reporters.
*
* Each Donobu reporter (HTML, Markdown, Slack) records its intended output
* path into a single state file that the auto-heal orchestrator reads after
* merging two runs, so it can re-render every configured format at the same
* path the reporter originally chose.
*
* When multiple reporters run in the same Playwright process, each one calls
* {@link mergeStateFileEntry} in its `onEnd` hook. The helper is
* read-modify-write: it loads any previously-written state, merges this
* reporter's `donobuOutputs` entry in without clobbering sibling entries, and
* writes the result back. Synchronous fs I/O is sufficient — Playwright runs
* reporter hooks sequentially within a single JS event loop.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.mergeStateFileEntry = mergeStateFileEntry;
const fs_1 = require("fs");
const path_1 = require("path");
const model_1 = require("./model");
/**
* Merge a single reporter's `donobuOutputs` entry into the shared state file.
* Safe to call from multiple reporters in the same run — each reporter's
* entry is merged alongside any siblings already written.
*
* @param playwrightOutputDir - the Playwright JSON output dir (passed via
* `PLAYWRIGHT_JSON_OUTPUT_DIR`). When unset, the call is a no-op because
* we have nowhere canonical to land the state file.
* @param report - the fresh `DonobuReport` this reporter built from live events.
* Its `suites` overwrite any previous state (they're identical across
* reporters running the same test run, so either is fine).
* @param outputsEntry - the format-keyed entry this reporter is contributing.
*/
function mergeStateFileEntry(playwrightOutputDir, report, outputsEntry) {
if (!playwrightOutputDir) {
return;
}
const statePath = (0, path_1.join)(playwrightOutputDir, model_1.DONOBU_REPORT_STATE_FILENAME);
let existing = null;
if ((0, fs_1.existsSync)(statePath)) {
try {
existing = JSON.parse((0, fs_1.readFileSync)(statePath, 'utf8'));
}
catch {
// Corrupt state file — start fresh rather than failing the reporter.
}
}
const merged = {
...(existing ?? {}),
...report,
metadata: {
...(existing?.metadata ?? {}),
...(report.metadata ?? {}),
donobuOutputs: {
...(existing?.metadata?.donobuOutputs ?? {}),
...(report.metadata?.donobuOutputs ?? {}),
...outputsEntry,
},
},
};
try {
(0, fs_1.mkdirSync)(playwrightOutputDir, { recursive: true });
(0, fs_1.writeFileSync)(statePath, JSON.stringify(merged), 'utf8');
}
catch {
// Non-fatal — worst case the orchestrator falls back to no re-rendering.
}
}
//# sourceMappingURL=stateFile.js.map