
























@@ -1,8 +1,9 @@
11import type { Client, Plugin } from "@buape/carbon";
2-import { describe, expect, it, vi } from "vitest";
2+import { beforeEach, describe, expect, it, vi } from "vitest";
334-const { registerVoiceClientSpy } = vi.hoisted(() => ({
4+const { registerVoiceClientSpy, waitForDiscordGatewayPluginRegistrationMock } = vi.hoisted(() => ({
55registerVoiceClientSpy: vi.fn(),
6+waitForDiscordGatewayPluginRegistrationMock: vi.fn(),
67}));
7889vi.mock("@buape/carbon/voice", () => ({
@@ -51,6 +52,7 @@ vi.mock("./auto-presence.js", () => ({
51525253vi.mock("./gateway-plugin.js", () => ({
5354createDiscordGatewayPlugin: vi.fn(),
55+waitForDiscordGatewayPluginRegistration: waitForDiscordGatewayPluginRegistrationMock,
5456}));
55575658vi.mock("./gateway-supervisor.js", () => ({
@@ -73,16 +75,50 @@ vi.mock("./presence.js", () => ({
7375import { createDiscordMonitorClient } from "./provider.startup.js";
74767577describe("createDiscordMonitorClient", () => {
76-it("adds listener compat for legacy voice plugins", () => {
78+beforeEach(() => {
7779registerVoiceClientSpy.mockReset();
80+waitForDiscordGatewayPluginRegistrationMock.mockReset().mockReturnValue(undefined);
81+});
788283+function createRuntime() {
84+return {
85+log: vi.fn(),
86+error: vi.fn(),
87+exit: vi.fn(),
88+};
89+}
90+91+function createClientWithPlugins(
92+_options: ConstructorParameters<typeof import("@buape/carbon").Client>[0],
93+handlers: ConstructorParameters<typeof import("@buape/carbon").Client>[1],
94+plugins: Plugin[] = [],
95+) {
96+const pluginRegistry = plugins.map((plugin) => ({ id: plugin.id, plugin }));
97+return {
98+listeners: [...(handlers.listeners ?? [])],
99+plugins: pluginRegistry,
100+getPlugin: (id: string) => pluginRegistry.find((entry) => entry.id === id)?.plugin,
101+} as Client;
102+}
103+104+function createAutoPresenceController() {
105+return {
106+enabled: false,
107+start: vi.fn(),
108+stop: vi.fn(),
109+refresh: vi.fn(),
110+runNow: vi.fn(),
111+};
112+}
113+114+it("adds listener compat for legacy voice plugins", async () => {
79115const gatewayPlugin = {
80116id: "gateway",
81117registerClient: vi.fn(),
82118registerRoutes: vi.fn(),
83119} as Plugin;
8412085-const result = createDiscordMonitorClient({
121+const result = await createDiscordMonitorClient({
86122accountId: "default",
87123applicationId: "app-1",
88124token: "token-1",
@@ -91,29 +127,11 @@ describe("createDiscordMonitorClient", () => {
91127modals: [],
92128voiceEnabled: true,
93129discordConfig: {},
94-runtime: {
95-log: vi.fn(),
96-error: vi.fn(),
97-exit: vi.fn(),
98-},
99-createClient: (_options, handlers, plugins = []) => {
100-const pluginRegistry = plugins.map((plugin) => ({ id: plugin.id, plugin }));
101-return {
102-listeners: [...(handlers.listeners ?? [])],
103-plugins: pluginRegistry,
104-getPlugin: (id: string) => pluginRegistry.find((entry) => entry.id === id)?.plugin,
105-} as Client;
106-},
130+runtime: createRuntime(),
131+createClient: createClientWithPlugins,
107132createGatewayPlugin: () => gatewayPlugin as never,
108133createGatewaySupervisor: () => ({ shutdown: vi.fn(), handleError: vi.fn() }) as never,
109-createAutoPresenceController: () =>
110-({
111-enabled: false,
112-start: vi.fn(),
113-stop: vi.fn(),
114-refresh: vi.fn(),
115-runNow: vi.fn(),
116-}) as never,
134+createAutoPresenceController: () => createAutoPresenceController() as never,
117135isDisallowedIntentsError: () => false,
118136});
119137@@ -122,4 +140,73 @@ describe("createDiscordMonitorClient", () => {
122140expect.arrayContaining([expect.objectContaining({ type: "legacy-voice-listener" })]),
123141);
124142});
143+144+it("waits for gateway registration before creating the supervisor", async () => {
145+const gatewayPlugin = { id: "gateway" } as Plugin;
146+let resolveRegistration: (() => void) | undefined;
147+const registration = new Promise<void>((resolve) => {
148+resolveRegistration = resolve;
149+});
150+waitForDiscordGatewayPluginRegistrationMock.mockReturnValue(registration);
151+const gatewaySupervisor = { shutdown: vi.fn(), handleError: vi.fn() };
152+const createGatewaySupervisor = vi.fn(() => gatewaySupervisor);
153+154+const resultPromise = createDiscordMonitorClient({
155+accountId: "default",
156+applicationId: "app-1",
157+token: "token-1",
158+commands: [],
159+components: [],
160+modals: [],
161+voiceEnabled: false,
162+discordConfig: {},
163+runtime: createRuntime(),
164+createClient: createClientWithPlugins,
165+createGatewayPlugin: () => gatewayPlugin as never,
166+createGatewaySupervisor: createGatewaySupervisor as never,
167+createAutoPresenceController: () => createAutoPresenceController() as never,
168+isDisallowedIntentsError: () => false,
169+});
170+await Promise.resolve();
171+172+expect(waitForDiscordGatewayPluginRegistrationMock).toHaveBeenCalledWith(gatewayPlugin);
173+expect(createGatewaySupervisor).not.toHaveBeenCalled();
174+175+resolveRegistration?.();
176+const result = await resultPromise;
177+178+expect(createGatewaySupervisor).toHaveBeenCalledTimes(1);
179+expect(result.gatewaySupervisor).toBe(gatewaySupervisor);
180+});
181+182+it("propagates gateway registration failures before supervisor startup", async () => {
183+const gatewayPlugin = { id: "gateway" } as Plugin;
184+const createGatewaySupervisor = vi.fn();
185+const createAutoPresenceControllerForTest = vi.fn(createAutoPresenceController);
186+waitForDiscordGatewayPluginRegistrationMock.mockReturnValue(
187+Promise.reject(new Error("gateway metadata denied")),
188+);
189+190+await expect(
191+createDiscordMonitorClient({
192+accountId: "default",
193+applicationId: "app-1",
194+token: "token-1",
195+commands: [],
196+components: [],
197+modals: [],
198+voiceEnabled: false,
199+discordConfig: {},
200+runtime: createRuntime(),
201+createClient: createClientWithPlugins,
202+createGatewayPlugin: () => gatewayPlugin as never,
203+createGatewaySupervisor: createGatewaySupervisor as never,
204+createAutoPresenceController: createAutoPresenceControllerForTest as never,
205+isDisallowedIntentsError: () => false,
206+}),
207+).rejects.toThrow("gateway metadata denied");
208+209+expect(createGatewaySupervisor).not.toHaveBeenCalled();
210+expect(createAutoPresenceControllerForTest).not.toHaveBeenCalled();
211+});
125212});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。