




















@@ -0,0 +1,113 @@
1+import { describe, expect, it } from "vitest";
2+import { buildBlueBubblesInboundChatResolveTarget } from "./monitor-processing.js";
3+4+describe("buildBlueBubblesInboundChatResolveTarget", () => {
5+it("uses chat_id for group inbound when chatId is present", () => {
6+const target = buildBlueBubblesInboundChatResolveTarget({
7+isGroup: true,
8+chatId: 42,
9+chatIdentifier: undefined,
10+senderId: "+15551234567",
11+});
12+expect(target).toEqual({ kind: "chat_id", chatId: 42 });
13+});
14+15+it("uses chat_identifier for group inbound when chatId missing but identifier present", () => {
16+const target = buildBlueBubblesInboundChatResolveTarget({
17+isGroup: true,
18+chatId: undefined,
19+chatIdentifier: "iMessage;+;chat-abc",
20+senderId: "+15551234567",
21+});
22+expect(target).toEqual({
23+kind: "chat_identifier",
24+chatIdentifier: "iMessage;+;chat-abc",
25+});
26+});
27+28+it("prefers chat_id over chat_identifier when both are present for a group", () => {
29+const target = buildBlueBubblesInboundChatResolveTarget({
30+isGroup: true,
31+chatId: 7,
32+chatIdentifier: "iMessage;+;chat-abc",
33+senderId: "+15551234567",
34+});
35+expect(target).toEqual({ kind: "chat_id", chatId: 7 });
36+});
37+38+it("REFUSES sender-handle fallback for group inbound with no chat identifiers", () => {
39+// This is the candidate-4 regression: BlueBubbles webhooks for tapbacks
40+// and certain reaction/updated-message events arrive without chatGuid/
41+// chatId/chatIdentifier. Falling through to { kind: "handle",
42+// address: senderId } would resolve the sender's DM chatGuid and
43+// poison every action keyed off it (ack reaction, mark-read, outbound
44+// reply cache), making group reactions land in DMs.
45+const target = buildBlueBubblesInboundChatResolveTarget({
46+isGroup: true,
47+chatId: undefined,
48+chatIdentifier: undefined,
49+senderId: "+15551234567",
50+});
51+expect(target).toBeNull();
52+});
53+54+it("treats blank chatIdentifier as missing for group inbound", () => {
55+const target = buildBlueBubblesInboundChatResolveTarget({
56+isGroup: true,
57+chatId: undefined,
58+chatIdentifier: " ",
59+senderId: "+15551234567",
60+});
61+expect(target).toBeNull();
62+});
63+64+it("treats non-finite chatId as missing for group inbound", () => {
65+const target = buildBlueBubblesInboundChatResolveTarget({
66+isGroup: true,
67+chatId: Number.NaN,
68+chatIdentifier: undefined,
69+senderId: "+15551234567",
70+});
71+expect(target).toBeNull();
72+});
73+74+it("treats null chatId/chatIdentifier as missing for group inbound", () => {
75+const target = buildBlueBubblesInboundChatResolveTarget({
76+isGroup: true,
77+chatId: null,
78+chatIdentifier: null,
79+senderId: "+15551234567",
80+});
81+expect(target).toBeNull();
82+});
83+84+it("uses sender handle for DM inbound (the chat IS the conversation with that sender)", () => {
85+const target = buildBlueBubblesInboundChatResolveTarget({
86+isGroup: false,
87+chatId: undefined,
88+chatIdentifier: undefined,
89+senderId: "+15551234567",
90+});
91+expect(target).toEqual({ kind: "handle", address: "+15551234567" });
92+});
93+94+it("uses sender handle for DM inbound even when chatId is present (preserves prior behavior)", () => {
95+const target = buildBlueBubblesInboundChatResolveTarget({
96+isGroup: false,
97+chatId: 99,
98+chatIdentifier: "iMessage;-;+15551234567",
99+senderId: "+15551234567",
100+});
101+expect(target).toEqual({ kind: "handle", address: "+15551234567" });
102+});
103+104+it("returns null for DM inbound with empty senderId", () => {
105+const target = buildBlueBubblesInboundChatResolveTarget({
106+isGroup: false,
107+chatId: undefined,
108+chatIdentifier: undefined,
109+senderId: " ",
110+});
111+expect(target).toBeNull();
112+});
113+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。