





















@@ -2,16 +2,8 @@ import fs from "node:fs";
22import os from "node:os";
33import path from "node:path";
44import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
5-import type { OpenClawConfig, PluginRuntime, RuntimeEnv } from "../runtime-api.js";
6-import {
7-type MSTeamsActivityHandler,
8-type MSTeamsMessageHandlerDeps,
9-registerMSTeamsHandlers,
10-} from "./monitor-handler.js";
11-import {
12-createActivityHandler,
13-createMSTeamsMessageHandlerDeps,
14-} from "./monitor-handler.test-helpers.js";
5+import type { PluginRuntime } from "../runtime-api.js";
6+import { respondToMSTeamsFileConsentInvoke } from "./file-consent-invoke.js";
157import { getPendingUploadFs, storePendingUploadFs } from "./pending-uploads-fs.js";
168import { clearPendingUploads, getPendingUpload, storePendingUpload } from "./pending-uploads.js";
179import { setMSTeamsRuntime } from "./runtime.js";
@@ -64,14 +56,11 @@ function createRuntimeStub(stateDir?: string): PluginRuntime {
64566557const runtimeStub: PluginRuntime = createRuntimeStub();
665867-function createDeps(): MSTeamsMessageHandlerDeps {
68-return createMSTeamsMessageHandlerDeps({
69-cfg: {} as OpenClawConfig,
70-runtime: {
71-error: vi.fn(),
72-} as unknown as RuntimeEnv,
73-});
74-}
59+const log = {
60+debug: vi.fn(),
61+info: vi.fn(),
62+error: vi.fn(),
63+};
75647665function createInvokeContext(params: {
7766conversationId: string;
@@ -129,18 +118,12 @@ function createConsentInvokeHarness(params: {
129118conversationId: params.pendingConversationId ?? "19:victim@thread.v2",
130119consentCardActivityId: params.consentCardActivityId,
131120});
132-const handler = registerMSTeamsHandlers(
133-createActivityHandler(),
134-createDeps(),
135-) as MSTeamsActivityHandler & {
136-run: NonNullable<MSTeamsActivityHandler["run"]>;
137-};
138121const { context, sendActivity, updateActivity } = createInvokeContext({
139122conversationId: params.invokeConversationId,
140123 uploadId,
141124action: params.action,
142125});
143-return { uploadId, handler, context, sendActivity, updateActivity };
126+return { uploadId, context, sendActivity, updateActivity };
144127}
145128146129function requirePendingUpload(uploadId: string) {
@@ -155,17 +138,18 @@ describe("msteams file consent invoke authz", () => {
155138beforeEach(() => {
156139setMSTeamsRuntime(runtimeStub);
157140clearPendingUploads();
141+vi.clearAllMocks();
158142fileConsentMockState.uploadToConsentUrl.mockReset();
159143fileConsentMockState.uploadToConsentUrl.mockResolvedValue(undefined);
160144});
161145162146it("uploads when invoke conversation matches pending upload conversation", async () => {
163-const { uploadId, handler, context, sendActivity } = createConsentInvokeHarness({
147+const { uploadId, context, sendActivity } = createConsentInvokeHarness({
164148invokeConversationId: "19:victim@thread.v2;messageid=abc123",
165149action: "accept",
166150});
167151168-await handler.run(context);
152+await respondToMSTeamsFileConsentInvoke(context, log);
169153170154// invokeResponse should be sent immediately
171155expect(sendActivity).toHaveBeenCalledWith(
@@ -185,13 +169,13 @@ describe("msteams file consent invoke authz", () => {
185169});
186170187171it("calls updateActivity to replace the consent card when consentCardActivityId is set", async () => {
188-const { handler, context, sendActivity, updateActivity } = createConsentInvokeHarness({
172+const { context, sendActivity, updateActivity } = createConsentInvokeHarness({
189173invokeConversationId: "19:victim@thread.v2;messageid=abc123",
190174action: "accept",
191175consentCardActivityId: "consent-card-activity-id-123",
192176});
193177194-await handler.run?.(context);
178+await respondToMSTeamsFileConsentInvoke(context, log);
195179196180expect(sendActivity).toHaveBeenCalledWith(expect.objectContaining({ type: "invokeResponse" }));
197181expect(fileConsentMockState.uploadToConsentUrl).toHaveBeenCalledTimes(1);
@@ -212,13 +196,13 @@ describe("msteams file consent invoke authz", () => {
212196});
213197214198it("does not send file info card via sendActivity when updateActivity succeeds", async () => {
215-const { handler, context, sendActivity, updateActivity } = createConsentInvokeHarness({
199+const { context, sendActivity, updateActivity } = createConsentInvokeHarness({
216200invokeConversationId: "19:victim@thread.v2;messageid=abc123",
217201action: "accept",
218202consentCardActivityId: "consent-card-activity-id-happy",
219203});
220204221-await handler.run?.(context);
205+await respondToMSTeamsFileConsentInvoke(context, log);
222206223207// updateActivity should replace the consent card in-place
224208expect(updateActivity).toHaveBeenCalledTimes(1);
@@ -240,27 +224,27 @@ describe("msteams file consent invoke authz", () => {
240224});
241225242226it("does not call updateActivity when no consentCardActivityId is stored", async () => {
243-const { handler, context, updateActivity } = createConsentInvokeHarness({
227+const { context, updateActivity } = createConsentInvokeHarness({
244228invokeConversationId: "19:victim@thread.v2;messageid=abc123",
245229action: "accept",
246230// no consentCardActivityId
247231});
248232249-await handler.run?.(context);
233+await respondToMSTeamsFileConsentInvoke(context, log);
250234251235expect(fileConsentMockState.uploadToConsentUrl).toHaveBeenCalledTimes(1);
252236expect(updateActivity).not.toHaveBeenCalled();
253237});
254238255239it("still completes upload if updateActivity throws", async () => {
256-const { uploadId, handler, context, updateActivity } = createConsentInvokeHarness({
240+const { uploadId, context, updateActivity } = createConsentInvokeHarness({
257241invokeConversationId: "19:victim@thread.v2;messageid=abc123",
258242action: "accept",
259243consentCardActivityId: "consent-card-activity-id-fail",
260244});
261245updateActivity.mockRejectedValueOnce(new Error("Teams API error"));
262246263-await handler.run?.(context);
247+await respondToMSTeamsFileConsentInvoke(context, log);
264248265249// Upload should have completed despite updateActivity failure
266250expect(fileConsentMockState.uploadToConsentUrl).toHaveBeenCalledTimes(1);
@@ -269,12 +253,12 @@ describe("msteams file consent invoke authz", () => {
269253});
270254271255it("rejects cross-conversation accept invoke and keeps pending upload", async () => {
272-const { uploadId, handler, context, sendActivity } = createConsentInvokeHarness({
256+const { uploadId, context, sendActivity } = createConsentInvokeHarness({
273257invokeConversationId: "19:attacker@thread.v2",
274258action: "accept",
275259});
276260277-await handler.run(context);
261+await respondToMSTeamsFileConsentInvoke(context, log);
278262279263// invokeResponse should be sent immediately
280264expect(sendActivity).toHaveBeenCalledWith(
@@ -296,12 +280,12 @@ describe("msteams file consent invoke authz", () => {
296280});
297281298282it("ignores cross-conversation decline invoke and keeps pending upload", async () => {
299-const { uploadId, handler, context, sendActivity } = createConsentInvokeHarness({
283+const { uploadId, context, sendActivity } = createConsentInvokeHarness({
300284invokeConversationId: "19:attacker@thread.v2",
301285action: "decline",
302286});
303287304-await handler.run(context);
288+await respondToMSTeamsFileConsentInvoke(context, log);
305289306290// invokeResponse should be sent immediately
307291expect(sendActivity).toHaveBeenCalledWith(
@@ -330,6 +314,7 @@ describe("msteams file consent invoke FS fallback", () => {
330314process.env.OPENCLAW_STATE_DIR = tmpDir;
331315setMSTeamsRuntime(createRuntimeStub(tmpDir));
332316clearPendingUploads();
317+vi.clearAllMocks();
333318fileConsentMockState.uploadToConsentUrl.mockReset();
334319fileConsentMockState.uploadToConsentUrl.mockResolvedValue(undefined);
335320});
@@ -387,14 +372,7 @@ describe("msteams file consent invoke FS fallback", () => {
387372 updateActivity,
388373} as unknown as MSTeamsTurnContext;
389374390-const handler = registerMSTeamsHandlers(
391-createActivityHandler(),
392-createDeps(),
393-) as MSTeamsActivityHandler & {
394-run: NonNullable<MSTeamsActivityHandler["run"]>;
395-};
396-397-await handler.run(context);
375+await respondToMSTeamsFileConsentInvoke(context, log);
398376399377// The upload should have run using the FS-loaded buffer
400378expect(fileConsentMockState.uploadToConsentUrl).toHaveBeenCalledTimes(1);
@@ -437,14 +415,7 @@ describe("msteams file consent invoke FS fallback", () => {
437415 updateActivity,
438416} as unknown as MSTeamsTurnContext;
439417440-const handler = registerMSTeamsHandlers(
441-createActivityHandler(),
442-createDeps(),
443-) as MSTeamsActivityHandler & {
444-run: NonNullable<MSTeamsActivityHandler["run"]>;
445-};
446-447-await handler.run(context);
418+await respondToMSTeamsFileConsentInvoke(context, log);
448419449420expect(fileConsentMockState.uploadToConsentUrl).not.toHaveBeenCalled();
450421expect(await getPendingUploadFs(uploadId)).toBeUndefined();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。