Files
mono 2f7a491666 feat: harden support, localize knowledge and add operator availability [skip ci]
Source-only publication of reviewed commit 64e96a7f423673dc29ad56485be9fc79bce8af1c.

Passed in isolation: focused frontend/backend tests, race checks, TypeScript typecheck, lint, Go compilation, Flowgram build, and deterministic SDK build/tests.

Not accepted as a production release: Next.js export/native assembly remains blocked by environment memory limits; browser interaction and MySQL staging acceptance remain unverified. No production server, database/schema, runtime configuration, deployment, release tag, or workflow execution was performed.

Expected source tree: 0a4a7528e9.
2026-10-16 15:21:42 +00:00

113 lines
7.0 KiB
JavaScript

import assert from "node:assert/strict"
import { readFile } from "node:fs/promises"
import test from "node:test"
import vm from "node:vm"
import ts from "typescript"
async function compile(path, imports) {
const source = await readFile(new URL(path, import.meta.url), "utf8")
const compiled = ts.transpileModule(source, { compilerOptions: { target: ts.ScriptTarget.ES2020, module: ts.ModuleKind.CommonJS, jsx: ts.JsxEmit.ReactJSX } })
const loaded = { exports: {} }
vm.runInNewContext(compiled.outputText, { exports: loaded.exports, module: loaded, Intl, Date, Set, AbortController, setTimeout, clearTimeout, require: name => { assert.ok(name in imports, `unexpected import ${name}`); return imports[name] } })
return loaded.exports
}
const helpers = await compile("../../lib/support-availability.ts", {})
const enums = await compile("../../lib/generated/enums.ts", {})
const mappings = await compile("../../lib/support-availability-i18n.ts", { "@/lib/generated/enums": enums })
const guard = await compile("../../lib/session-request-guard.ts", {})
const sessionA = { user: { id: 1 }, accessToken: "fixture-a" }
const sessionB = { user: { id: 2 }, accessToken: "fixture-b" }
const calendar = { teamId: 5, mode: "recurring", timezone: "UTC", effectiveTimezone: "UTC", deploymentTimezone: "UTC", weekly: [], exceptions: [] }
const operator = { userId: 1, serviceStatus: 1, effectiveServiceStatus: 1, returnServiceStatus: 0, reason: "busy", online: true, calendar }
function deferred() { let resolve; const promise = new Promise(r => { resolve = r }); return { promise, resolve } }
function find(node, predicate) {
if (!node || typeof node !== "object") return null
if (predicate(node)) return node
for (const value of Object.values(node.props ?? {})) {
for (const child of Array.isArray(value) ? value.flat(Infinity) : [value]) {
const found = find(child, predicate)
if (found) return found
}
}
return null
}
async function harness(kind, options = {}) {
let session = sessionA, stateIndex = 0
const effects = [], calls = [], saved = []
const apiResult = options.apiResult ?? Promise.resolve(operator)
const formValues = options.formValues ?? { serviceStatus: "1", start: "", end: "", startOccurrence: "", endOccurrence: "" }
const jsx = (type, props, key) => ({ type, props, key })
const controls = new Proxy({}, { get: (_target, name) => name })
const imports = {
"react/jsx-runtime": { jsx, jsxs: jsx, Fragment: "Fragment" },
react: { useRef: value => ({ current: value }), useState: value => { const current = stateIndex++; return [current === 0 && options.editing ? true : typeof value === "function" ? value() : value, () => {}] }, useEffect: fn => { effects.push(fn) }, useCallback: fn => fn },
"react-hook-form": { Controller: "Controller", useFieldArray: () => ({ fields: [] }), useForm: () => ({ control: {}, register: () => ({}), handleSubmit: fn => fn, watch: key => key ? formValues[key] : calendar, setError: () => {}, clearErrors: () => {}, reset: () => {}, formState: { errors: {}, isDirty: true } }) },
"lucide-react": controls, "next/link": { default: "Link" }, sonner: { toast: { success: () => {} } },
"@/components/auth-provider": { useAuth: () => ({ session }) },
"@/components/confirm-provider": { useConfirm: () => options.confirm ?? (async () => true) },
"@/components/option-combobox": controls, "@/components/project-dialog": controls,
"@/components/ui/badge": controls, "@/components/ui/button": controls, "@/components/ui/field": controls, "@/components/ui/input": controls, "@/components/ui/switch": controls,
"@/i18n/provider": { useI18n: () => key => key, useAppLocale: () => ({ locale: "en-US" }) },
"@/lib/auth": { readSession: () => session }, "@/lib/session-request-guard": guard,
"@/lib/generated/enums": enums, "@/lib/support-availability-i18n": mappings, "@/lib/support-availability": helpers,
"@/components/support-availability/operator-status": { notifyAvailabilityUpdated: () => {} },
"@/lib/api/support-availability": { updateMyAvailability: payload => { calls.push(payload); return apiResult }, updateAgentAvailability: (id, payload) => { calls.push({ id, payload }); return apiResult }, updateSupportCalendar: payload => { calls.push(payload); return options.apiResult ?? Promise.resolve(calendar) } },
}
const file = kind === "operator" ? "./operator-status.tsx" : "../../app/(dashboard)/dashboard/support-availability/_components/calendar-editor.tsx"
const loaded = await compile(file, imports)
const root = kind === "operator" ? loaded.OperatorStatusDialog({ value: operator, onClose() {}, onSaved: value => saved.push(value) }) : loaded.CalendarEditor({ initial: calendar, writable: options.writable ?? true, onDirtyChange() {}, onSaved: value => saved.push(value) })
// Execute only lifetime effects: calendar also registers browser navigation listeners.
const lifetime = effects.filter(fn => fn.toString().includes("mounted.current = true"))
assert.equal(lifetime.length, 1)
const setup = () => lifetime[0]()
const submit = find(root, node => node.type === "form").props.onSubmit
return { calls, saved, setup, submit: () => submit(kind === "operator" ? formValues : calendar), switchSession: () => { session = sessionB } }
}
test("operator save still completes after StrictMode setup-cleanup-setup", async () => {
const h = await harness("operator")
h.setup()(); h.setup()
await h.submit()
assert.equal(h.calls.length, 1)
assert.equal(h.saved.length, 1)
})
test("operator save is single-flight and a late prior-session result is ignored", async () => {
const pending = deferred()
const h = await harness("operator", { apiResult: pending.promise })
h.setup()
const first = h.submit(), second = h.submit()
h.switchSession(); pending.resolve(operator)
await Promise.all([first, second])
assert.equal(h.calls.length, 1)
assert.equal(h.saved.length, 0)
})
test("operator controls from a stale session cannot submit a mutation", async () => {
const h = await harness("operator")
h.setup(); h.switchSession(); await h.submit()
assert.equal(h.calls.length, 0)
})
test("read-only calendar or preview Enter cannot save even when form appears dirty", async () => {
for (const writable of [false, true]) {
const h = await harness("calendar", { writable })
h.setup(); await h.submit()
assert.equal(h.calls.length, 0)
}
})
test("calendar confirmation cannot cross session or unmount boundaries", async () => {
for (const action of ["session", "unmount"]) {
const approval = deferred()
const h = await harness("calendar", { editing: true, confirm: () => approval.promise })
const cleanup = h.setup()
const submit = h.submit()
if (action === "session") h.switchSession(); else cleanup()
approval.resolve(true); await submit
assert.equal(h.calls.length, 0)
}
})
test("calendar save completes after StrictMode restart and explicit confirmation", async () => {
const h = await harness("calendar", { editing: true })
h.setup()(); h.setup(); await h.submit()
assert.equal(h.calls.length, 1)
assert.equal(h.saved.length, 1)
})