mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:40:44 +00:00
test(extensions): trim hot extension imports
This commit is contained in:
@@ -11,13 +11,13 @@
|
||||
// - #60715 BB health check fails on LAN/private serverUrl
|
||||
// - #66869 move `?password=` → header auth (future-proofed via AuthStrategy)
|
||||
|
||||
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { isBlockedHostnameOrIp, type SsrFPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
import { resolveBlueBubblesServerAccount } from "./account-resolve.js";
|
||||
import { extractAttachments } from "./monitor-normalize.js";
|
||||
import { postMultipartFormData } from "./multipart.js";
|
||||
import { resolveRequestUrl } from "./request-url.js";
|
||||
import { DEFAULT_ACCOUNT_ID } from "./runtime-api.js";
|
||||
import type { OpenClawConfig } from "./runtime-api.js";
|
||||
import { getBlueBubblesRuntime } from "./runtime.js";
|
||||
import {
|
||||
|
||||
13
extensions/whatsapp/src/account-ids.ts
Normal file
13
extensions/whatsapp/src/account-ids.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { createAccountListHelpers } from "openclaw/plugin-sdk/account-core";
|
||||
|
||||
const {
|
||||
listConfiguredAccountIds,
|
||||
listAccountIds,
|
||||
resolveDefaultAccountId: resolveDefaultWhatsAppAccountId,
|
||||
} = createAccountListHelpers("whatsapp");
|
||||
|
||||
export {
|
||||
listConfiguredAccountIds,
|
||||
listAccountIds as listWhatsAppAccountIds,
|
||||
resolveDefaultWhatsAppAccountId,
|
||||
};
|
||||
@@ -1,7 +1,6 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import {
|
||||
createAccountListHelpers,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
normalizeAccountId,
|
||||
resolveUserPath,
|
||||
@@ -11,9 +10,16 @@ import type { DmPolicy, GroupPolicy, ReplyToMode } from "openclaw/plugin-sdk/con
|
||||
import { resolveOAuthDir } from "openclaw/plugin-sdk/state-paths";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { resolveMergedWhatsAppAccountConfig } from "./account-config.js";
|
||||
import {
|
||||
listConfiguredAccountIds,
|
||||
listWhatsAppAccountIds,
|
||||
resolveDefaultWhatsAppAccountId,
|
||||
} from "./account-ids.js";
|
||||
import type { WhatsAppAccountConfig } from "./account-types.js";
|
||||
import { hasWebCredsSync } from "./creds-files.js";
|
||||
|
||||
export { listWhatsAppAccountIds, resolveDefaultWhatsAppAccountId } from "./account-ids.js";
|
||||
|
||||
export type ResolvedWhatsAppAccount = {
|
||||
accountId: string;
|
||||
name?: string;
|
||||
@@ -43,11 +49,6 @@ export type ResolvedWhatsAppAccount = {
|
||||
|
||||
export const DEFAULT_WHATSAPP_MEDIA_MAX_MB = 50;
|
||||
|
||||
const { listConfiguredAccountIds, listAccountIds, resolveDefaultAccountId } =
|
||||
createAccountListHelpers("whatsapp");
|
||||
export const listWhatsAppAccountIds = listAccountIds;
|
||||
export const resolveDefaultWhatsAppAccountId = resolveDefaultAccountId;
|
||||
|
||||
export function listWhatsAppAuthDirs(cfg: OpenClawConfig): string[] {
|
||||
const oauthDir = resolveOAuthDir();
|
||||
const whatsappDir = path.join(oauthDir, "whatsapp");
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { getActiveWebListener, resolveWebAccountId } from "./active-listener.js";
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/config-runtime", () => ({
|
||||
loadConfig: () => ({
|
||||
@@ -6,18 +7,19 @@ vi.mock("openclaw/plugin-sdk/config-runtime", () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
const registryMocks = vi.hoisted(() => ({
|
||||
getRegisteredWhatsAppConnectionController: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("./connection-controller-registry.js", () => ({
|
||||
getRegisteredWhatsAppConnectionController:
|
||||
registryMocks.getRegisteredWhatsAppConnectionController,
|
||||
}));
|
||||
|
||||
const WHATSAPP_ACTIVE_LISTENER_TEST_CFG = {
|
||||
channels: { whatsapp: { accounts: { work: { enabled: true } }, defaultAccount: "work" } },
|
||||
};
|
||||
|
||||
type ActiveListenerModule = typeof import("./active-listener.js");
|
||||
|
||||
const activeListenerModuleUrl = new URL("./active-listener.ts", import.meta.url).href;
|
||||
|
||||
async function importActiveListenerModule(cacheBust: string): Promise<ActiveListenerModule> {
|
||||
return (await import(`${activeListenerModuleUrl}?t=${cacheBust}`)) as ActiveListenerModule;
|
||||
}
|
||||
|
||||
function makeListener() {
|
||||
return {
|
||||
sendMessage: vi.fn(async () => ({ messageId: "msg-1" })),
|
||||
@@ -27,53 +29,43 @@ function makeListener() {
|
||||
};
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
vi.doUnmock("./connection-controller-registry.js");
|
||||
beforeEach(() => {
|
||||
registryMocks.getRegisteredWhatsAppConnectionController.mockReset();
|
||||
});
|
||||
|
||||
describe("active WhatsApp listener view", () => {
|
||||
it("reads controller-backed state across duplicate module instances", async () => {
|
||||
it("reads controller-backed state", () => {
|
||||
const listener = makeListener();
|
||||
vi.doMock("./connection-controller-registry.js", () => ({
|
||||
getRegisteredWhatsAppConnectionController: (accountId: string) =>
|
||||
registryMocks.getRegisteredWhatsAppConnectionController.mockImplementation(
|
||||
(accountId: string) =>
|
||||
accountId === "work"
|
||||
? {
|
||||
getActiveListener: () => listener,
|
||||
}
|
||||
: null,
|
||||
}));
|
||||
);
|
||||
|
||||
const first = await importActiveListenerModule(`first-${Date.now()}`);
|
||||
const second = await importActiveListenerModule(`second-${Date.now()}`);
|
||||
|
||||
expect(first.getActiveWebListener("work")).toBe(listener);
|
||||
expect(second.getActiveWebListener("work")).toBe(listener);
|
||||
expect(getActiveWebListener("work")).toBe(listener);
|
||||
});
|
||||
|
||||
it("resolves the configured default account when accountId is omitted", async () => {
|
||||
it("resolves the configured default account when accountId is omitted", () => {
|
||||
const listener = makeListener();
|
||||
vi.doMock("./connection-controller-registry.js", () => ({
|
||||
getRegisteredWhatsAppConnectionController: (accountId: string) =>
|
||||
registryMocks.getRegisteredWhatsAppConnectionController.mockImplementation(
|
||||
(accountId: string) =>
|
||||
accountId === "work"
|
||||
? {
|
||||
getActiveListener: () => listener,
|
||||
}
|
||||
: null,
|
||||
}));
|
||||
);
|
||||
|
||||
const mod = await importActiveListenerModule(`default-${Date.now()}`);
|
||||
|
||||
expect(mod.resolveWebAccountId({ cfg: WHATSAPP_ACTIVE_LISTENER_TEST_CFG })).toBe("work");
|
||||
expect(mod.getActiveWebListener("work")).toBe(listener);
|
||||
expect(resolveWebAccountId({ cfg: WHATSAPP_ACTIVE_LISTENER_TEST_CFG })).toBe("work");
|
||||
expect(getActiveWebListener("work")).toBe(listener);
|
||||
});
|
||||
|
||||
it("returns null when the controller has no active listener for the account", async () => {
|
||||
vi.doMock("./connection-controller-registry.js", () => ({
|
||||
getRegisteredWhatsAppConnectionController: () => null,
|
||||
}));
|
||||
it("returns null when the controller has no active listener for the account", () => {
|
||||
registryMocks.getRegisteredWhatsAppConnectionController.mockReturnValue(null);
|
||||
|
||||
const mod = await importActiveListenerModule(`missing-${Date.now()}`);
|
||||
|
||||
expect(mod.getActiveWebListener("work")).toBeNull();
|
||||
expect(getActiveWebListener("work")).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { resolveDefaultWhatsAppAccountId } from "./accounts.js";
|
||||
import { resolveDefaultWhatsAppAccountId } from "./account-ids.js";
|
||||
import { getRegisteredWhatsAppConnectionController } from "./connection-controller-registry.js";
|
||||
import type { ActiveWebListener, ActiveWebSendOptions } from "./inbound/types.js";
|
||||
|
||||
|
||||
@@ -2,9 +2,8 @@ import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/routing";
|
||||
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createQueuedWizardPrompter } from "../../../test/helpers/plugins/setup-wizard.js";
|
||||
import { whatsappApprovalAuth } from "./approval-auth.js";
|
||||
import { WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store.js";
|
||||
import { whatsappPlugin } from "./channel.js";
|
||||
import { whatsappSetupPlugin } from "./channel.setup.js";
|
||||
import { checkWhatsAppHeartbeatReady } from "./heartbeat.js";
|
||||
import type { OpenClawConfig } from "./runtime-api.js";
|
||||
import { finalizeWhatsAppSetup } from "./setup-finalize.js";
|
||||
@@ -160,13 +159,6 @@ describe("whatsapp setup wizard", () => {
|
||||
hoisted.resolveWhatsAppAuthDir.mockReturnValue({ authDir: "/tmp/openclaw-whatsapp-test" });
|
||||
});
|
||||
|
||||
it("exposes approval auth through approvalCapability only", () => {
|
||||
expect(whatsappPlugin.approvalCapability).toBe(whatsappApprovalAuth);
|
||||
expect(typeof whatsappPlugin.auth?.login).toBe("function");
|
||||
expect("authorizeActorAction" in (whatsappPlugin.auth ?? {})).toBe(false);
|
||||
expect("getActionAvailabilityState" in (whatsappPlugin.auth ?? {})).toBe(false);
|
||||
});
|
||||
|
||||
it("applies owner allowlist when forceAllowFrom is enabled", async () => {
|
||||
const harness = createWhatsAppOwnerAllowlistHarness(createQueuedWizardPrompter);
|
||||
|
||||
@@ -245,7 +237,7 @@ describe("whatsapp setup wizard", () => {
|
||||
});
|
||||
|
||||
it("surfaces accounts.default group warning paths for named accounts", () => {
|
||||
const warnings = whatsappPlugin.security?.collectWarnings?.({
|
||||
const warnings = whatsappSetupPlugin.security?.collectWarnings?.({
|
||||
cfg: {
|
||||
channels: {
|
||||
whatsapp: {
|
||||
@@ -277,7 +269,7 @@ describe("whatsapp setup wizard", () => {
|
||||
});
|
||||
|
||||
it("surfaces mixed-case default-account group warning paths for named accounts", () => {
|
||||
const warnings = whatsappPlugin.security?.collectWarnings?.({
|
||||
const warnings = whatsappSetupPlugin.security?.collectWarnings?.({
|
||||
cfg: {
|
||||
channels: {
|
||||
whatsapp: {
|
||||
@@ -458,7 +450,7 @@ describe("whatsapp setup wizard", () => {
|
||||
hoisted.readWebAuthState.mockResolvedValueOnce("unstable");
|
||||
|
||||
await expect(
|
||||
whatsappPlugin.config.isConfigured?.(
|
||||
whatsappSetupPlugin.config.isConfigured?.(
|
||||
{
|
||||
authDir: "/tmp/work",
|
||||
} as never,
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
type RegistryModule = typeof import("./connection-controller-registry.js");
|
||||
|
||||
const registryModuleUrl = new URL("./connection-controller-registry.ts", import.meta.url).href;
|
||||
|
||||
async function importRegistryModule(cacheBust: string): Promise<RegistryModule> {
|
||||
return (await import(`${registryModuleUrl}?t=${cacheBust}`)) as RegistryModule;
|
||||
}
|
||||
|
||||
describe("WhatsApp connection controller registry", () => {
|
||||
it("shares registered controllers across duplicate module instances", async () => {
|
||||
const first = await importRegistryModule(`first-${Date.now()}`);
|
||||
const second = await importRegistryModule(`second-${Date.now()}`);
|
||||
const controller = {
|
||||
getActiveListener: vi.fn(() => null),
|
||||
};
|
||||
|
||||
first.registerWhatsAppConnectionController("work", controller);
|
||||
|
||||
try {
|
||||
expect(second.getRegisteredWhatsAppConnectionController("work")).toBe(controller);
|
||||
} finally {
|
||||
first.unregisterWhatsAppConnectionController("work", controller);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user