refactor(test): dedupe setup wizard helpers

This commit is contained in:
Peter Steinberger
2026-03-22 00:15:51 +00:00
parent 85722d4cf2
commit 30ad059da8
27 changed files with 322 additions and 186 deletions

View File

@@ -1,7 +1,9 @@
import type { RuntimeEnv } from "openclaw/plugin-sdk/testing";
import { vi } from "vitest";
export function createRuntimeEnv(options?: { throwOnExit?: boolean }): RuntimeEnv {
export function createRuntimeEnv<TRuntime = RuntimeEnv>(options?: {
throwOnExit?: boolean;
}): RuntimeEnv {
const throwOnExit = options?.throwOnExit ?? true;
return {
log: vi.fn(),
@@ -13,3 +15,15 @@ export function createRuntimeEnv(options?: { throwOnExit?: boolean }): RuntimeEn
: vi.fn(),
};
}
export function createTypedRuntimeEnv<TRuntime>(options?: { throwOnExit?: boolean }): TRuntime {
return createRuntimeEnv(options) as TRuntime;
}
export function createNonExitingRuntimeEnv(): RuntimeEnv {
return createRuntimeEnv({ throwOnExit: false });
}
export function createNonExitingTypedRuntimeEnv<TRuntime>(): TRuntime {
return createTypedRuntimeEnv<TRuntime>({ throwOnExit: false });
}

View File

@@ -75,6 +75,40 @@ export function createQueuedWizardPrompter(params?: {
type SetupWizardAdapterParams = Parameters<typeof buildChannelSetupWizardAdapterFromSetupWizard>[0];
type SetupWizardPlugin = SetupWizardAdapterParams["plugin"];
type SetupWizard = NonNullable<SetupWizardAdapterParams["wizard"]>;
type SetupWizardCredentialValues = Record<string, string>;
function resolveSetupWizardAccountContext<TCfg>(params: {
cfg?: TCfg;
accountId?: string;
credentialValues?: SetupWizardCredentialValues;
}) {
return {
cfg: (params.cfg ?? {}) as TCfg,
accountId: params.accountId ?? "default",
credentialValues: params.credentialValues ?? {},
};
}
function resolveSetupWizardRuntime<TRuntime>(runtime?: TRuntime): TRuntime {
return (runtime ?? createRuntimeEnv({ throwOnExit: false })) as TRuntime;
}
function resolveSetupWizardPrompter(prompter?: WizardPrompter): WizardPrompter {
return prompter ?? createTestWizardPrompter();
}
function resolveSetupWizardNotePrompter(prompter?: Pick<WizardPrompter, "note">) {
return (
prompter ??
({
note: vi.fn(async () => undefined),
} satisfies Pick<WizardPrompter, "note">)
);
}
export function createSetupWizardAdapter(params: SetupWizardAdapterParams) {
return buildChannelSetupWizardAdapterFromSetupWizard(params);
}
export function createPluginSetupWizardAdapter<
TPlugin extends SetupWizardPlugin & { setupWizard?: SetupWizard },
@@ -83,12 +117,24 @@ export function createPluginSetupWizardAdapter<
if (!wizard) {
throw new Error(`${plugin.id} is missing setupWizard`);
}
return buildChannelSetupWizardAdapterFromSetupWizard({
return createSetupWizardAdapter({
plugin,
wizard,
});
}
export function createPluginSetupWizardConfigure<
TPlugin extends SetupWizardPlugin & { setupWizard?: SetupWizard },
>(plugin: TPlugin) {
return createPluginSetupWizardAdapter(plugin).configure;
}
export function createPluginSetupWizardStatus<
TPlugin extends SetupWizardPlugin & { setupWizard?: SetupWizard },
>(plugin: TPlugin) {
return createPluginSetupWizardAdapter(plugin).getStatus;
}
export async function runSetupWizardConfigure<
TCfg,
TOptions extends Record<string, unknown>,
@@ -123,3 +169,144 @@ export async function runSetupWizardConfigure<
forceAllowFrom: params.forceAllowFrom ?? false,
});
}
export async function runSetupWizardPrepare<
TCfg,
TOptions extends Record<string, unknown>,
TRuntime,
TResult,
>(params: {
prepare?: (args: {
cfg: TCfg;
accountId: string;
credentialValues: Record<string, string>;
runtime: TRuntime;
prompter: WizardPrompter;
options?: TOptions;
}) => Promise<TResult> | TResult;
cfg?: TCfg;
accountId?: string;
credentialValues?: Record<string, string>;
runtime?: TRuntime;
prompter?: WizardPrompter;
options?: TOptions;
}): Promise<TResult | undefined> {
const context = resolveSetupWizardAccountContext({
cfg: params.cfg,
accountId: params.accountId,
credentialValues: params.credentialValues,
});
return await params.prepare?.({
...context,
runtime: resolveSetupWizardRuntime(params.runtime),
prompter: resolveSetupWizardPrompter(params.prompter),
options: params.options,
});
}
export async function runSetupWizardFinalize<
TCfg,
TOptions extends Record<string, unknown>,
TRuntime,
TResult,
>(params: {
finalize?: (args: {
cfg: TCfg;
accountId: string;
credentialValues: Record<string, string>;
runtime: TRuntime;
prompter: WizardPrompter;
options?: TOptions;
forceAllowFrom: boolean;
}) => Promise<TResult> | TResult;
cfg?: TCfg;
accountId?: string;
credentialValues?: Record<string, string>;
runtime?: TRuntime;
prompter?: WizardPrompter;
options?: TOptions;
forceAllowFrom?: boolean;
}): Promise<TResult | undefined> {
const context = resolveSetupWizardAccountContext({
cfg: params.cfg,
accountId: params.accountId,
credentialValues: params.credentialValues,
});
return await params.finalize?.({
...context,
runtime: resolveSetupWizardRuntime(params.runtime),
prompter: resolveSetupWizardPrompter(params.prompter),
options: params.options,
forceAllowFrom: params.forceAllowFrom ?? false,
});
}
export async function promptSetupWizardAllowFrom<TCfg, TResult>(params: {
promptAllowFrom?: (args: {
cfg: TCfg;
prompter: WizardPrompter;
accountId: string;
}) => Promise<TResult> | TResult;
cfg?: TCfg;
prompter?: WizardPrompter;
accountId?: string;
}): Promise<TResult | undefined> {
const context = resolveSetupWizardAccountContext({
cfg: params.cfg,
accountId: params.accountId,
});
return await params.promptAllowFrom?.({
cfg: context.cfg,
accountId: context.accountId,
prompter: resolveSetupWizardPrompter(params.prompter),
});
}
export async function resolveSetupWizardAllowFromEntries<TCfg, TResult>(params: {
resolveEntries?: (args: {
cfg: TCfg;
accountId: string;
credentialValues: Record<string, string>;
entries: string[];
}) => Promise<TResult> | TResult;
entries: string[];
cfg?: TCfg;
accountId?: string;
credentialValues?: SetupWizardCredentialValues;
}): Promise<TResult | undefined> {
const context = resolveSetupWizardAccountContext({
cfg: params.cfg,
accountId: params.accountId,
credentialValues: params.credentialValues,
});
return await params.resolveEntries?.({
...context,
entries: params.entries,
});
}
export async function resolveSetupWizardGroupAllowlist<TCfg, TResult>(params: {
resolveAllowlist?: (args: {
cfg: TCfg;
accountId: string;
credentialValues: Record<string, string>;
entries: string[];
prompter: Pick<WizardPrompter, "note">;
}) => Promise<TResult> | TResult;
entries: string[];
cfg?: TCfg;
accountId?: string;
credentialValues?: SetupWizardCredentialValues;
prompter?: Pick<WizardPrompter, "note">;
}): Promise<TResult | undefined> {
const context = resolveSetupWizardAccountContext({
cfg: params.cfg,
accountId: params.accountId,
credentialValues: params.credentialValues,
});
return await params.resolveAllowlist?.({
...context,
entries: params.entries,
prompter: resolveSetupWizardNotePrompter(params.prompter),
});
}