fix(bluebubbles): add opt-in coalesceSameSenderDms for split-send DMs (#69258)

Merged via squash.

Prepared head SHA: 8f1bd3cf53
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Reviewed-by: @omarshahine
This commit is contained in:
Omar Shahine
2026-04-21 01:43:17 -07:00
committed by GitHub
parent f1805ab54d
commit 14506aeca4
16 changed files with 921 additions and 22 deletions

View File

@@ -325,9 +325,44 @@ export function createPluginRuntimeMock(overrides: DeepPartial<PluginRuntime> =
flushKey: vi.fn(),
}),
) as unknown as PluginRuntime["channel"]["debounce"]["createInboundDebouncer"],
resolveInboundDebounceMs: vi.fn(
() => 0,
) as unknown as PluginRuntime["channel"]["debounce"]["resolveInboundDebounceMs"],
resolveInboundDebounceMs: vi.fn((params: unknown) => {
// Match the production contract so channel plugins that delegate to
// `core.channel.debounce.resolveInboundDebounceMs({ cfg, channel })`
// see the same per-channel/global/default precedence in tests as
// they would at runtime. Prior to this, the mock returned 0
// unconditionally, which meant any channel that delegated (vs.
// reading config directly) effectively disabled its debounce
// window in tests — a footgun that silently hid coverage for
// per-channel overrides.
const p = params as
| {
cfg?: {
messages?: {
inbound?: {
debounceMs?: unknown;
byChannel?: Record<string, unknown>;
};
};
};
channel?: string;
overrideMs?: unknown;
}
| undefined;
const override = typeof p?.overrideMs === "number" ? p.overrideMs : undefined;
if (typeof override === "number") {
return override;
}
const inbound = p?.cfg?.messages?.inbound;
const perChannel =
p?.channel && inbound?.byChannel ? inbound.byChannel[p.channel] : undefined;
if (typeof perChannel === "number") {
return perChannel;
}
if (typeof inbound?.debounceMs === "number") {
return inbound.debounceMs;
}
return 0;
}) as unknown as PluginRuntime["channel"]["debounce"]["resolveInboundDebounceMs"],
},
commands: {
resolveCommandAuthorizedFromAuthorizers: vi.fn(