mirror of https://github.com/openclaw/openclaw.git
202 lines
6.7 KiB
TypeScript
202 lines
6.7 KiB
TypeScript
import fs from "node:fs";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { createMSTeamsConversationStoreFs } from "./conversation-store-fs.js";
|
|
import { createMSTeamsConversationStoreMemory } from "./conversation-store-memory.js";
|
|
import type { MSTeamsConversationStore } from "./conversation-store.js";
|
|
import { setMSTeamsRuntime } from "./runtime.js";
|
|
import { msteamsRuntimeStub } from "./test-runtime.js";
|
|
|
|
type StoreFactory = {
|
|
name: string;
|
|
createStore: () => Promise<MSTeamsConversationStore>;
|
|
};
|
|
|
|
const storeFactories: StoreFactory[] = [
|
|
{
|
|
name: "fs",
|
|
createStore: async () => {
|
|
const stateDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), "openclaw-msteams-store-"));
|
|
return createMSTeamsConversationStoreFs({
|
|
env: { ...process.env, OPENCLAW_STATE_DIR: stateDir },
|
|
ttlMs: 60_000,
|
|
});
|
|
},
|
|
},
|
|
{
|
|
name: "memory",
|
|
createStore: async () => createMSTeamsConversationStoreMemory(),
|
|
},
|
|
];
|
|
|
|
describe.each(storeFactories)("msteams conversation store ($name)", ({ createStore }) => {
|
|
beforeEach(() => {
|
|
setMSTeamsRuntime(msteamsRuntimeStub);
|
|
});
|
|
|
|
it("normalizes conversation ids consistently", async () => {
|
|
const store = await createStore();
|
|
|
|
await store.upsert("conv-norm;messageid=123", {
|
|
conversation: { id: "conv-norm" },
|
|
channelId: "msteams",
|
|
serviceUrl: "https://service.example.com",
|
|
user: { id: "u1" },
|
|
});
|
|
|
|
await expect(store.get("conv-norm")).resolves.toEqual(
|
|
expect.objectContaining({
|
|
conversation: { id: "conv-norm" },
|
|
}),
|
|
);
|
|
await expect(store.remove("conv-norm")).resolves.toBe(true);
|
|
await expect(store.get("conv-norm;messageid=123")).resolves.toBeNull();
|
|
});
|
|
|
|
it("upserts, lists, removes, and resolves users by both AAD and Bot Framework ids", async () => {
|
|
const store = await createStore();
|
|
|
|
await store.upsert("conv-a", {
|
|
conversation: { id: "conv-a" },
|
|
channelId: "msteams",
|
|
serviceUrl: "https://service.example.com",
|
|
user: { id: "user-a", aadObjectId: "aad-a", name: "Alice" },
|
|
});
|
|
|
|
await store.upsert("conv-b", {
|
|
conversation: { id: "conv-b" },
|
|
channelId: "msteams",
|
|
serviceUrl: "https://service.example.com",
|
|
user: { id: "user-b", aadObjectId: "aad-b", name: "Bob" },
|
|
});
|
|
|
|
await expect(store.get("conv-a")).resolves.toEqual({
|
|
conversation: { id: "conv-a" },
|
|
channelId: "msteams",
|
|
serviceUrl: "https://service.example.com",
|
|
user: { id: "user-a", aadObjectId: "aad-a", name: "Alice" },
|
|
lastSeenAt: expect.any(String),
|
|
});
|
|
|
|
await expect(store.list()).resolves.toEqual([
|
|
{
|
|
conversationId: "conv-a",
|
|
reference: {
|
|
conversation: { id: "conv-a" },
|
|
channelId: "msteams",
|
|
serviceUrl: "https://service.example.com",
|
|
user: { id: "user-a", aadObjectId: "aad-a", name: "Alice" },
|
|
lastSeenAt: expect.any(String),
|
|
},
|
|
},
|
|
{
|
|
conversationId: "conv-b",
|
|
reference: {
|
|
conversation: { id: "conv-b" },
|
|
channelId: "msteams",
|
|
serviceUrl: "https://service.example.com",
|
|
user: { id: "user-b", aadObjectId: "aad-b", name: "Bob" },
|
|
lastSeenAt: expect.any(String),
|
|
},
|
|
},
|
|
]);
|
|
|
|
await expect(store.findPreferredDmByUserId(" aad-b ")).resolves.toEqual({
|
|
conversationId: "conv-b",
|
|
reference: {
|
|
conversation: { id: "conv-b" },
|
|
channelId: "msteams",
|
|
serviceUrl: "https://service.example.com",
|
|
user: { id: "user-b", aadObjectId: "aad-b", name: "Bob" },
|
|
lastSeenAt: expect.any(String),
|
|
},
|
|
});
|
|
await expect(store.findPreferredDmByUserId("user-a")).resolves.toEqual({
|
|
conversationId: "conv-a",
|
|
reference: {
|
|
conversation: { id: "conv-a" },
|
|
channelId: "msteams",
|
|
serviceUrl: "https://service.example.com",
|
|
user: { id: "user-a", aadObjectId: "aad-a", name: "Alice" },
|
|
lastSeenAt: expect.any(String),
|
|
},
|
|
});
|
|
await expect(store.findByUserId("user-a")).resolves.toEqual(
|
|
await store.findPreferredDmByUserId("user-a"),
|
|
);
|
|
await expect(store.findPreferredDmByUserId(" ")).resolves.toBeNull();
|
|
|
|
await expect(store.remove("conv-a")).resolves.toBe(true);
|
|
await expect(store.get("conv-a")).resolves.toBeNull();
|
|
await expect(store.remove("missing")).resolves.toBe(false);
|
|
});
|
|
|
|
it("preserves existing timezone when upsert omits timezone", async () => {
|
|
const store = await createStore();
|
|
|
|
await store.upsert("conv-tz", {
|
|
conversation: { id: "conv-tz" },
|
|
channelId: "msteams",
|
|
serviceUrl: "https://service.example.com",
|
|
user: { id: "u1" },
|
|
timezone: "Europe/London",
|
|
});
|
|
|
|
await store.upsert("conv-tz", {
|
|
conversation: { id: "conv-tz" },
|
|
channelId: "msteams",
|
|
serviceUrl: "https://service.example.com",
|
|
user: { id: "u1" },
|
|
});
|
|
|
|
await expect(store.get("conv-tz")).resolves.toMatchObject({
|
|
timezone: "Europe/London",
|
|
});
|
|
});
|
|
|
|
it("prefers the freshest personal conversation for repeated upserts of the same user", async () => {
|
|
const store = await createStore();
|
|
|
|
vi.useFakeTimers();
|
|
try {
|
|
vi.setSystemTime(new Date("2026-03-25T20:00:00.000Z"));
|
|
await store.upsert("dm-old", {
|
|
conversation: { id: "dm-old", conversationType: "personal" },
|
|
channelId: "msteams",
|
|
serviceUrl: "https://service.example.com",
|
|
user: { id: "user-shared-old", aadObjectId: "aad-shared", name: "Old DM" },
|
|
});
|
|
|
|
vi.setSystemTime(new Date("2026-03-25T20:30:00.000Z"));
|
|
await store.upsert("group-shared", {
|
|
conversation: { id: "group-shared", conversationType: "groupChat" },
|
|
channelId: "msteams",
|
|
serviceUrl: "https://service.example.com",
|
|
user: { id: "user-shared-group", aadObjectId: "aad-shared", name: "Group" },
|
|
});
|
|
|
|
vi.setSystemTime(new Date("2026-03-25T21:00:00.000Z"));
|
|
await store.upsert("dm-new", {
|
|
conversation: { id: "dm-new", conversationType: "personal" },
|
|
channelId: "msteams",
|
|
serviceUrl: "https://service.example.com",
|
|
user: { id: "user-shared-new", aadObjectId: "aad-shared", name: "New DM" },
|
|
});
|
|
|
|
await expect(store.findPreferredDmByUserId("aad-shared")).resolves.toEqual({
|
|
conversationId: "dm-new",
|
|
reference: {
|
|
conversation: { id: "dm-new", conversationType: "personal" },
|
|
channelId: "msteams",
|
|
serviceUrl: "https://service.example.com",
|
|
user: { id: "user-shared-new", aadObjectId: "aad-shared", name: "New DM" },
|
|
lastSeenAt: "2026-03-25T21:00:00.000Z",
|
|
},
|
|
});
|
|
} finally {
|
|
vi.useRealTimers();
|
|
}
|
|
});
|
|
});
|