mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-22 14:55:36 +00:00
Normalize WhatsApp onboarding allowlist entries to digit-only WhatsApp IDs and reject invalid owner-phone inputs during prompt validation.
218 lines
6.1 KiB
TypeScript
218 lines
6.1 KiB
TypeScript
import { expect } from "vitest";
|
|
|
|
type WhatsAppSetupConfig = {
|
|
channels?: {
|
|
whatsapp?: {
|
|
selfChatMode?: boolean;
|
|
dmPolicy?: string;
|
|
allowFrom?: string[];
|
|
accounts?: Record<string, { dmPolicy?: string; allowFrom?: string[]; authDir?: string }>;
|
|
};
|
|
};
|
|
};
|
|
|
|
type WizardPromptHarness = {
|
|
text: (...args: unknown[]) => unknown;
|
|
select: (...args: unknown[]) => unknown;
|
|
note: (...args: unknown[]) => unknown;
|
|
};
|
|
|
|
type QueuedWizardPrompterFactory<T extends WizardPromptHarness> = (params: {
|
|
confirmValues?: boolean[];
|
|
selectValues?: string[];
|
|
textValues?: string[];
|
|
}) => T;
|
|
|
|
const WHATSAPP_OWNER_NUMBER_INPUT = "+1 (555) 555-0123";
|
|
const WHATSAPP_OWNER_NUMBER_E164 = "+15555550123";
|
|
const WHATSAPP_OWNER_NUMBER = "15555550123";
|
|
const WHATSAPP_PERSONAL_NUMBER_INPUT = "+1 (555) 111-2222";
|
|
const WHATSAPP_PERSONAL_NUMBER = "15551112222";
|
|
const WHATSAPP_ACCESS_NOTE_TITLE = "WhatsApp DM access";
|
|
const WHATSAPP_LOGIN_NOTE_TITLE = "WhatsApp";
|
|
|
|
export function createWhatsAppRootAllowFromConfig(): WhatsAppSetupConfig {
|
|
return {
|
|
channels: {
|
|
whatsapp: {
|
|
allowFrom: [WHATSAPP_OWNER_NUMBER_E164],
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createWhatsAppOwnerAllowlistHarness<T extends WizardPromptHarness>(
|
|
createPrompter: QueuedWizardPrompterFactory<T>,
|
|
): T {
|
|
return createPrompter({
|
|
confirmValues: [false],
|
|
textValues: [WHATSAPP_OWNER_NUMBER_INPUT],
|
|
});
|
|
}
|
|
|
|
export function createWhatsAppPersonalPhoneHarness<T extends WizardPromptHarness>(
|
|
createPrompter: QueuedWizardPrompterFactory<T>,
|
|
): T {
|
|
return createPrompter({
|
|
confirmValues: [false],
|
|
selectValues: ["personal"],
|
|
textValues: [WHATSAPP_PERSONAL_NUMBER_INPUT],
|
|
});
|
|
}
|
|
|
|
export function createWhatsAppLinkingHarness<T extends WizardPromptHarness>(
|
|
createPrompter: QueuedWizardPrompterFactory<T>,
|
|
): T {
|
|
return createPrompter({
|
|
confirmValues: [true],
|
|
selectValues: ["separate", "disabled"],
|
|
});
|
|
}
|
|
|
|
export function createWhatsAppWorkAccountConfig(
|
|
params: {
|
|
defaultAccount?: string;
|
|
} = {},
|
|
): WhatsAppSetupConfig {
|
|
return {
|
|
channels: {
|
|
whatsapp: {
|
|
...(params.defaultAccount ? { defaultAccount: params.defaultAccount } : {}),
|
|
dmPolicy: "disabled",
|
|
allowFrom: [WHATSAPP_OWNER_NUMBER_E164],
|
|
accounts: {
|
|
work: {
|
|
authDir: "/tmp/work",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createWhatsAppAllowlistModeInput(): {
|
|
selectValues: string[];
|
|
textValues: string[];
|
|
} {
|
|
return {
|
|
selectValues: ["separate", "allowlist", "list"],
|
|
textValues: [`${WHATSAPP_OWNER_NUMBER_INPUT}, ${WHATSAPP_OWNER_NUMBER}, *`],
|
|
};
|
|
}
|
|
|
|
function expectWhatsAppDmAccess(
|
|
cfg: WhatsAppSetupConfig,
|
|
expected: {
|
|
selfChatMode: boolean;
|
|
dmPolicy: string;
|
|
allowFrom?: string[];
|
|
},
|
|
): void {
|
|
expect(cfg.channels?.whatsapp?.selfChatMode).toBe(expected.selfChatMode);
|
|
expect(cfg.channels?.whatsapp?.dmPolicy).toBe(expected.dmPolicy);
|
|
if ("allowFrom" in expected) {
|
|
expect(cfg.channels?.whatsapp?.allowFrom).toEqual(expected.allowFrom);
|
|
} else {
|
|
expect(cfg.channels?.whatsapp?.allowFrom).toBeUndefined();
|
|
}
|
|
}
|
|
|
|
export function expectWhatsAppWorkAccountOpenAccess(cfg: WhatsAppSetupConfig): void {
|
|
expect(cfg.channels?.whatsapp?.dmPolicy).toBe("disabled");
|
|
expect(cfg.channels?.whatsapp?.allowFrom).toEqual([WHATSAPP_OWNER_NUMBER_E164]);
|
|
expect(cfg.channels?.whatsapp?.accounts?.work?.dmPolicy).toBe("open");
|
|
expect(cfg.channels?.whatsapp?.accounts?.work?.allowFrom).toEqual(["*", WHATSAPP_OWNER_NUMBER]);
|
|
}
|
|
|
|
function expectWhatsAppOwnerNumberPrompt(harness: WizardPromptHarness): void {
|
|
expect(harness.text).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
message: "Your personal WhatsApp number (the phone you will message from)",
|
|
}),
|
|
);
|
|
}
|
|
|
|
export function expectWhatsAppOwnerAllowlistSetup(
|
|
cfg: WhatsAppSetupConfig,
|
|
harness: WizardPromptHarness,
|
|
): void {
|
|
expectWhatsAppDmAccess(cfg, {
|
|
selfChatMode: true,
|
|
dmPolicy: "allowlist",
|
|
allowFrom: [WHATSAPP_OWNER_NUMBER],
|
|
});
|
|
expectWhatsAppOwnerNumberPrompt(harness);
|
|
}
|
|
|
|
export function expectWhatsAppSeparatePhoneDisabledSetup(
|
|
cfg: WhatsAppSetupConfig,
|
|
harness: WizardPromptHarness,
|
|
): void {
|
|
expectWhatsAppDmAccess(cfg, {
|
|
selfChatMode: false,
|
|
dmPolicy: "disabled",
|
|
});
|
|
expect(harness.text).not.toHaveBeenCalled();
|
|
}
|
|
|
|
export function expectWhatsAppAllowlistModeSetup(cfg: WhatsAppSetupConfig): void {
|
|
expectWhatsAppDmAccess(cfg, {
|
|
selfChatMode: false,
|
|
dmPolicy: "allowlist",
|
|
allowFrom: [WHATSAPP_OWNER_NUMBER, "*"],
|
|
});
|
|
}
|
|
|
|
export function expectWhatsAppPersonalPhoneSetup(cfg: WhatsAppSetupConfig): void {
|
|
expectWhatsAppDmAccess(cfg, {
|
|
selfChatMode: true,
|
|
dmPolicy: "allowlist",
|
|
allowFrom: [WHATSAPP_PERSONAL_NUMBER],
|
|
});
|
|
}
|
|
|
|
export function expectWhatsAppOpenPolicySetup(
|
|
cfg: WhatsAppSetupConfig,
|
|
harness: WizardPromptHarness,
|
|
): void {
|
|
expectWhatsAppDmAccess(cfg, {
|
|
selfChatMode: false,
|
|
dmPolicy: "open",
|
|
allowFrom: ["*", WHATSAPP_OWNER_NUMBER],
|
|
});
|
|
expect(harness.select).toHaveBeenCalledTimes(2);
|
|
expect(harness.text).not.toHaveBeenCalled();
|
|
}
|
|
|
|
export function expectNoWhatsAppLoginFollowup(harness: WizardPromptHarness): void {
|
|
expect(harness.note).not.toHaveBeenCalledWith(
|
|
expect.stringContaining("openclaw channels login"),
|
|
WHATSAPP_LOGIN_NOTE_TITLE,
|
|
);
|
|
}
|
|
|
|
export function expectWhatsAppLoginFollowup(harness: WizardPromptHarness): void {
|
|
expect(harness.note).toHaveBeenCalledWith(
|
|
expect.stringContaining("openclaw channels login"),
|
|
WHATSAPP_LOGIN_NOTE_TITLE,
|
|
);
|
|
}
|
|
|
|
export function expectWhatsAppWorkAccountAccessNote(harness: WizardPromptHarness): void {
|
|
expect(harness.note).toHaveBeenCalledWith(
|
|
expect.stringContaining(
|
|
"`channels.whatsapp.accounts.work.dmPolicy` + `channels.whatsapp.accounts.work.allowFrom`",
|
|
),
|
|
WHATSAPP_ACCESS_NOTE_TITLE,
|
|
);
|
|
}
|
|
|
|
export function expectWhatsAppDefaultAccountAccessNote(harness: WizardPromptHarness): void {
|
|
expect(harness.note).toHaveBeenCalledWith(
|
|
expect.stringContaining(
|
|
"`channels.whatsapp.accounts.default.dmPolicy` + `channels.whatsapp.accounts.default.allowFrom`",
|
|
),
|
|
WHATSAPP_ACCESS_NOTE_TITLE,
|
|
);
|
|
}
|