|
1 | | -// Foreground Gmail service tests cover `openclaw webhooks gmail run` behavior. |
2 | 1 | import { EventEmitter } from "node:events"; |
3 | 2 | import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; |
4 | 3 |
|
@@ -82,44 +81,38 @@ describe("runGmailService", () => { |
82 | 81 | mocks.spawn.mockReset(); |
83 | 82 | }); |
84 | 83 |
|
85 | | - afterEach(async () => { |
| 84 | + afterEach(() => { |
86 | 85 | vi.useRealTimers(); |
87 | | - // Reset any leftover handlers from the previous run. |
88 | | - vi.restoreAllMocks(); |
89 | 86 | }); |
90 | 87 |
|
91 | | - it("catches renewal interval errors instead of letting them become unhandled rejections", async () => { |
| 88 | + it("logs rejected renewal commands", async () => { |
92 | 89 | vi.useFakeTimers(); |
93 | | - const unhandled: unknown[] = []; |
94 | | - const onUnhandled = (reason: unknown) => unhandled.push(reason); |
95 | | - process.on("unhandledRejection", onUnhandled); |
96 | | - |
97 | | - // Initial watch start succeeds; every renewal throws. |
98 | 90 | mocks.runCommandWithTimeout |
99 | 91 | .mockResolvedValueOnce({ code: 0, stdout: "", stderr: "" }) |
100 | 92 | .mockRejectedValue(new Error("renewal failed")); |
101 | 93 |
|
102 | 94 | const child = new EventEmitter(); |
103 | | - const kill = vi.fn((signal: string) => { |
104 | | - queueMicrotask(() => child.emit("exit", null, signal)); |
| 95 | + const kill = vi.fn(() => { |
| 96 | + child.emit("exit", null, "SIGTERM"); |
105 | 97 | return true; |
106 | 98 | }); |
107 | 99 | mocks.spawn.mockReturnValue(Object.assign(child, { kill, killed: false })); |
108 | 100 |
|
109 | | - // Start the service without awaiting; it runs until we signal shutdown. |
110 | | - const servicePromise = runGmailService({} as never); |
111 | | - |
112 | | - // Advance one full renewal cycle to trigger the interval callback. |
113 | | - await vi.advanceTimersByTimeAsync(720 * 60_000); |
114 | | - |
115 | | - // Shut down so the test can finish. |
116 | | - process.emit("SIGINT", "SIGINT"); |
117 | | - await servicePromise.catch(() => { |
118 | | - // The service may reject on forced shutdown; we only care about unhandled rejections. |
119 | | - }); |
120 | | - |
121 | | - process.off("unhandledRejection", onUnhandled); |
122 | | - |
123 | | - expect(unhandled).toHaveLength(0); |
| 101 | + const existingSigintListeners = new Set(process.rawListeners("SIGINT")); |
| 102 | + let shutdown: (() => void) | undefined; |
| 103 | + try { |
| 104 | + await runGmailService({}); |
| 105 | + shutdown = process |
| 106 | + .rawListeners("SIGINT") |
| 107 | + .find((listener) => !existingSigintListeners.has(listener)) as (() => void) | undefined; |
| 108 | + |
| 109 | + await vi.advanceTimersByTimeAsync(720 * 60_000); |
| 110 | + |
| 111 | + expect(mocks.defaultRuntime.error).toHaveBeenCalledWith( |
| 112 | + "gmail watch renew failed: Error: renewal failed", |
| 113 | + ); |
| 114 | + } finally { |
| 115 | + shutdown?.(); |
| 116 | + } |
124 | 117 | }); |
125 | 118 | }); |
0 commit comments