diff options
Diffstat (limited to 'src/features/surface-host')
| -rw-r--r-- | src/features/surface-host/index.ts | 1 | ||||
| -rw-r--r-- | src/features/surface-host/logic/message-queue.test.ts | 35 | ||||
| -rw-r--r-- | src/features/surface-host/logic/message-queue.ts | 10 |
3 files changed, 46 insertions, 0 deletions
diff --git a/src/features/surface-host/index.ts b/src/features/surface-host/index.ts index 1e21e3d..f6a3041 100644 --- a/src/features/surface-host/index.ts +++ b/src/features/surface-host/index.ts @@ -1,3 +1,4 @@ +export { MESSAGE_QUEUE_RENDERER_ID, messageQueueCount } from "./logic/message-queue"; export { buildInvoke, planSurface } from "./logic/plan"; export type { FieldView, SurfaceRenderPlan } from "./logic/types"; export { default as SurfaceView } from "./ui/SurfaceView.svelte"; diff --git a/src/features/surface-host/logic/message-queue.test.ts b/src/features/surface-host/logic/message-queue.test.ts index ae91c8f..93256b4 100644 --- a/src/features/surface-host/logic/message-queue.test.ts +++ b/src/features/surface-host/logic/message-queue.test.ts @@ -1,6 +1,8 @@ +import type { SurfaceSpec } from "@dispatch/ui-contract"; import type { QueuedMessage } from "@dispatch/wire"; import { describe, expect, it } from "vitest"; import { + messageQueueCount, parseMessageQueuePayload, reconcileCancelledIds, selectVisibleMessages, @@ -103,3 +105,36 @@ describe("reconcileCancelledIds", () => { expect([...result]).toEqual(["m2"]); }); }); + +describe("messageQueueCount", () => { + const spec = (payload: unknown): SurfaceSpec => ({ + id: "message-queue", + region: "inline", + title: "Message queue", + fields: [{ kind: "custom", rendererId: "message-queue", payload }], + }); + + it("counts messages, including image-only input", () => { + expect(messageQueueCount(spec({ messages: [msg("m1", ""), msg("m2", "next")] }))).toBe(2); + }); + + it("distinguishes an empty queue from an unavailable snapshot", () => { + expect(messageQueueCount(spec({ messages: [] }))).toBe(0); + expect(messageQueueCount(null)).toBeUndefined(); + }); + + it("returns unknown for missing fields or a different renderer", () => { + expect(messageQueueCount({ ...spec(null), fields: [] })).toBeUndefined(); + expect( + messageQueueCount({ + ...spec(null), + fields: [{ kind: "custom", rendererId: "other", payload: { messages: [msg("m1", "x")] } }], + }), + ).toBeUndefined(); + }); + + it("returns unknown for malformed payloads", () => { + expect(messageQueueCount(spec({ messages: "nope" }))).toBeUndefined(); + expect(messageQueueCount(spec({ messages: [{ id: "m1" }] }))).toBeUndefined(); + }); +}); diff --git a/src/features/surface-host/logic/message-queue.ts b/src/features/surface-host/logic/message-queue.ts index 7a3653e..a49d4d0 100644 --- a/src/features/surface-host/logic/message-queue.ts +++ b/src/features/surface-host/logic/message-queue.ts @@ -1,3 +1,4 @@ +import type { SurfaceSpec } from "@dispatch/ui-contract"; import type { QueuedMessage } from "@dispatch/wire"; /** @@ -41,6 +42,15 @@ export function parseMessageQueuePayload(payload: unknown): MessageQueueData | n return { messages }; } +/** Queue size from a validated snapshot; absent/malformed data stays unknown. */ +export function messageQueueCount(spec: SurfaceSpec | null): number | undefined { + const field = spec?.fields.find( + (field) => field.kind === "custom" && field.rendererId === MESSAGE_QUEUE_RENDERER_ID, + ); + if (field?.kind !== "custom") return undefined; + return parseMessageQueuePayload(field.payload)?.messages.length; +} + /** The `rendererId` the message-queue extension's `custom` surface field uses. */ export const MESSAGE_QUEUE_RENDERER_ID = "message-queue"; |
