test: harden live QA transport probes

This commit is contained in:
Peter Steinberger
2026-05-17 12:08:32 +01:00
parent d41916b5c3
commit 7bf4dfeff3
3 changed files with 67 additions and 29 deletions

View File

@@ -192,4 +192,9 @@ describe("WhatsApp QA live runtime", () => {
},
]);
});
it("classifies WhatsApp driver connection closures as retryable", () => {
expect(__testing.isTransientWhatsAppQaDriverError(new Error("Connection Closed"))).toBe(true);
expect(__testing.isTransientWhatsAppQaDriverError(new Error("timed out waiting"))).toBe(false);
});
});

View File

@@ -470,6 +470,10 @@ function messageMatches(message: WhatsAppObservedMessage, matchText: string | Re
: matchText.test(message.text);
}
function isTransientWhatsAppQaDriverError(error: unknown) {
return /\bConnection Closed\b/iu.test(formatErrorMessage(error));
}
async function runWhatsAppScenario(params: {
driver: WhatsAppQaDriverSession;
driverPhoneE164: string;
@@ -754,7 +758,7 @@ export async function runWhatsAppQaLive(params: {
parentDir: tempAuthRoot,
}),
]);
const activeDriver = await startWhatsAppQaDriverSession({ authDir: driverAuthDir });
let activeDriver = await startWhatsAppQaDriverSession({ authDir: driverAuthDir });
driver = activeDriver;
for (const scenario of scenarios) {
@@ -768,32 +772,50 @@ export async function runWhatsAppQaLive(params: {
);
continue;
}
try {
const result = await runWhatsAppScenario({
driver: activeDriver,
driverPhoneE164: runtimeEnv.driverPhoneE164,
gatewayDebugDirPath,
observedMessages,
providerMode,
primaryModel,
alternateModel,
fastMode: params.fastMode,
groupJid: runtimeEnv.groupJid,
repoRoot,
scenario,
sutAccountId,
sutAuthDir,
sutPhoneE164: runtimeEnv.sutPhoneE164,
});
scenarioResults.push(result);
} catch (error) {
preservedGatewayDebugArtifacts = true;
scenarioResults.push({
id: scenario.id,
title: scenario.title,
status: "fail",
details: formatErrorMessage(error),
});
let retriedDriver = false;
while (true) {
try {
const result = await runWhatsAppScenario({
driver: activeDriver,
driverPhoneE164: runtimeEnv.driverPhoneE164,
gatewayDebugDirPath,
observedMessages,
providerMode,
primaryModel,
alternateModel,
fastMode: params.fastMode,
groupJid: runtimeEnv.groupJid,
repoRoot,
scenario,
sutAccountId,
sutAuthDir,
sutPhoneE164: runtimeEnv.sutPhoneE164,
});
scenarioResults.push(
retriedDriver
? { ...result, details: `${result.details}; driver reconnected` }
: result,
);
break;
} catch (error) {
if (!retriedDriver && isTransientWhatsAppQaDriverError(error)) {
retriedDriver = true;
await activeDriver.close().catch(() => {});
activeDriver = await startWhatsAppQaDriverSession({ authDir: driverAuthDir });
driver = activeDriver;
continue;
}
preservedGatewayDebugArtifacts = true;
scenarioResults.push({
id: scenario.id,
title: scenario.title,
status: "fail",
details: formatErrorMessage(error),
});
break;
}
}
if (scenarioResults.at(-1)?.status === "fail") {
break;
}
}
@@ -921,6 +943,7 @@ export const __testing = {
buildWhatsAppQaConfig,
createMissingGroupJidScenarioResult,
findScenarios,
isTransientWhatsAppQaDriverError,
parseWhatsAppQaCredentialPayload,
resolveWhatsAppQaRuntimeEnv,
resolveWhatsAppMetadataRedaction,

View File

@@ -561,7 +561,7 @@ export async function runAllowlistHotReloadScenario(context: MatrixQaScenarioCon
export async function runQuietStreamingPreviewScenario(context: MatrixQaScenarioContext) {
return runMatrixStreamingPreviewScenario(context, {
expectedPreviewKind: "notice",
finalText: `MATRIX_QA_QUIET_STREAM_${randomUUID().slice(0, 8).toUpperCase()} preview complete`,
finalText: buildMatrixStreamingPreviewFinalText("MATRIX_QA_QUIET_STREAM"),
label: "quiet streaming",
triggerBodyBuilder: buildMatrixQuietStreamingPrompt,
});
@@ -570,12 +570,22 @@ export async function runQuietStreamingPreviewScenario(context: MatrixQaScenario
export async function runPartialStreamingPreviewScenario(context: MatrixQaScenarioContext) {
return runMatrixStreamingPreviewScenario(context, {
expectedPreviewKind: "message",
finalText: `MATRIX_QA_PARTIAL_STREAM_${randomUUID().slice(0, 8).toUpperCase()} preview complete`,
finalText: buildMatrixStreamingPreviewFinalText("MATRIX_QA_PARTIAL_STREAM"),
label: "partial streaming",
triggerBodyBuilder: buildMatrixPartialStreamingPrompt,
});
}
function buildMatrixStreamingPreviewFinalText(prefix: string) {
const token = `${prefix}_${randomUUID().slice(0, 8).toUpperCase()}`;
return [
`${token} preview complete.`,
`${token} alpha segment confirms the draft stream started before final delivery.`,
`${token} beta segment keeps the exact final answer long enough for preview updates.`,
`${token} omega segment marks the finalized Matrix QA reply.`,
].join(" ");
}
async function runMatrixStreamingPreviewScenario(
context: MatrixQaScenarioContext,
params: {