mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-17 12:11:20 +00:00
Tests: add campaign-2 controller characterization coverage
This commit is contained in:
@@ -173,6 +173,30 @@ describe("loadToolsCatalog", () => {
|
||||
expect(state.toolsCatalogError).toContain("gateway unavailable");
|
||||
expect(state.toolsCatalogLoading).toBe(false);
|
||||
});
|
||||
|
||||
it("ignores catalog responses after selected agent changes mid-request", async () => {
|
||||
const { state, request } = createState();
|
||||
const resolvers: Array<(value: unknown) => void> = [];
|
||||
request.mockImplementation(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
resolvers.push(resolve);
|
||||
}),
|
||||
);
|
||||
|
||||
const pending = loadToolsCatalog(state, "main");
|
||||
state.agentsSelectedId = "other-agent";
|
||||
resolvers.shift()?.({
|
||||
agentId: "main",
|
||||
profiles: [{ id: "full", label: "Full" }],
|
||||
groups: [],
|
||||
});
|
||||
await pending;
|
||||
|
||||
expect(state.toolsCatalogResult).toBeNull();
|
||||
expect(state.toolsCatalogError).toBeNull();
|
||||
expect(state.toolsCatalogLoading).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("loadToolsEffective", () => {
|
||||
@@ -224,6 +248,31 @@ describe("loadToolsEffective", () => {
|
||||
expect(state.toolsEffectiveLoading).toBe(false);
|
||||
});
|
||||
|
||||
it("ignores effective-tool responses after selected agent changes mid-request", async () => {
|
||||
const { state, request } = createState();
|
||||
const resolvers: Array<(value: unknown) => void> = [];
|
||||
request.mockImplementation(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
resolvers.push(resolve);
|
||||
}),
|
||||
);
|
||||
|
||||
const pending = loadToolsEffective(state, { agentId: "main", sessionKey: "main" });
|
||||
state.agentsSelectedId = "other-agent";
|
||||
resolvers.shift()?.({
|
||||
agentId: "main",
|
||||
profile: "coding",
|
||||
groups: [],
|
||||
});
|
||||
await pending;
|
||||
|
||||
expect(state.toolsEffectiveResult).toBeNull();
|
||||
expect(state.toolsEffectiveResultKey).toBeNull();
|
||||
expect(state.toolsEffectiveError).toBeNull();
|
||||
expect(state.toolsEffectiveLoading).toBe(false);
|
||||
});
|
||||
|
||||
it("uses the catalog provider when the active session reports a stale provider", async () => {
|
||||
const { state, request } = createState();
|
||||
const sessionsResult = state.sessionsResult!;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
installSkill,
|
||||
loadClawHubDetail,
|
||||
saveSkillApiKey,
|
||||
searchClawHub,
|
||||
setClawHubSearchQuery,
|
||||
@@ -113,6 +114,63 @@ describe("searchClawHub", () => {
|
||||
expect(state.clawhubSearchError).toBeNull();
|
||||
expect(state.clawhubSearchLoading).toBe(false);
|
||||
});
|
||||
|
||||
it("ignores stale search responses after query changes", async () => {
|
||||
const { state, request } = createState();
|
||||
const resolvers: Array<(value: unknown) => void> = [];
|
||||
request.mockImplementation(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
resolvers.push(resolve);
|
||||
}),
|
||||
);
|
||||
|
||||
const pending = searchClawHub(state, "github");
|
||||
setClawHubSearchQuery(state, "gitlab");
|
||||
resolvers.shift()?.({
|
||||
results: [{ score: 1, slug: "github", displayName: "GitHub" }],
|
||||
});
|
||||
await pending;
|
||||
|
||||
expect(state.clawhubSearchQuery).toBe("gitlab");
|
||||
expect(state.clawhubSearchResults).toBeNull();
|
||||
expect(state.clawhubSearchError).toBeNull();
|
||||
expect(state.clawhubSearchLoading).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("loadClawHubDetail", () => {
|
||||
it("ignores stale detail responses after slug changes", async () => {
|
||||
const { state, request } = createState();
|
||||
const resolvers: Array<(value: unknown) => void> = [];
|
||||
request.mockImplementation(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
resolvers.push(resolve);
|
||||
}),
|
||||
);
|
||||
|
||||
const firstPending = loadClawHubDetail(state, "github");
|
||||
const secondPending = loadClawHubDetail(state, "gitlab");
|
||||
|
||||
resolvers.shift()?.({
|
||||
skill: { slug: "github", displayName: "GitHub", createdAt: 1, updatedAt: 2 },
|
||||
});
|
||||
await firstPending;
|
||||
|
||||
expect(state.clawhubDetailSlug).toBe("gitlab");
|
||||
expect(state.clawhubDetail).toBeNull();
|
||||
expect(state.clawhubDetailError).toBeNull();
|
||||
expect(state.clawhubDetailLoading).toBe(true);
|
||||
|
||||
resolvers.shift()?.({
|
||||
skill: { slug: "gitlab", displayName: "GitLab", createdAt: 3, updatedAt: 4 },
|
||||
});
|
||||
await secondPending;
|
||||
|
||||
expect(state.clawhubDetailLoading).toBe(false);
|
||||
expect(state.clawhubDetail?.skill?.slug).toBe("gitlab");
|
||||
});
|
||||
});
|
||||
|
||||
describe("skill mutations", () => {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { __test, loadUsage, type UsageState } from "./usage.ts";
|
||||
import {
|
||||
__test,
|
||||
loadSessionLogs,
|
||||
loadSessionTimeSeries,
|
||||
loadUsage,
|
||||
type UsageState,
|
||||
} from "./usage.ts";
|
||||
|
||||
type RequestFn = (method: string, params?: unknown) => Promise<unknown>;
|
||||
|
||||
@@ -162,6 +168,49 @@ describe("usage controller date interpretation params", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("usage session detail loaders", () => {
|
||||
beforeEach(() => {
|
||||
__test.resetLegacyUsageDateParamsCache();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("keeps optional loaders resilient when requests fail", async () => {
|
||||
const request = vi.fn(async (method: string) => {
|
||||
if (method === "sessions.usage.timeseries" || method === "sessions.usage.logs") {
|
||||
throw new Error("optional endpoint unavailable");
|
||||
}
|
||||
return {};
|
||||
});
|
||||
const state = createState(request);
|
||||
|
||||
await loadSessionTimeSeries(state, "session-1");
|
||||
await loadSessionLogs(state, "session-1");
|
||||
|
||||
expect(state.usageTimeSeries).toBeNull();
|
||||
expect(state.usageSessionLogs).toBeNull();
|
||||
expect(state.usageTimeSeriesLoading).toBe(false);
|
||||
expect(state.usageSessionLogsLoading).toBe(false);
|
||||
});
|
||||
|
||||
it("normalizes usage logs payloads when logs is not an array", async () => {
|
||||
const request = vi.fn(async (method: string) => {
|
||||
if (method === "sessions.usage.logs") {
|
||||
return { logs: "unexpected-shape" };
|
||||
}
|
||||
return {};
|
||||
});
|
||||
const state = createState(request);
|
||||
|
||||
await loadSessionLogs(state, "session-1");
|
||||
|
||||
expect(state.usageSessionLogs).toBeNull();
|
||||
expect(state.usageSessionLogsLoading).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
function createStorageMock() {
|
||||
const store = new Map<string, string>();
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user