File size: 3,267 Bytes
fc93158
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { IrcClient } from "./client.js";
import type { CoreConfig } from "./types.js";

const hoisted = vi.hoisted(() => {
  const loadConfig = vi.fn();
  const resolveMarkdownTableMode = vi.fn(() => "preserve");
  const convertMarkdownTables = vi.fn((text: string) => text);
  const record = vi.fn();
  return {
    loadConfig,
    resolveMarkdownTableMode,
    convertMarkdownTables,
    record,
    resolveIrcAccount: vi.fn(() => ({
      configured: true,
      accountId: "default",
      host: "irc.example.com",
      nick: "openclaw",
      port: 6697,
      tls: true,
    })),
    normalizeIrcMessagingTarget: vi.fn((value: string) => value.trim()),
    connectIrcClient: vi.fn(),
    buildIrcConnectOptions: vi.fn(() => ({})),
  };
});

vi.mock("./runtime.js", () => ({
  getIrcRuntime: () => ({
    config: {
      loadConfig: hoisted.loadConfig,
    },
    channel: {
      text: {
        resolveMarkdownTableMode: hoisted.resolveMarkdownTableMode,
        convertMarkdownTables: hoisted.convertMarkdownTables,
      },
      activity: {
        record: hoisted.record,
      },
    },
  }),
}));

vi.mock("./accounts.js", () => ({
  resolveIrcAccount: hoisted.resolveIrcAccount,
}));

vi.mock("./normalize.js", () => ({
  normalizeIrcMessagingTarget: hoisted.normalizeIrcMessagingTarget,
}));

vi.mock("./client.js", () => ({
  connectIrcClient: hoisted.connectIrcClient,
}));

vi.mock("./connect-options.js", () => ({
  buildIrcConnectOptions: hoisted.buildIrcConnectOptions,
}));

vi.mock("./protocol.js", async () => {
  const actual = await vi.importActual<typeof import("./protocol.js")>("./protocol.js");
  return {
    ...actual,
    makeIrcMessageId: () => "irc-msg-1",
  };
});

import { sendMessageIrc } from "./send.js";

describe("sendMessageIrc cfg threading", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("uses explicitly provided cfg without loading runtime config", async () => {
    const providedCfg = { source: "provided" } as unknown as CoreConfig;
    const client = {
      isReady: vi.fn(() => true),
      sendPrivmsg: vi.fn(),
    } as unknown as IrcClient;

    const result = await sendMessageIrc("#room", "hello", {
      cfg: providedCfg,
      client,
      accountId: "work",
    });

    expect(hoisted.loadConfig).not.toHaveBeenCalled();
    expect(hoisted.resolveIrcAccount).toHaveBeenCalledWith({
      cfg: providedCfg,
      accountId: "work",
    });
    expect(client.sendPrivmsg).toHaveBeenCalledWith("#room", "hello");
    expect(result).toEqual({ messageId: "irc-msg-1", target: "#room" });
  });

  it("falls back to runtime config when cfg is omitted", async () => {
    const runtimeCfg = { source: "runtime" } as unknown as CoreConfig;
    hoisted.loadConfig.mockReturnValueOnce(runtimeCfg);
    const client = {
      isReady: vi.fn(() => true),
      sendPrivmsg: vi.fn(),
    } as unknown as IrcClient;

    await sendMessageIrc("#ops", "ping", { client });

    expect(hoisted.loadConfig).toHaveBeenCalledTimes(1);
    expect(hoisted.resolveIrcAccount).toHaveBeenCalledWith({
      cfg: runtimeCfg,
      accountId: undefined,
    });
    expect(client.sendPrivmsg).toHaveBeenCalledWith("#ops", "ping");
  });
});