import assert from "node:assert/strict" import test from "node:test" import { deferred, loadTypeScriptModule } from "../test-support/load-typescript-module.mjs" const helpers = loadTypeScriptModule(new URL("../support-availability.ts", import.meta.url), {}, { Date, Intl, Set }) // Execute real API wrappers with offline transport and a deterministic deadline clock. function fixture(request, initialConfig = {}) { const timers = new Map() let timerId = 0 let runtimeConfig = initialConfig const api = loadTypeScriptModule(new URL("./support-availability.ts", import.meta.url), { "@/lib/api/client": { request }, "@/lib/support-availability": helpers, "@/lib/sdk/runtime-config": { readSupportChatRuntimeConfig: () => runtimeConfig }, }, { AbortController, process: { env: {} }, setTimeout(callback, delay) { const id = ++timerId timers.set(id, { callback, delay }) return id }, clearTimeout(id) { timers.delete(id) }, }) return { api, timers, setRuntimeConfig(value) { runtimeConfig = value }, } } test("calendar reads normalize nullable collections without changing the transport result", async () => { const transportResult = { teamId: 7, mode: "legacy", timezone: "", effectiveTimezone: "UTC", deploymentTimezone: "UTC", weekly: null, exceptions: [{ date: "2026-12-31", closed: true, periods: null }], } const f = fixture(async () => transportResult) const calendar = await f.api.fetchSupportCalendar(7) assert.equal(calendar.weekly.length, 0) assert.equal(calendar.exceptions[0].periods.length, 0) assert.equal(transportResult.weekly, null) assert.equal(transportResult.exceptions[0].periods, null) assert.equal(f.timers.size, 0) transportResult.exceptions = null assert.equal((await f.api.fetchSupportCalendar(7)).exceptions.length, 0) }) test("an already-aborted caller signal is not replaced with a live deadline signal", async () => { const caller = new AbortController() caller.abort() const f = fixture(async (_path, options) => { assert.equal(options.signal.aborted, true) throw new Error("cancelled fixture request") }) await assert.rejects(f.api.fetchMyAvailability(caller.signal), /cancelled fixture request/) assert.equal(f.timers.size, 0) }) test("the next availability read can recover after a deadline abort", async () => { let calls = 0 const f = fixture((_path, options) => { if (++calls > 1) return Promise.resolve({ userId: 42, eligible: false, reason: "offline" }) return new Promise((_, reject) => options.signal.addEventListener("abort", () => reject(new Error("fixture deadline")), { once: true })) }) const first = f.api.fetchMyAvailability() const deadline = [...f.timers.values()][0] assert.equal(deadline.delay, 10000) deadline.callback() await assert.rejects(first, /fixture deadline/) assert.equal(f.timers.size, 0) const next = await f.api.fetchMyAvailability() assert.equal(next.userId, 42) assert.equal(next.eligible, false) assert.equal(f.timers.size, 0) }) test("concurrent availability reads own separate abort signals and deadlines", async () => { const pending = [] const f = fixture((_path, options) => { const response = deferred() options.signal.addEventListener("abort", () => response.reject(new Error("fixture deadline")), { once: true }) pending.push({ ...response, signal: options.signal }) return response.promise }) const first = f.api.fetchMyAvailability() const second = f.api.fetchAvailabilityAgents(19) assert.equal(f.timers.size, 2) assert.notEqual(pending[0].signal, pending[1].signal) ;[...f.timers.values()][0].callback() await assert.rejects(first, /fixture deadline/) assert.equal(pending[1].signal.aborted, false) pending[1].resolve([]) assert.equal((await second).length, 0) assert.equal(f.timers.size, 0) }) test("settled reads remove the caller's abort listener on both success and failure", async () => { for (const fail of [false, true]) { const listeners = new Set() const signal = { aborted: false, addEventListener(event, listener) { assert.equal(event, "abort"); listeners.add(listener) }, removeEventListener(event, listener) { assert.equal(event, "abort"); assert.equal(listeners.delete(listener), true) }, } const f = fixture(async () => { assert.equal(listeners.size, 1) if (fail) throw new Error("fixture transport failure") return null }) const pending = f.api.fetchMyAvailability(signal) if (fail) await assert.rejects(pending, /fixture transport failure/) else assert.equal(await pending, null) assert.equal(listeners.size, 0) assert.equal(f.timers.size, 0) } }) test("each public check reads the current runtime channel and endpoint rather than caching the prior identity", async () => { const calls = [] const f = fixture(async (path, options) => { calls.push({ path, options }) return { available: false, reason: "temporarily_absent", timezone: "UTC" } }, { channelId: "channel-a", apiBaseUrl: "https://first.example.invalid/", baseUrl: "https://unused.example.invalid/" }) await f.api.fetchPublicSupportStatus() f.setRuntimeConfig({ channelId: "channel-b", baseUrl: "https://second.example.invalid/" }) await f.api.fetchPublicSupportStatus() assert.deepEqual(calls.map(({ options }) => options.baseUrl), ["https://first.example.invalid", "https://second.example.invalid"]) assert.deepEqual(calls.map(({ options }) => options.headers["X-Channel-Id"]), ["channel-a", "channel-b"]) for (const { path, options } of calls) { assert.equal(path, "/api/support/status") assert.equal(options.skipAuth, true) assert.deepEqual(Object.keys(options.headers), ["X-Channel-Id"]) assert.equal(options.body, undefined) } }) test("successful public HTTP requests never manufacture human availability", async () => { for (const reason of ["outside_hours", "temporarily_absent", "capacity"]) { const response = { available: false, reason, timezone: "UTC", nextOpeningAt: "2026-12-31T09:00:00Z" } const f = fixture(async () => response) assert.equal(await f.api.fetchPublicSupportStatus(), response) assert.equal(response.available, false) assert.equal(f.timers.size, 0) } })