feat(slack): track thread participation for auto-reply without @mention (#29165)
* feat(slack): track thread participation for auto-reply without @mention * fix(slack): scope thread participation cache by accountId and capture actual reply thread ts * fix(slack): capture reply thread ts from all delivery paths and only after success * Slack: add changelog for thread participation cache behavior --------- Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
58
src/slack/sent-thread-cache.test.ts
Normal file
58
src/slack/sent-thread-cache.test.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
clearSlackThreadParticipationCache,
|
||||
hasSlackThreadParticipation,
|
||||
recordSlackThreadParticipation,
|
||||
} from "./sent-thread-cache.js";
|
||||
|
||||
describe("slack sent-thread-cache", () => {
|
||||
afterEach(() => {
|
||||
clearSlackThreadParticipationCache();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("records and checks thread participation", () => {
|
||||
recordSlackThreadParticipation("A1", "C123", "1700000000.000001");
|
||||
expect(hasSlackThreadParticipation("A1", "C123", "1700000000.000001")).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false for unrecorded threads", () => {
|
||||
expect(hasSlackThreadParticipation("A1", "C123", "1700000000.000001")).toBe(false);
|
||||
});
|
||||
|
||||
it("distinguishes different channels and threads", () => {
|
||||
recordSlackThreadParticipation("A1", "C123", "1700000000.000001");
|
||||
expect(hasSlackThreadParticipation("A1", "C123", "1700000000.000002")).toBe(false);
|
||||
expect(hasSlackThreadParticipation("A1", "C456", "1700000000.000001")).toBe(false);
|
||||
});
|
||||
|
||||
it("scopes participation by accountId", () => {
|
||||
recordSlackThreadParticipation("A1", "C123", "1700000000.000001");
|
||||
expect(hasSlackThreadParticipation("A2", "C123", "1700000000.000001")).toBe(false);
|
||||
expect(hasSlackThreadParticipation("A1", "C123", "1700000000.000001")).toBe(true);
|
||||
});
|
||||
|
||||
it("ignores empty accountId, channelId, or threadTs", () => {
|
||||
recordSlackThreadParticipation("", "C123", "1700000000.000001");
|
||||
recordSlackThreadParticipation("A1", "", "1700000000.000001");
|
||||
recordSlackThreadParticipation("A1", "C123", "");
|
||||
expect(hasSlackThreadParticipation("", "C123", "1700000000.000001")).toBe(false);
|
||||
expect(hasSlackThreadParticipation("A1", "", "1700000000.000001")).toBe(false);
|
||||
expect(hasSlackThreadParticipation("A1", "C123", "")).toBe(false);
|
||||
});
|
||||
|
||||
it("clears all entries", () => {
|
||||
recordSlackThreadParticipation("A1", "C123", "1700000000.000001");
|
||||
recordSlackThreadParticipation("A1", "C456", "1700000000.000002");
|
||||
clearSlackThreadParticipationCache();
|
||||
expect(hasSlackThreadParticipation("A1", "C123", "1700000000.000001")).toBe(false);
|
||||
expect(hasSlackThreadParticipation("A1", "C456", "1700000000.000002")).toBe(false);
|
||||
});
|
||||
|
||||
it("expired entries return false and are cleaned up on read", () => {
|
||||
recordSlackThreadParticipation("A1", "C123", "1700000000.000001");
|
||||
// Advance time past the 24-hour TTL
|
||||
vi.spyOn(Date, "now").mockReturnValue(Date.now() + 25 * 60 * 60 * 1000);
|
||||
expect(hasSlackThreadParticipation("A1", "C123", "1700000000.000001")).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user