@@ -11,6 +11,7 @@ import {
|
11 | 11 | } from "node:fs/promises"; |
12 | 12 | import os from "node:os"; |
13 | 13 | import path from "node:path"; |
| 14 | +import { MAX_TIMER_TIMEOUT_MS } from "openclaw/plugin-sdk/number-runtime"; |
14 | 15 | import { withEnvAsync } from "openclaw/plugin-sdk/test-env"; |
15 | 16 | import { beforeEach, describe, expect, it, vi } from "vitest"; |
16 | 17 | import type { API, Credentials, LoginQRCallbackEvent } from "./zca-client.js"; |
@@ -157,6 +158,30 @@ describe("zalouser credential persistence", () => {
|
157 | 158 | } |
158 | 159 | }); |
159 | 160 | |
| 161 | +it("caps oversized QR start timeout before computing the polling deadline", async () => { |
| 162 | +createZaloMock.mockResolvedValueOnce({ |
| 163 | +loginQR: async () => new Promise(() => undefined), |
| 164 | +}); |
| 165 | +const nowSpy = vi.spyOn(Date, "now"); |
| 166 | +nowSpy |
| 167 | +.mockReturnValueOnce(0) |
| 168 | +.mockReturnValueOnce(0) |
| 169 | +.mockReturnValueOnce(MAX_TIMER_TIMEOUT_MS + 1); |
| 170 | +try { |
| 171 | +const result = await startZaloQrLogin({ |
| 172 | +profile: "qr-timeout-cap", |
| 173 | +timeoutMs: Number.MAX_SAFE_INTEGER, |
| 174 | +}); |
| 175 | + |
| 176 | +expect(result.message).toBe( |
| 177 | +"Still preparing QR. Call wait to continue checking login status.", |
| 178 | +); |
| 179 | +expect(nowSpy).toHaveBeenCalledTimes(3); |
| 180 | +} finally { |
| 181 | +nowSpy.mockRestore(); |
| 182 | +} |
| 183 | +}); |
| 184 | + |
160 | 185 | it("rewrites restored sessions with cookies refreshed by zca-js login", async () => { |
161 | 186 | const stateDir = await mkdtemp(path.join(os.tmpdir(), "openclaw-zalouser-credentials-")); |
162 | 187 | const profile = "restore-refresh"; |
|