Add unattended end-to-end self-test mode for the production webview
VOICED_SELFTEST_OUT runs the Diagnostics checks plus an issue, archive, export (searchable, flattened, re-render), cancel and archive-immutability flow through the real IPC, writes a JSON report and exits. Inert without the variable; doubles as the per-release gate on installed builds.
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
/** Step log of the unattended end-to-end self-test: one entry per step with its verdict and timing. */
|
||||
|
||||
export interface StepResult {
|
||||
name: string;
|
||||
ok: boolean;
|
||||
ms: number;
|
||||
detail: string;
|
||||
}
|
||||
|
||||
export interface StepLog {
|
||||
steps: StepResult[];
|
||||
/**
|
||||
* Runs one step. The body returns its detail text, or throws to fail. A body may also return
|
||||
* `{ ok: false, detail }` for a failed expectation. Never throws; resolves to the recorded result.
|
||||
*/
|
||||
run(name: string, body: () => Promise<string | { ok: boolean; detail: string }>): Promise<StepResult>;
|
||||
}
|
||||
|
||||
const errText = (e: unknown) => (e instanceof Error ? `${e.name}: ${e.message}` : String(e));
|
||||
|
||||
export function createStepLog(now: () => number = () => performance.now()): StepLog {
|
||||
const steps: StepResult[] = [];
|
||||
return {
|
||||
steps,
|
||||
async run(name, body) {
|
||||
const t0 = now();
|
||||
let result: StepResult;
|
||||
try {
|
||||
const r = await body();
|
||||
const { ok, detail } = typeof r === "string" ? { ok: true, detail: r } : r;
|
||||
result = { name, ok, ms: Math.round(now() - t0), detail };
|
||||
} catch (e) {
|
||||
result = { name, ok: false, ms: Math.round(now() - t0), detail: errText(e) };
|
||||
}
|
||||
steps.push(result);
|
||||
return result;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/** The directory part of an absolute path, whichever separator it uses. */
|
||||
export function dirOf(path: string): string {
|
||||
const i = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
|
||||
return i <= 0 ? path.slice(0, i + 1) : path.slice(0, i);
|
||||
}
|
||||
|
||||
export function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {
|
||||
if (a.byteLength !== b.byteLength) return false;
|
||||
for (let i = 0; i < a.byteLength; i++) if (a[i] !== b[i]) return false;
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user