mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 10:01:24 +00:00
test(pairing): dedupe fixture writers and expand store coverage
This commit is contained in:
@@ -10,6 +10,8 @@ import {
|
|||||||
approveChannelPairingCode,
|
approveChannelPairingCode,
|
||||||
listChannelPairingRequests,
|
listChannelPairingRequests,
|
||||||
readChannelAllowFromStore,
|
readChannelAllowFromStore,
|
||||||
|
readChannelAllowFromStoreSync,
|
||||||
|
removeChannelAllowFromStoreEntry,
|
||||||
upsertChannelPairingRequest,
|
upsertChannelPairingRequest,
|
||||||
} from "./pairing-store.js";
|
} from "./pairing-store.js";
|
||||||
|
|
||||||
@@ -32,6 +34,29 @@ async function withTempStateDir<T>(fn: (stateDir: string) => Promise<T>) {
|
|||||||
return await withEnvAsync({ OPENCLAW_STATE_DIR: dir }, async () => await fn(dir));
|
return await withEnvAsync({ OPENCLAW_STATE_DIR: dir }, async () => await fn(dir));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function writeJsonFixture(filePath: string, value: unknown) {
|
||||||
|
await fs.writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolvePairingFilePath(stateDir: string, channel: string) {
|
||||||
|
return path.join(resolveOAuthDir(process.env, stateDir), `${channel}-pairing.json`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function writeAllowFromFixture(params: {
|
||||||
|
stateDir: string;
|
||||||
|
channel: string;
|
||||||
|
allowFrom: string[];
|
||||||
|
accountId?: string;
|
||||||
|
}) {
|
||||||
|
const oauthDir = resolveOAuthDir(process.env, params.stateDir);
|
||||||
|
await fs.mkdir(oauthDir, { recursive: true });
|
||||||
|
const suffix = params.accountId ? `-${params.accountId}` : "";
|
||||||
|
await writeJsonFixture(path.join(oauthDir, `${params.channel}${suffix}-allowFrom.json`), {
|
||||||
|
version: 1,
|
||||||
|
allowFrom: params.allowFrom,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
describe("pairing store", () => {
|
describe("pairing store", () => {
|
||||||
it("reuses pending code and reports created=false", async () => {
|
it("reuses pending code and reports created=false", async () => {
|
||||||
await withTempStateDir(async () => {
|
await withTempStateDir(async () => {
|
||||||
@@ -61,8 +86,7 @@ describe("pairing store", () => {
|
|||||||
});
|
});
|
||||||
expect(created.created).toBe(true);
|
expect(created.created).toBe(true);
|
||||||
|
|
||||||
const oauthDir = resolveOAuthDir(process.env, stateDir);
|
const filePath = resolvePairingFilePath(stateDir, "signal");
|
||||||
const filePath = path.join(oauthDir, "signal-pairing.json");
|
|
||||||
const raw = await fs.readFile(filePath, "utf8");
|
const raw = await fs.readFile(filePath, "utf8");
|
||||||
const parsed = JSON.parse(raw) as {
|
const parsed = JSON.parse(raw) as {
|
||||||
requests?: Array<Record<string, unknown>>;
|
requests?: Array<Record<string, unknown>>;
|
||||||
@@ -73,11 +97,7 @@ describe("pairing store", () => {
|
|||||||
createdAt: expiredAt,
|
createdAt: expiredAt,
|
||||||
lastSeenAt: expiredAt,
|
lastSeenAt: expiredAt,
|
||||||
}));
|
}));
|
||||||
await fs.writeFile(
|
await writeJsonFixture(filePath, { version: 1, requests });
|
||||||
filePath,
|
|
||||||
`${JSON.stringify({ version: 1, requests }, null, 2)}\n`,
|
|
||||||
"utf8",
|
|
||||||
);
|
|
||||||
|
|
||||||
const list = await listChannelPairingRequests("signal");
|
const list = await listChannelPairingRequests("signal");
|
||||||
expect(list).toHaveLength(0);
|
expect(list).toHaveLength(0);
|
||||||
@@ -183,34 +203,90 @@ describe("pairing store", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("filters approvals by account id and ignores blank approval codes", async () => {
|
||||||
|
await withTempStateDir(async () => {
|
||||||
|
const created = await upsertChannelPairingRequest({
|
||||||
|
channel: "telegram",
|
||||||
|
accountId: "yy",
|
||||||
|
id: "12345",
|
||||||
|
});
|
||||||
|
expect(created.created).toBe(true);
|
||||||
|
|
||||||
|
const blank = await approveChannelPairingCode({
|
||||||
|
channel: "telegram",
|
||||||
|
code: " ",
|
||||||
|
});
|
||||||
|
expect(blank).toBeNull();
|
||||||
|
|
||||||
|
const mismatched = await approveChannelPairingCode({
|
||||||
|
channel: "telegram",
|
||||||
|
code: created.code,
|
||||||
|
accountId: "zz",
|
||||||
|
});
|
||||||
|
expect(mismatched).toBeNull();
|
||||||
|
|
||||||
|
const pending = await listChannelPairingRequests("telegram");
|
||||||
|
expect(pending).toHaveLength(1);
|
||||||
|
expect(pending[0]?.id).toBe("12345");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("removes account-scoped allowFrom entries idempotently", async () => {
|
||||||
|
await withTempStateDir(async () => {
|
||||||
|
await addChannelAllowFromStoreEntry({
|
||||||
|
channel: "telegram",
|
||||||
|
accountId: "yy",
|
||||||
|
entry: "12345",
|
||||||
|
});
|
||||||
|
|
||||||
|
const removed = await removeChannelAllowFromStoreEntry({
|
||||||
|
channel: "telegram",
|
||||||
|
accountId: "yy",
|
||||||
|
entry: "12345",
|
||||||
|
});
|
||||||
|
expect(removed.changed).toBe(true);
|
||||||
|
expect(removed.allowFrom).toEqual([]);
|
||||||
|
|
||||||
|
const removedAgain = await removeChannelAllowFromStoreEntry({
|
||||||
|
channel: "telegram",
|
||||||
|
accountId: "yy",
|
||||||
|
entry: "12345",
|
||||||
|
});
|
||||||
|
expect(removedAgain.changed).toBe(false);
|
||||||
|
expect(removedAgain.allowFrom).toEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reads sync allowFrom with scoped + legacy dedupe and wildcard filtering", async () => {
|
||||||
|
await withTempStateDir(async (stateDir) => {
|
||||||
|
await writeAllowFromFixture({
|
||||||
|
stateDir,
|
||||||
|
channel: "telegram",
|
||||||
|
allowFrom: ["1001", "*", " 1001 ", " "],
|
||||||
|
});
|
||||||
|
await writeAllowFromFixture({
|
||||||
|
stateDir,
|
||||||
|
channel: "telegram",
|
||||||
|
accountId: "yy",
|
||||||
|
allowFrom: [" 1002 ", "1001", "1002"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const scoped = readChannelAllowFromStoreSync("telegram", process.env, "yy");
|
||||||
|
const channelScoped = readChannelAllowFromStoreSync("telegram");
|
||||||
|
expect(scoped).toEqual(["1002", "1001"]);
|
||||||
|
expect(channelScoped).toEqual(["1001", "1001"]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("reads legacy channel-scoped allowFrom for default account", async () => {
|
it("reads legacy channel-scoped allowFrom for default account", async () => {
|
||||||
await withTempStateDir(async (stateDir) => {
|
await withTempStateDir(async (stateDir) => {
|
||||||
const oauthDir = resolveOAuthDir(process.env, stateDir);
|
await writeAllowFromFixture({ stateDir, channel: "telegram", allowFrom: ["1001"] });
|
||||||
await fs.mkdir(oauthDir, { recursive: true });
|
await writeAllowFromFixture({
|
||||||
await fs.writeFile(
|
stateDir,
|
||||||
path.join(oauthDir, "telegram-allowFrom.json"),
|
channel: "telegram",
|
||||||
JSON.stringify(
|
accountId: "default",
|
||||||
{
|
allowFrom: ["1002"],
|
||||||
version: 1,
|
});
|
||||||
allowFrom: ["1001"],
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
2,
|
|
||||||
) + "\n",
|
|
||||||
"utf8",
|
|
||||||
);
|
|
||||||
await fs.writeFile(
|
|
||||||
path.join(oauthDir, "telegram-default-allowFrom.json"),
|
|
||||||
JSON.stringify(
|
|
||||||
{
|
|
||||||
version: 1,
|
|
||||||
allowFrom: ["1002"],
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
2,
|
|
||||||
) + "\n",
|
|
||||||
"utf8",
|
|
||||||
);
|
|
||||||
|
|
||||||
const scoped = await readChannelAllowFromStore("telegram", process.env, "default");
|
const scoped = await readChannelAllowFromStore("telegram", process.env, "default");
|
||||||
expect(scoped).toEqual(["1002", "1001"]);
|
expect(scoped).toEqual(["1002", "1001"]);
|
||||||
|
|||||||
Reference in New Issue
Block a user