From a62d55b2837669174d6519d990d593b4f71d86b8 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 1 Mar 2026 23:59:59 +0000 Subject: [PATCH] test(discord): cover DM command decision flow --- src/discord/monitor/dm-command-auth.test.ts | 16 +++ .../monitor/dm-command-decision.test.ts | 114 ++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 src/discord/monitor/dm-command-decision.test.ts diff --git a/src/discord/monitor/dm-command-auth.test.ts b/src/discord/monitor/dm-command-auth.test.ts index 041eb82b41b..ce92b06fb7b 100644 --- a/src/discord/monitor/dm-command-auth.test.ts +++ b/src/discord/monitor/dm-command-auth.test.ts @@ -38,6 +38,22 @@ describe("resolveDiscordDmCommandAccess", () => { expect(result.commandAuthorized).toBe(true); }); + it("keeps command auth enabled for open DMs when configured allowlist does not match", async () => { + const result = await resolveDiscordDmCommandAccess({ + accountId: "default", + dmPolicy: "open", + configuredAllowFrom: ["discord:999"], + sender, + allowNameMatching: false, + useAccessGroups: true, + readStoreAllowFrom: async () => [], + }); + + expect(result.decision).toBe("allow"); + expect(result.allowMatch.allowed).toBe(false); + expect(result.commandAuthorized).toBe(true); + }); + it("returns pairing decision and unauthorized command auth for unknown senders", async () => { const result = await resolveDiscordDmCommandAccess({ accountId: "default", diff --git a/src/discord/monitor/dm-command-decision.test.ts b/src/discord/monitor/dm-command-decision.test.ts new file mode 100644 index 00000000000..1847ec2e56e --- /dev/null +++ b/src/discord/monitor/dm-command-decision.test.ts @@ -0,0 +1,114 @@ +import { describe, expect, it, vi } from "vitest"; +import type { DiscordDmCommandAccess } from "./dm-command-auth.js"; +import { handleDiscordDmCommandDecision } from "./dm-command-decision.js"; + +function buildDmAccess(overrides: Partial): DiscordDmCommandAccess { + return { + decision: "allow", + reason: "ok", + commandAuthorized: true, + allowMatch: { allowed: true, matchKey: "123", matchSource: "id" }, + ...overrides, + }; +} + +describe("handleDiscordDmCommandDecision", () => { + it("returns true for allowed DM access", async () => { + const onPairingCreated = vi.fn(async () => {}); + const onUnauthorized = vi.fn(async () => {}); + const upsertPairingRequest = vi.fn(async () => ({ code: "PAIR-1", created: true })); + + const allowed = await handleDiscordDmCommandDecision({ + dmAccess: buildDmAccess({ decision: "allow" }), + accountId: "default", + sender: { id: "123", tag: "alice#0001", name: "alice" }, + onPairingCreated, + onUnauthorized, + upsertPairingRequest, + }); + + expect(allowed).toBe(true); + expect(upsertPairingRequest).not.toHaveBeenCalled(); + expect(onPairingCreated).not.toHaveBeenCalled(); + expect(onUnauthorized).not.toHaveBeenCalled(); + }); + + it("creates pairing reply for new pairing requests", async () => { + const onPairingCreated = vi.fn(async () => {}); + const onUnauthorized = vi.fn(async () => {}); + const upsertPairingRequest = vi.fn(async () => ({ code: "PAIR-1", created: true })); + + const allowed = await handleDiscordDmCommandDecision({ + dmAccess: buildDmAccess({ + decision: "pairing", + commandAuthorized: false, + allowMatch: { allowed: false }, + }), + accountId: "default", + sender: { id: "123", tag: "alice#0001", name: "alice" }, + onPairingCreated, + onUnauthorized, + upsertPairingRequest, + }); + + expect(allowed).toBe(false); + expect(upsertPairingRequest).toHaveBeenCalledWith({ + channel: "discord", + id: "123", + accountId: "default", + meta: { + tag: "alice#0001", + name: "alice", + }, + }); + expect(onPairingCreated).toHaveBeenCalledWith("PAIR-1"); + expect(onUnauthorized).not.toHaveBeenCalled(); + }); + + it("skips pairing reply when pairing request already exists", async () => { + const onPairingCreated = vi.fn(async () => {}); + const onUnauthorized = vi.fn(async () => {}); + const upsertPairingRequest = vi.fn(async () => ({ code: "PAIR-1", created: false })); + + const allowed = await handleDiscordDmCommandDecision({ + dmAccess: buildDmAccess({ + decision: "pairing", + commandAuthorized: false, + allowMatch: { allowed: false }, + }), + accountId: "default", + sender: { id: "123", tag: "alice#0001", name: "alice" }, + onPairingCreated, + onUnauthorized, + upsertPairingRequest, + }); + + expect(allowed).toBe(false); + expect(onPairingCreated).not.toHaveBeenCalled(); + expect(onUnauthorized).not.toHaveBeenCalled(); + }); + + it("runs unauthorized handler for blocked DM access", async () => { + const onPairingCreated = vi.fn(async () => {}); + const onUnauthorized = vi.fn(async () => {}); + const upsertPairingRequest = vi.fn(async () => ({ code: "PAIR-1", created: true })); + + const allowed = await handleDiscordDmCommandDecision({ + dmAccess: buildDmAccess({ + decision: "block", + commandAuthorized: false, + allowMatch: { allowed: false }, + }), + accountId: "default", + sender: { id: "123", tag: "alice#0001", name: "alice" }, + onPairingCreated, + onUnauthorized, + upsertPairingRequest, + }); + + expect(allowed).toBe(false); + expect(onUnauthorized).toHaveBeenCalledTimes(1); + expect(upsertPairingRequest).not.toHaveBeenCalled(); + expect(onPairingCreated).not.toHaveBeenCalled(); + }); +});