






















@@ -184,6 +184,35 @@ describe("runDiscordGatewayLifecycle", () => {
184184expect(params.gatewaySupervisor.detachLifecycle).toHaveBeenCalledTimes(params.detachCalls ?? 1);
185185}
186186187+function mockMessages(mock: ReturnType<typeof vi.fn>): string[] {
188+return mock.mock.calls.map((call) => String(call[0] ?? ""));
189+}
190+191+function expectMockMessageContains(mock: ReturnType<typeof vi.fn>, expected: string): void {
192+expect(mockMessages(mock).some((message) => message.includes(expected))).toBe(true);
193+}
194+195+function expectMockMessageNotContains(mock: ReturnType<typeof vi.fn>, expected: string): void {
196+expect(mockMessages(mock).every((message) => !message.includes(expected))).toBe(true);
197+}
198+199+type StatusPatch = {
200+connected?: boolean;
201+lastDisconnect?: null | Record<string, unknown>;
202+lastError?: string | null;
203+};
204+205+function statusPatches(statusSink: ReturnType<typeof vi.fn>): StatusPatch[] {
206+return statusSink.mock.calls.map((call) => call[0] as StatusPatch);
207+}
208+209+function expectStatusPatch(
210+statusSink: ReturnType<typeof vi.fn>,
211+predicate: (patch: StatusPatch) => boolean,
212+): void {
213+expect(statusPatches(statusSink).some(predicate)).toBe(true);
214+}
215+187216it("resolves gateway READY timeouts from config, env, then defaults", () => {
188217expect(resolveDiscordGatewayReadyTimeoutMs({ configuredTimeoutMs: 45_000 })).toBe(45_000);
189218expect(
@@ -240,11 +269,9 @@ describe("runDiscordGatewayLifecycle", () => {
240269const { lifecycleParams, statusSink } = createLifecycleHarness({ gateway });
241270await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
242271243-expect(statusSink).toHaveBeenCalledWith(
244-expect.objectContaining({
245-connected: true,
246-lastDisconnect: null,
247-}),
272+expectStatusPatch(
273+statusSink,
274+(patch) => patch.connected === true && patch.lastDisconnect === null,
248275);
249276});
250277@@ -266,11 +293,7 @@ describe("runDiscordGatewayLifecycle", () => {
266293await expect(lifecyclePromise).rejects.toThrow(
267294"discord gateway did not reach READY within 5000ms",
268295);
269-expect(statusSink).not.toHaveBeenCalledWith(
270-expect.objectContaining({
271-connected: true,
272-}),
273-);
296+expect(statusPatches(statusSink).every((patch) => patch.connected !== true)).toBe(true);
274297expectLifecycleCleanup({
275298 threadStop,
276299waitCalls: 0,
@@ -352,21 +375,18 @@ describe("runDiscordGatewayLifecycle", () => {
352375await vi.advanceTimersByTimeAsync(18_500);
353376await expect(lifecyclePromise).resolves.toBeUndefined();
354377355-expect(runtimeError).toHaveBeenCalledWith(
356-expect.stringContaining("gateway READY wait timed out after 15000ms"),
357-);
358-expect(runtimeError).not.toHaveBeenCalledWith(
359-expect.stringContaining("gateway was not ready after 15000ms; restarting gateway"),
378+expectMockMessageContains(runtimeError, "gateway READY wait timed out after 15000ms");
379+expectMockMessageNotContains(
380+runtimeError,
381+"gateway was not ready after 15000ms; restarting gateway",
360382);
361383expect(gateway.disconnect).toHaveBeenCalledTimes(1);
362384expect(gateway.connect).toHaveBeenCalledTimes(1);
363385expect(gateway.connect).toHaveBeenCalledWith(false);
364-expect(statusSink).toHaveBeenCalledWith(
365-expect.objectContaining({
366-connected: true,
367-lastDisconnect: null,
368-lastError: null,
369-}),
386+expectStatusPatch(
387+statusSink,
388+(patch) =>
389+patch.connected === true && patch.lastDisconnect === null && patch.lastError === null,
370390);
371391} finally {
372392vi.useRealTimers();
@@ -447,9 +467,7 @@ describe("runDiscordGatewayLifecycle", () => {
447467448468await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
449469450-expect(runtimeError).toHaveBeenCalledWith(
451-expect.stringContaining("discord: gateway closed with code 4014"),
452-);
470+expectMockMessageContains(runtimeError, "discord: gateway closed with code 4014");
453471expectLifecycleCleanup({
454472 threadStop,
455473waitCalls: 0,
@@ -466,8 +484,9 @@ describe("runDiscordGatewayLifecycle", () => {
466484467485await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
468486469-expect(runtimeError).toHaveBeenCalledWith(
470-expect.stringContaining("discord gateway error: Error: transient startup error"),
487+expectMockMessageContains(
488+runtimeError,
489+"discord gateway error: Error: transient startup error",
471490);
472491expectLifecycleCleanup({
473492 threadStop,
@@ -550,15 +569,15 @@ describe("runDiscordGatewayLifecycle", () => {
550569await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
551570552571expect(gatewaySupervisor.attachLifecycle).toHaveBeenCalledTimes(1);
553-expect(runtimeLog).toHaveBeenCalledWith(
554-expect.stringContaining("treating reconnect-exhausted during expected shutdown as clean"),
555-);
556-expect(runtimeLog).toHaveBeenCalledWith(
557-expect.stringContaining("Max reconnect attempts (50) reached after close code 1005"),
572+expectMockMessageContains(
573+runtimeLog,
574+"treating reconnect-exhausted during expected shutdown as clean",
558575);
559-expect(runtimeError).not.toHaveBeenCalledWith(
560-expect.stringContaining("discord gateway reconnect-exhausted"),
576+expectMockMessageContains(
577+runtimeLog,
578+"Max reconnect attempts (50) reached after close code 1005",
561579);
580+expectMockMessageNotContains(runtimeError, "discord gateway reconnect-exhausted");
562581expectLifecycleCleanup({
563582 threadStop,
564583waitCalls: 1,
@@ -590,8 +609,9 @@ describe("runDiscordGatewayLifecycle", () => {
590609await expect(lifecyclePromise).rejects.toThrow(
591610"discord gateway fatal: Error: Fatal Gateway error: 4001",
592611);
593-expect(runtimeError).toHaveBeenCalledWith(
594-expect.stringContaining("discord gateway fatal: Error: Fatal Gateway error: 4001"),
612+expectMockMessageContains(
613+runtimeError,
614+"discord gateway fatal: Error: Fatal Gateway error: 4001",
595615);
596616expect(gateway.disconnect).not.toHaveBeenCalled();
597617expect(gateway.connect).not.toHaveBeenCalled();
@@ -617,11 +637,12 @@ describe("runDiscordGatewayLifecycle", () => {
617637618638await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
619639620-expect(statusSink).toHaveBeenCalledWith(
621-expect.objectContaining({
622-connected: false,
623-lastDisconnect: expect.objectContaining({ status: 1006 }),
624-}),
640+expectStatusPatch(
641+statusSink,
642+(patch) =>
643+patch.connected === false &&
644+patch.lastDisconnect !== null &&
645+patch.lastDisconnect?.status === 1006,
625646);
626647});
627648@@ -637,11 +658,11 @@ describe("runDiscordGatewayLifecycle", () => {
637658638659await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
639660640-expect(statusSink).toHaveBeenCalledWith(
641-expect.objectContaining({
642- connected: false,
643-lastError: "Gateway reconnect scheduled in 1000ms (zombie, resume=true)",
644-}),
661+expectStatusPatch(
662+statusSink,
663+(patch) =>
664+patch.connected === false &&
665+ patch.lastError === "Gateway reconnect scheduled in 1000ms (zombie, resume=true)",
645666);
646667});
647668@@ -664,12 +685,10 @@ describe("runDiscordGatewayLifecycle", () => {
664685665686await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
666687667-expect(statusSink).toHaveBeenCalledWith(expect.objectContaining({ connected: false }));
668-expect(statusSink).toHaveBeenCalledWith(
669-expect.objectContaining({
670-connected: true,
671-lastDisconnect: null,
672-}),
688+expectStatusPatch(statusSink, (patch) => patch.connected === false);
689+expectStatusPatch(
690+statusSink,
691+(patch) => patch.connected === true && patch.lastDisconnect === null,
673692);
674693} finally {
675694vi.useRealTimers();
@@ -700,14 +719,13 @@ describe("runDiscordGatewayLifecycle", () => {
700719await expect(lifecyclePromise).rejects.toThrow(
701720"discord gateway opened but did not reach READY within 5000ms",
702721);
703-expect(runtimeError).toHaveBeenCalledWith(
704-expect.stringContaining("did not reach READY within 5000ms"),
705-);
706-expect(statusSink).toHaveBeenCalledWith(
707-expect.objectContaining({
708-connected: false,
709-lastDisconnect: expect.objectContaining({ error: "runtime-not-ready" }),
710-}),
722+expectMockMessageContains(runtimeError, "did not reach READY within 5000ms");
723+expectStatusPatch(
724+statusSink,
725+(patch) =>
726+patch.connected === false &&
727+patch.lastDisconnect !== null &&
728+patch.lastDisconnect?.error === "runtime-not-ready",
711729);
712730} finally {
713731vi.useRealTimers();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。