mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-18 13:04:47 +00:00
Add QR-based app registration, improve Feishu onboarding flows, support direct login entry, add group chat policy setup, reduce log noise, and update docs.
176 lines
5.1 KiB
TypeScript
176 lines
5.1 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
import { createNonExitingTypedRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js";
|
|
import {
|
|
createPluginSetupWizardConfigure,
|
|
createPluginSetupWizardStatus,
|
|
createTestWizardPrompter,
|
|
runSetupWizardConfigure,
|
|
} from "../../../test/helpers/plugins/setup-wizard.js";
|
|
|
|
vi.mock("./probe.js", () => ({
|
|
probeFeishu: vi.fn(async () => ({ ok: false, error: "mocked" })),
|
|
}));
|
|
|
|
vi.mock("./app-registration.js", () => ({
|
|
initAppRegistration: vi.fn(async () => {
|
|
throw new Error("mocked: scan-to-create not available");
|
|
}),
|
|
beginAppRegistration: vi.fn(),
|
|
pollAppRegistration: vi.fn(),
|
|
printQrCode: vi.fn(async () => {}),
|
|
getAppOwnerOpenId: vi.fn(async () => undefined),
|
|
}));
|
|
|
|
import { feishuPlugin } from "./channel.js";
|
|
|
|
const baseStatusContext = {
|
|
accountOverrides: {},
|
|
};
|
|
|
|
async function withEnvVars(values: Record<string, string | undefined>, run: () => Promise<void>) {
|
|
const previous = new Map<string, string | undefined>();
|
|
for (const [key, value] of Object.entries(values)) {
|
|
previous.set(key, process.env[key]);
|
|
if (value === undefined) {
|
|
delete process.env[key];
|
|
} else {
|
|
process.env[key] = value;
|
|
}
|
|
}
|
|
|
|
try {
|
|
await run();
|
|
} finally {
|
|
for (const [key, prior] of previous.entries()) {
|
|
if (prior === undefined) {
|
|
delete process.env[key];
|
|
} else {
|
|
process.env[key] = prior;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async function getStatusWithEnvRefs(params: { appIdKey: string; appSecretKey: string }) {
|
|
return await feishuGetStatus({
|
|
cfg: {
|
|
channels: {
|
|
feishu: {
|
|
appId: { source: "env", id: params.appIdKey, provider: "default" },
|
|
appSecret: { source: "env", id: params.appSecretKey, provider: "default" },
|
|
},
|
|
},
|
|
} as never,
|
|
...baseStatusContext,
|
|
});
|
|
}
|
|
|
|
const feishuConfigure = createPluginSetupWizardConfigure(feishuPlugin);
|
|
const feishuGetStatus = createPluginSetupWizardStatus(feishuPlugin);
|
|
type FeishuConfigureRuntime = Parameters<typeof feishuConfigure>[0]["runtime"];
|
|
|
|
describe("feishu setup wizard", () => {
|
|
it("does not throw when config appId/appSecret are SecretRef objects", async () => {
|
|
const text = vi
|
|
.fn()
|
|
.mockResolvedValueOnce("cli_from_prompt")
|
|
.mockResolvedValueOnce("secret_from_prompt");
|
|
const prompter = createTestWizardPrompter({
|
|
text,
|
|
confirm: vi.fn(async () => true),
|
|
select: vi.fn(
|
|
async ({ initialValue }: { initialValue?: string }) => initialValue ?? "bot",
|
|
) as never,
|
|
});
|
|
|
|
await expect(
|
|
runSetupWizardConfigure({
|
|
configure: feishuConfigure,
|
|
cfg: {
|
|
channels: {
|
|
feishu: {
|
|
appId: { source: "env", id: "FEISHU_APP_ID", provider: "default" },
|
|
appSecret: { source: "env", id: "FEISHU_APP_SECRET", provider: "default" },
|
|
},
|
|
},
|
|
} as never,
|
|
prompter,
|
|
runtime: createNonExitingTypedRuntimeEnv<FeishuConfigureRuntime>(),
|
|
}),
|
|
).resolves.toBeTruthy();
|
|
});
|
|
});
|
|
|
|
describe("feishu setup wizard status", () => {
|
|
it("treats SecretRef appSecret as configured when appId is present", async () => {
|
|
const status = await feishuGetStatus({
|
|
cfg: {
|
|
channels: {
|
|
feishu: {
|
|
appId: "cli_a123456",
|
|
appSecret: {
|
|
source: "env",
|
|
provider: "default",
|
|
id: "FEISHU_APP_SECRET",
|
|
},
|
|
},
|
|
},
|
|
} as never,
|
|
accountOverrides: {},
|
|
});
|
|
|
|
expect(status.configured).toBe(true);
|
|
});
|
|
|
|
it("does not fallback to top-level appId when account explicitly sets empty appId", async () => {
|
|
const status = await feishuGetStatus({
|
|
cfg: {
|
|
channels: {
|
|
feishu: {
|
|
appId: "top_level_app",
|
|
accounts: {
|
|
main: {
|
|
appId: "",
|
|
appSecret: "sample-app-credential", // pragma: allowlist secret
|
|
},
|
|
},
|
|
},
|
|
},
|
|
} as never,
|
|
...baseStatusContext,
|
|
});
|
|
|
|
expect(status.configured).toBe(false);
|
|
});
|
|
|
|
it("treats env SecretRef appId as not configured when env var is missing", async () => {
|
|
const appIdKey = "FEISHU_APP_ID_STATUS_MISSING_TEST";
|
|
const appSecretKey = "FEISHU_APP_CREDENTIAL_STATUS_MISSING_TEST"; // pragma: allowlist secret
|
|
await withEnvVars(
|
|
{
|
|
[appIdKey]: undefined,
|
|
[appSecretKey]: "env-credential-456", // pragma: allowlist secret
|
|
},
|
|
async () => {
|
|
const status = await getStatusWithEnvRefs({ appIdKey, appSecretKey });
|
|
expect(status.configured).toBe(false);
|
|
},
|
|
);
|
|
});
|
|
|
|
it("treats env SecretRef appId/appSecret as configured in status", async () => {
|
|
const appIdKey = "FEISHU_APP_ID_STATUS_TEST";
|
|
const appSecretKey = "FEISHU_APP_CREDENTIAL_STATUS_TEST"; // pragma: allowlist secret
|
|
await withEnvVars(
|
|
{
|
|
[appIdKey]: "cli_env_123",
|
|
[appSecretKey]: "env-credential-456", // pragma: allowlist secret
|
|
},
|
|
async () => {
|
|
const status = await getStatusWithEnvRefs({ appIdKey, appSecretKey });
|
|
expect(status.configured).toBe(true);
|
|
},
|
|
);
|
|
});
|
|
});
|