



























@@ -369,6 +369,103 @@ describe("matrix live qa scenarios", () => {
369369expect(shardIds.toSorted()).toEqual(allIds.toSorted());
370370});
371371372+it("waits for the driver Matrix approval reaction echo before awaiting the decision", async () => {
373+const context = matrixQaScenarioContext();
374+let approvalId = "";
375+const gatewayCall = vi.fn().mockImplementation(async (method: string, ...args: unknown[]) => {
376+if (method === "exec.approval.request") {
377+const params = args.find(
378+(arg): arg is { id?: unknown } => typeof arg === "object" && arg !== null && "id" in arg,
379+);
380+const payload =
381+typeof params === "object" && params !== null ? (params as { id?: unknown }) : undefined;
382+approvalId = String(payload?.id ?? "approval-missing");
383+return { id: approvalId, status: "accepted" };
384+}
385+if (method === "exec.approval.waitDecision") {
386+return { decision: "allow-once", id: approvalId };
387+}
388+throw new Error(`unexpected gateway method ${method}`);
389+});
390+context.gatewayCall = gatewayCall;
391+const rootEventId = "$approval-thread-root";
392+const approvalEventId = "$approval-thread-event";
393+const sendReaction = vi.fn().mockResolvedValue("$driver-approval-reaction");
394+const waitForRoomEvent = vi
395+.fn()
396+.mockImplementationOnce(async () => ({
397+event: matrixQaMessageEvent({
398+approval: {
399+allowedDecisions: ["allow-once", "deny"],
400+hasCommandText: true,
401+id: approvalId,
402+kind: "exec",
403+state: "pending",
404+type: "approval.request",
405+version: 1,
406+},
407+body: "approval requested",
408+eventId: approvalEventId,
409+kind: "message",
410+relatesTo: {
411+eventId: rootEventId,
412+inReplyToId: rootEventId,
413+isFallingBack: true,
414+relType: "m.thread",
415+},
416+}),
417+since: "driver-sync-approval",
418+}))
419+.mockImplementationOnce(async () => ({
420+event: {
421+eventId: "$bot-approval-option",
422+kind: "reaction",
423+reaction: {
424+eventId: approvalEventId,
425+key: "✅",
426+},
427+roomId: "!main:matrix-qa.test",
428+sender: "@sut:matrix-qa.test",
429+type: "m.reaction",
430+} satisfies MatrixQaObservedEvent,
431+since: "driver-sync-option",
432+}))
433+.mockImplementationOnce(async () => ({
434+event: {
435+eventId: "$driver-approval-reaction",
436+kind: "reaction",
437+reaction: {
438+eventId: approvalEventId,
439+key: "✅",
440+},
441+roomId: "!main:matrix-qa.test",
442+sender: "@driver:matrix-qa.test",
443+type: "m.reaction",
444+} satisfies MatrixQaObservedEvent,
445+since: "driver-sync-driver-reaction",
446+}));
447+createMatrixQaClient.mockReturnValue({
448+primeRoom: vi.fn().mockResolvedValue("driver-sync-start"),
449+ sendReaction,
450+sendTextMessage: vi.fn().mockResolvedValue(rootEventId),
451+ waitForRoomEvent,
452+});
453+454+const scenario = MATRIX_QA_SCENARIOS.find(
455+(entry) => entry.id === "matrix-approval-thread-target",
456+);
457+expect(scenario).toBeDefined();
458+459+await expect(runMatrixQaScenario(scenario!, context)).resolves.toMatchObject({
460+artifacts: {
461+reactionEventId: "$driver-approval-reaction",
462+reactionTargetEventId: approvalEventId,
463+},
464+});
465+expect(waitForRoomEvent).toHaveBeenCalledTimes(3);
466+expect(gatewayCall.mock.calls.at(-1)?.[0]).toBe("exec.approval.waitDecision");
467+});
468+372469it("lets explicit Matrix scenario ids override the selected profile", () => {
373470expect(
374471scenarioTesting
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。