























@@ -1,91 +1,84 @@
1+import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
12import { describe, expect, it, vi } from "vitest";
2-import {
3-createActiveCfgProvider,
4-resolveActiveCfg,
5-type GatewayCfg,
6-type GatewayCfgFetcher,
7-} from "./active-cfg.js";
3+import { createActiveCfgProvider, resolveActiveCfg, type GatewayCfgLoader } from "./active-cfg.js";
849-const getRuntimeConfigMock = vi.hoisted(() => vi.fn<() => GatewayCfg | undefined>());
5+const getRuntimeConfigMock = vi.hoisted(() => vi.fn<() => OpenClawConfig>());
106117vi.mock("openclaw/plugin-sdk/runtime-config-snapshot", () => ({
128getRuntimeConfig: getRuntimeConfigMock,
139}));
141015-describe("resolveActiveCfg", () => {
16-it("returns the freshly fetched value when present", () => {
17-const fresh = { bindings: [{ id: "fresh" }] };
18-const fallback = { bindings: [{ id: "stale" }] };
19-const fetch: GatewayCfgFetcher = () => fresh;
20-21-expect(resolveActiveCfg(fetch, fallback)).toBe(fresh);
22-});
11+function asCfg(shape: { bindings: Array<{ id: string }> }): OpenClawConfig {
12+return shape as unknown as OpenClawConfig;
13+}
231424-it("falls back when the fetcher returns undefined", () => {
25-const fallback = { bindings: [{ id: "stale" }] };
26-const fetch: GatewayCfgFetcher = () => undefined;
15+describe("resolveActiveCfg", () => {
16+it("returns the freshly loaded value when the loader succeeds", () => {
17+const fresh = asCfg({ bindings: [{ id: "fresh" }] });
18+const fallback = asCfg({ bindings: [{ id: "stale" }] });
19+const loader: GatewayCfgLoader = () => fresh;
272028-expect(resolveActiveCfg(fetch, fallback)).toBe(fallback);
21+expect(resolveActiveCfg(loader, fallback)).toBe(fresh);
2922});
302331-it("falls back when the fetcher throws", () => {
32-const fallback = { bindings: [{ id: "stale" }] };
33-const fetch: GatewayCfgFetcher = () => {
24+it("falls back when the loader throws", () => {
25+const fallback = asCfg({ bindings: [{ id: "stale" }] });
26+const loader: GatewayCfgLoader = () => {
3427throw new Error("snapshot not initialised");
3528};
362937-expect(resolveActiveCfg(fetch, fallback)).toBe(fallback);
30+expect(resolveActiveCfg(loader, fallback)).toBe(fallback);
3831});
3932});
40334134describe("createActiveCfgProvider", () => {
42-it("invokes the injected fetcher on every getActiveCfg call", () => {
43-const fallback = { bindings: [] };
44-const first = { bindings: [{ id: "first" }] };
45-const second = { bindings: [{ id: "second" }] };
46-const fetch = vi
47-.fn<() => GatewayCfg | undefined>()
35+it("invokes the injected loader on every getActiveCfg call", () => {
36+const fallback = asCfg({ bindings: [] });
37+const first = asCfg({ bindings: [{ id: "first" }] });
38+const second = asCfg({ bindings: [{ id: "second" }] });
39+const load = vi
40+.fn<() => OpenClawConfig>()
4841.mockReturnValueOnce(first)
4942.mockReturnValueOnce(second);
504351-const provider = createActiveCfgProvider({ fallback, fetch });
44+const provider = createActiveCfgProvider({ fallback, load });
52455346expect(provider.getActiveCfg()).toBe(first);
5447expect(provider.getActiveCfg()).toBe(second);
55-expect(fetch).toHaveBeenCalledTimes(2);
48+expect(load).toHaveBeenCalledTimes(2);
5649});
575058-it("never caches a previously fetched value", () => {
59-const fallback = { bindings: [] };
60-const calls: GatewayCfg[] = [
61-{ bindings: [{ id: "a" }] },
62-{ bindings: [{ id: "b" }] },
63-{ bindings: [{ id: "c" }] },
51+it("never caches a previously loaded value", () => {
52+const fallback = asCfg({ bindings: [] });
53+const calls: OpenClawConfig[] = [
54+asCfg({ bindings: [{ id: "a" }] }),
55+asCfg({ bindings: [{ id: "b" }] }),
56+asCfg({ bindings: [{ id: "c" }] }),
6457];
6558let index = 0;
6659const provider = createActiveCfgProvider({
6760 fallback,
68-fetch: () => calls[index++],
61+load: () => calls[index++],
6962});
70637164expect(provider.getActiveCfg()).toBe(calls[0]);
7265expect(provider.getActiveCfg()).toBe(calls[1]);
7366expect(provider.getActiveCfg()).toBe(calls[2]);
7467});
756876-it("delegates to getRuntimeConfig when no fetcher is provided", () => {
77-const live = { bindings: [{ id: "live" }] };
69+it("delegates to getRuntimeConfig when no loader is provided", () => {
70+const live = asCfg({ bindings: [{ id: "live" }] });
7871getRuntimeConfigMock.mockReset();
7972getRuntimeConfigMock.mockReturnValue(live);
807381-const provider = createActiveCfgProvider({ fallback: { bindings: [] } });
74+const provider = createActiveCfgProvider({ fallback: asCfg({ bindings: [] }) });
82758376expect(provider.getActiveCfg()).toBe(live);
8477expect(getRuntimeConfigMock).toHaveBeenCalledTimes(1);
8578});
86798780it("falls back to the supplied snapshot when the SDK getter throws", () => {
88-const fallback = { bindings: [{ id: "snapshot" }] };
81+const fallback = asCfg({ bindings: [{ id: "snapshot" }] });
8982getRuntimeConfigMock.mockReset();
9083getRuntimeConfigMock.mockImplementation(() => {
9184throw new Error("not ready");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。