summaryrefslogtreecommitdiffhomepage
path: root/src/adapters/ws
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-25 10:52:13 +0900
committerAdam Malczewski <[email protected]>2026-06-25 10:52:13 +0900
commit17ce47987e673b6618454d033885b17b2a01912e (patch)
tree2bd7259d51725eeadc20d410667d529f66834197 /src/adapters/ws
parenteff289b2b4cc41db706f3c3274a089d46012be87 (diff)
downloaddispatch-web-17ce47987e673b6618454d033885b17b2a01912e.tar.gz
dispatch-web-17ce47987e673b6618454d033885b17b2a01912e.zip
feat(core): chunks retry-banner, wire conformance, ws logic, history adapter
- core/chunks: add retry-banner view-model (+test), update reducer/selectors/types - core/wire: update conformance checks (+test) - adapters/ws: update reconnect logic (+tests) - adapters/history: new client-side routing adapter (history + popstate wrapper)
Diffstat (limited to 'src/adapters/ws')
-rw-r--r--src/adapters/ws/index.test.ts11
-rw-r--r--src/adapters/ws/logic.test.ts69
-rw-r--r--src/adapters/ws/logic.ts4
3 files changed, 79 insertions, 5 deletions
diff --git a/src/adapters/ws/index.test.ts b/src/adapters/ws/index.test.ts
index 92d57a8..e8e5434 100644
--- a/src/adapters/ws/index.test.ts
+++ b/src/adapters/ws/index.test.ts
@@ -283,11 +283,18 @@ describe("createSurfaceSocket", () => {
});
ws.resolveOpen();
- ws.invokeMessage(JSON.stringify({ type: "conversation.open", conversationId: "c1" }));
+ ws.invokeMessage(
+ JSON.stringify({
+ type: "conversation.open",
+ conversationId: "c1",
+ workspaceId: "w1",
+ }),
+ );
expect(onConversationOpen).toHaveBeenCalledOnce();
expect(onConversationOpen).toHaveBeenCalledWith({
type: "conversation.open",
conversationId: "c1",
+ workspaceId: "w1",
});
expect(onMessage).not.toHaveBeenCalled();
expect(onChat).not.toHaveBeenCalled();
@@ -310,6 +317,7 @@ describe("createSurfaceSocket", () => {
type: "conversation.statusChanged",
conversationId: "c1",
status: "active",
+ workspaceId: "w1",
}),
);
expect(onConversationStatusChanged).toHaveBeenCalledOnce();
@@ -317,6 +325,7 @@ describe("createSurfaceSocket", () => {
type: "conversation.statusChanged",
conversationId: "c1",
status: "active",
+ workspaceId: "w1",
});
expect(onMessage).not.toHaveBeenCalled();
});
diff --git a/src/adapters/ws/logic.test.ts b/src/adapters/ws/logic.test.ts
index 2463519..062d47b 100644
--- a/src/adapters/ws/logic.test.ts
+++ b/src/adapters/ws/logic.test.ts
@@ -219,18 +219,52 @@ describe("parseServerMessage", () => {
});
it("parses a conversation.open message", () => {
- const data = JSON.stringify({ type: "conversation.open", conversationId: "c1" });
+ const data = JSON.stringify({
+ type: "conversation.open",
+ conversationId: "c1",
+ workspaceId: "w1",
+ });
const result = parseServerMessage(data);
- expect(result).toEqual({ type: "conversation.open", conversationId: "c1" });
+ expect(result).toEqual({
+ type: "conversation.open",
+ conversationId: "c1",
+ workspaceId: "w1",
+ });
});
it("returns null for conversation.open with missing conversationId", () => {
- expect(parseServerMessage(JSON.stringify({ type: "conversation.open" }))).toBeNull();
+ expect(
+ parseServerMessage(JSON.stringify({ type: "conversation.open", workspaceId: "w1" })),
+ ).toBeNull();
});
it("returns null for conversation.open with non-string conversationId", () => {
expect(
- parseServerMessage(JSON.stringify({ type: "conversation.open", conversationId: 42 })),
+ parseServerMessage(
+ JSON.stringify({
+ type: "conversation.open",
+ conversationId: 42,
+ workspaceId: "w1",
+ }),
+ ),
+ ).toBeNull();
+ });
+
+ it("returns null for conversation.open with missing workspaceId", () => {
+ expect(
+ parseServerMessage(JSON.stringify({ type: "conversation.open", conversationId: "c1" })),
+ ).toBeNull();
+ });
+
+ it("returns null for conversation.open with non-string workspaceId", () => {
+ expect(
+ parseServerMessage(
+ JSON.stringify({
+ type: "conversation.open",
+ conversationId: "c1",
+ workspaceId: 42,
+ }),
+ ),
).toBeNull();
});
@@ -239,14 +273,40 @@ describe("parseServerMessage", () => {
type: "conversation.statusChanged",
conversationId: "c1",
status: "active",
+ workspaceId: "w1",
});
expect(parseServerMessage(data)).toEqual({
type: "conversation.statusChanged",
conversationId: "c1",
status: "active",
+ workspaceId: "w1",
});
});
+ it("returns null for conversation.statusChanged with missing workspaceId", () => {
+ expect(
+ parseServerMessage(
+ JSON.stringify({
+ type: "conversation.statusChanged",
+ conversationId: "c1",
+ status: "active",
+ }),
+ ),
+ ).toBeNull();
+ });
+
+ it("returns null for conversation.statusChanged with non-string workspaceId", () => {
+ expect(
+ parseServerMessage(
+ JSON.stringify({
+ type: "conversation.statusChanged",
+ conversationId: "c1",
+ status: "active",
+ workspaceId: 42,
+ }),
+ ),
+ ).toBeNull();
+ });
it("returns null for conversation.statusChanged with invalid status", () => {
expect(
parseServerMessage(
@@ -254,6 +314,7 @@ describe("parseServerMessage", () => {
type: "conversation.statusChanged",
conversationId: "c1",
status: "done",
+ workspaceId: "w1",
}),
),
).toBeNull();
diff --git a/src/adapters/ws/logic.ts b/src/adapters/ws/logic.ts
index b11c5c4..d1a5b5f 100644
--- a/src/adapters/ws/logic.ts
+++ b/src/adapters/ws/logic.ts
@@ -115,9 +115,11 @@ export function parseServerMessage(data: string): WsServerMessage | null {
}
case "conversation.open": {
if (typeof parsed.conversationId !== "string") return null;
+ if (typeof parsed.workspaceId !== "string") return null;
const msg: ConversationOpenMessage = {
type: "conversation.open",
conversationId: parsed.conversationId,
+ workspaceId: parsed.workspaceId,
};
return msg;
}
@@ -127,10 +129,12 @@ export function parseServerMessage(data: string): WsServerMessage | null {
if (parsed.status !== "active" && parsed.status !== "idle" && parsed.status !== "closed") {
return null;
}
+ if (typeof parsed.workspaceId !== "string") return null;
const msg: ConversationStatusChangedMessage = {
type: "conversation.statusChanged",
conversationId: parsed.conversationId,
status: parsed.status,
+ workspaceId: parsed.workspaceId,
};
return msg;
}