| import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; |
|
|
| const hoisted = vi.hoisted(() => ({ |
| loadConfig: vi.fn(), |
| resolveMarkdownTableMode: vi.fn(() => "preserve"), |
| convertMarkdownTables: vi.fn((text: string) => text), |
| record: vi.fn(), |
| resolveNextcloudTalkAccount: vi.fn(() => ({ |
| accountId: "default", |
| baseUrl: "https://nextcloud.example.com", |
| secret: "secret-value", |
| })), |
| generateNextcloudTalkSignature: vi.fn(() => ({ |
| random: "r", |
| signature: "s", |
| })), |
| })); |
|
|
| vi.mock("./runtime.js", () => ({ |
| getNextcloudTalkRuntime: () => ({ |
| config: { |
| loadConfig: hoisted.loadConfig, |
| }, |
| channel: { |
| text: { |
| resolveMarkdownTableMode: hoisted.resolveMarkdownTableMode, |
| convertMarkdownTables: hoisted.convertMarkdownTables, |
| }, |
| activity: { |
| record: hoisted.record, |
| }, |
| }, |
| }), |
| })); |
|
|
| vi.mock("./accounts.js", () => ({ |
| resolveNextcloudTalkAccount: hoisted.resolveNextcloudTalkAccount, |
| })); |
|
|
| vi.mock("./signature.js", () => ({ |
| generateNextcloudTalkSignature: hoisted.generateNextcloudTalkSignature, |
| })); |
|
|
| import { sendMessageNextcloudTalk, sendReactionNextcloudTalk } from "./send.js"; |
|
|
| describe("nextcloud-talk send cfg threading", () => { |
| const fetchMock = vi.fn<typeof fetch>(); |
|
|
| beforeEach(() => { |
| vi.clearAllMocks(); |
| fetchMock.mockReset(); |
| vi.stubGlobal("fetch", fetchMock); |
| }); |
|
|
| afterEach(() => { |
| vi.unstubAllGlobals(); |
| }); |
|
|
| it("uses provided cfg for sendMessage and skips runtime loadConfig", async () => { |
| const cfg = { source: "provided" } as const; |
| fetchMock.mockResolvedValueOnce( |
| new Response( |
| JSON.stringify({ |
| ocs: { data: { id: 12345, timestamp: 1_706_000_000 } }, |
| }), |
| { status: 200, headers: { "content-type": "application/json" } }, |
| ), |
| ); |
|
|
| const result = await sendMessageNextcloudTalk("room:abc123", "hello", { |
| cfg, |
| accountId: "work", |
| }); |
|
|
| expect(hoisted.loadConfig).not.toHaveBeenCalled(); |
| expect(hoisted.resolveNextcloudTalkAccount).toHaveBeenCalledWith({ |
| cfg, |
| accountId: "work", |
| }); |
| expect(fetchMock).toHaveBeenCalledTimes(1); |
| expect(result).toEqual({ |
| messageId: "12345", |
| roomToken: "abc123", |
| timestamp: 1_706_000_000, |
| }); |
| }); |
|
|
| it("falls back to runtime cfg for sendReaction when cfg is omitted", async () => { |
| const runtimeCfg = { source: "runtime" } as const; |
| hoisted.loadConfig.mockReturnValueOnce(runtimeCfg); |
| fetchMock.mockResolvedValueOnce(new Response("{}", { status: 200 })); |
|
|
| const result = await sendReactionNextcloudTalk("room:ops", "m-1", "👍", { |
| accountId: "default", |
| }); |
|
|
| expect(result).toEqual({ ok: true }); |
| expect(hoisted.loadConfig).toHaveBeenCalledTimes(1); |
| expect(hoisted.resolveNextcloudTalkAccount).toHaveBeenCalledWith({ |
| cfg: runtimeCfg, |
| accountId: "default", |
| }); |
| }); |
| }); |
|
|