mirror of https://github.com/openclaw/openclaw.git
171 lines
5.2 KiB
TypeScript
171 lines
5.2 KiB
TypeScript
import { describe, expect, it, vi, beforeEach } from "vitest";
|
|
import type { ChannelDirectoryEntry } from "../runtime-api.js";
|
|
import { listMatrixDirectoryGroupsLive, listMatrixDirectoryPeersLive } from "./directory-live.js";
|
|
import { resolveMatrixTargets } from "./resolve-targets.js";
|
|
|
|
vi.mock("./directory-live.js", () => ({
|
|
listMatrixDirectoryPeersLive: vi.fn(),
|
|
listMatrixDirectoryGroupsLive: vi.fn(),
|
|
}));
|
|
|
|
async function resolveUserTarget(input = "Alice") {
|
|
const [result] = await resolveMatrixTargets({
|
|
cfg: {},
|
|
inputs: [input],
|
|
kind: "user",
|
|
});
|
|
return result;
|
|
}
|
|
|
|
describe("resolveMatrixTargets (users)", () => {
|
|
beforeEach(() => {
|
|
vi.mocked(listMatrixDirectoryPeersLive).mockReset();
|
|
vi.mocked(listMatrixDirectoryGroupsLive).mockReset();
|
|
});
|
|
|
|
it("resolves exact unique display name matches", async () => {
|
|
const matches: ChannelDirectoryEntry[] = [
|
|
{ kind: "user", id: "@alice:example.org", name: "Alice" },
|
|
];
|
|
vi.mocked(listMatrixDirectoryPeersLive).mockResolvedValue(matches);
|
|
|
|
const result = await resolveUserTarget();
|
|
|
|
expect(result?.resolved).toBe(true);
|
|
expect(result?.id).toBe("@alice:example.org");
|
|
expect(listMatrixDirectoryPeersLive).toHaveBeenCalledWith({
|
|
cfg: {},
|
|
accountId: undefined,
|
|
query: "Alice",
|
|
limit: 5,
|
|
});
|
|
});
|
|
|
|
it("does not resolve ambiguous or non-exact matches", async () => {
|
|
const matches: ChannelDirectoryEntry[] = [
|
|
{ kind: "user", id: "@alice:example.org", name: "Alice" },
|
|
{ kind: "user", id: "@alice:evil.example", name: "Alice" },
|
|
];
|
|
vi.mocked(listMatrixDirectoryPeersLive).mockResolvedValue(matches);
|
|
|
|
const result = await resolveUserTarget();
|
|
|
|
expect(result?.resolved).toBe(false);
|
|
expect(result?.note).toMatch(/use full Matrix ID/i);
|
|
});
|
|
|
|
it("prefers exact group matches over first partial result", async () => {
|
|
const matches: ChannelDirectoryEntry[] = [
|
|
{ kind: "group", id: "!one:example.org", name: "General", handle: "#general" },
|
|
{ kind: "group", id: "!two:example.org", name: "Team", handle: "#team" },
|
|
];
|
|
vi.mocked(listMatrixDirectoryGroupsLive).mockResolvedValue(matches);
|
|
|
|
const [result] = await resolveMatrixTargets({
|
|
cfg: {},
|
|
inputs: ["#team"],
|
|
kind: "group",
|
|
});
|
|
|
|
expect(result?.resolved).toBe(true);
|
|
expect(result?.id).toBe("!two:example.org");
|
|
expect(result?.note).toBeUndefined();
|
|
expect(listMatrixDirectoryGroupsLive).toHaveBeenCalledWith({
|
|
cfg: {},
|
|
accountId: undefined,
|
|
query: "#team",
|
|
limit: 5,
|
|
});
|
|
});
|
|
|
|
it("threads accountId into live Matrix target lookups", async () => {
|
|
vi.mocked(listMatrixDirectoryPeersLive).mockResolvedValue([
|
|
{ kind: "user", id: "@alice:example.org", name: "Alice" },
|
|
]);
|
|
vi.mocked(listMatrixDirectoryGroupsLive).mockResolvedValue([
|
|
{ kind: "group", id: "!team:example.org", name: "Team", handle: "#team" },
|
|
]);
|
|
|
|
await resolveMatrixTargets({
|
|
cfg: {},
|
|
accountId: "ops",
|
|
inputs: ["Alice"],
|
|
kind: "user",
|
|
});
|
|
await resolveMatrixTargets({
|
|
cfg: {},
|
|
accountId: "ops",
|
|
inputs: ["#team"],
|
|
kind: "group",
|
|
});
|
|
|
|
expect(listMatrixDirectoryPeersLive).toHaveBeenCalledWith({
|
|
cfg: {},
|
|
accountId: "ops",
|
|
query: "Alice",
|
|
limit: 5,
|
|
});
|
|
expect(listMatrixDirectoryGroupsLive).toHaveBeenCalledWith({
|
|
cfg: {},
|
|
accountId: "ops",
|
|
query: "#team",
|
|
limit: 5,
|
|
});
|
|
});
|
|
|
|
it("reuses directory lookups for normalized duplicate inputs", async () => {
|
|
vi.mocked(listMatrixDirectoryPeersLive).mockResolvedValue([
|
|
{ kind: "user", id: "@alice:example.org", name: "Alice" },
|
|
]);
|
|
vi.mocked(listMatrixDirectoryGroupsLive).mockResolvedValue([
|
|
{ kind: "group", id: "!team:example.org", name: "Team", handle: "#team" },
|
|
]);
|
|
|
|
const userResults = await resolveMatrixTargets({
|
|
cfg: {},
|
|
inputs: ["Alice", " alice "],
|
|
kind: "user",
|
|
});
|
|
const groupResults = await resolveMatrixTargets({
|
|
cfg: {},
|
|
inputs: ["#team", "#team"],
|
|
kind: "group",
|
|
});
|
|
|
|
expect(userResults.every((entry) => entry.resolved)).toBe(true);
|
|
expect(groupResults.every((entry) => entry.resolved)).toBe(true);
|
|
expect(listMatrixDirectoryPeersLive).toHaveBeenCalledTimes(1);
|
|
expect(listMatrixDirectoryGroupsLive).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("accepts prefixed fully qualified ids without directory lookups", async () => {
|
|
const userResults = await resolveMatrixTargets({
|
|
cfg: {},
|
|
inputs: ["matrix:user:@alice:example.org"],
|
|
kind: "user",
|
|
});
|
|
const groupResults = await resolveMatrixTargets({
|
|
cfg: {},
|
|
inputs: ["matrix:room:!team:example.org"],
|
|
kind: "group",
|
|
});
|
|
|
|
expect(userResults).toEqual([
|
|
{
|
|
input: "matrix:user:@alice:example.org",
|
|
resolved: true,
|
|
id: "@alice:example.org",
|
|
},
|
|
]);
|
|
expect(groupResults).toEqual([
|
|
{
|
|
input: "matrix:room:!team:example.org",
|
|
resolved: true,
|
|
id: "!team:example.org",
|
|
},
|
|
]);
|
|
expect(listMatrixDirectoryPeersLive).not.toHaveBeenCalled();
|
|
expect(listMatrixDirectoryGroupsLive).not.toHaveBeenCalled();
|
|
});
|
|
});
|