Skip to content

Commit 645ef81

Browse files
authored
test(channels): preserve thread origin contracts
Add core and hook mapper regression coverage for the thread-origin contract behind #83302.\n\nThe tests prove a flat reply target can coexist with a thread-addressable OriginatingTo, and hook canonical conversation mapping keeps following OriginatingTo.\n\nProof: focused Vitest, autoreview, Testbox check:changed tbx_01krwaztbwm13sx9e4sbyyz4c1, and CI run 26008670388 passed.
1 parent 9aa4684 commit 645ef81

2 files changed

Lines changed: 52 additions & 0 deletions

File tree

src/channels/inbound-event/context.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,31 @@ describe("buildChannelInboundEventContext", () => {
228228
expect(ctx.InboundEventKind).toBe("room_event");
229229
});
230230

231+
it("preserves thread-addressable origins alongside flat reply targets", () => {
232+
const ctx = buildChannelInboundEventContext(
233+
createBaseContextParams({
234+
conversation: {
235+
kind: "group",
236+
id: "room-1",
237+
threadId: "topic-42",
238+
routePeer: {
239+
kind: "group",
240+
id: "room-1",
241+
},
242+
},
243+
reply: {
244+
to: "test:room:room-1",
245+
originatingTo: "test:room:room-1:topic:topic-42",
246+
messageThreadId: "topic-42",
247+
},
248+
}),
249+
);
250+
251+
expect(ctx.To).toBe("test:room:room-1");
252+
expect(ctx.OriginatingTo).toBe("test:room:room-1:topic:topic-42");
253+
expect(ctx.MessageThreadId).toBe("topic-42");
254+
});
255+
231256
it("keeps legacy command authorization fallback for authorizer arrays", () => {
232257
const ctx = buildChannelInboundEventContext(
233258
createBaseContextParams({

src/hooks/message-hook-mappers.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,33 @@ describe("message hook mappers", () => {
131131
expect(canonical.messageId).toBe("override-msg");
132132
});
133133

134+
it("uses OriginatingTo as the canonical conversation when To is flat", () => {
135+
const canonical = deriveInboundMessageHookContext(
136+
makeInboundCtx({
137+
To: "demo-chat:chat:456",
138+
OriginatingTo: "demo-chat:chat:456:topic:42",
139+
MessageThreadId: 42,
140+
}),
141+
);
142+
143+
expect(canonical.to).toBe("demo-chat:chat:456");
144+
expect(canonical.conversationId).toBe("demo-chat:chat:456:topic:42");
145+
expect(canonical.originatingTo).toBe("demo-chat:chat:456:topic:42");
146+
147+
const pluginContext = toPluginMessageContext(canonical);
148+
expect(pluginContext.conversationId).toBe("demo-chat:chat:456:topic:42");
149+
150+
const receivedEvent = toPluginMessageReceivedEvent(canonical);
151+
expect(receivedEvent.metadata?.to).toBe("demo-chat:chat:456");
152+
expect(receivedEvent.metadata?.originatingTo).toBe("demo-chat:chat:456:topic:42");
153+
expect(receivedEvent.metadata?.threadId).toBe(42);
154+
155+
const internalReceived = toInternalMessageReceivedContext(canonical);
156+
expect(internalReceived.conversationId).toBe("demo-chat:chat:456:topic:42");
157+
expect(internalReceived.metadata?.to).toBe("demo-chat:chat:456");
158+
expect(internalReceived.metadata?.threadId).toBe(42);
159+
});
160+
134161
it("preserves multi-attachment arrays for inbound claim metadata", () => {
135162
const canonical = deriveInboundMessageHookContext(
136163
makeInboundCtx({

0 commit comments

Comments
 (0)