mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 04:51:25 +00:00
test: dedupe and optimize test suites
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { telegramPlugin } from "../../extensions/telegram/src/channel.js";
|
||||
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
import { createTestRegistry } from "../test-utils/channel-plugins.js";
|
||||
@@ -99,13 +99,19 @@ async function runSuccessfulTelegramProbe(
|
||||
return { calls, telegram };
|
||||
}
|
||||
|
||||
let createPluginRuntime: typeof import("../plugins/runtime/index.js").createPluginRuntime;
|
||||
let setTelegramRuntime: typeof import("../../extensions/telegram/src/runtime.js").setTelegramRuntime;
|
||||
|
||||
describe("getHealthSnapshot", () => {
|
||||
beforeEach(async () => {
|
||||
beforeAll(async () => {
|
||||
({ createPluginRuntime } = await import("../plugins/runtime/index.js"));
|
||||
({ setTelegramRuntime } = await import("../../extensions/telegram/src/runtime.js"));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
setActivePluginRegistry(
|
||||
createTestRegistry([{ pluginId: "telegram", plugin: telegramPlugin, source: "test" }]),
|
||||
);
|
||||
const { createPluginRuntime } = await import("../plugins/runtime/index.js");
|
||||
const { setTelegramRuntime } = await import("../../extensions/telegram/src/runtime.js");
|
||||
setTelegramRuntime(createPluginRuntime());
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
let modelsListCommand: typeof import("./models/list.list-command.js").modelsListCommand;
|
||||
let loadModelRegistry: typeof import("./models/list.registry.js").loadModelRegistry;
|
||||
let toModelRow: typeof import("./models/list.registry.js").toModelRow;
|
||||
|
||||
const loadConfig = vi.fn();
|
||||
const ensureOpenClawModelsJson = vi.fn().mockResolvedValue(undefined);
|
||||
@@ -274,6 +276,7 @@ describe("models list/status", () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
({ modelsListCommand } = await import("./models/list.list-command.js"));
|
||||
({ loadModelRegistry, toModelRow } = await import("./models/list.registry.js"));
|
||||
});
|
||||
|
||||
it("models list syncs auth-profiles into auth.json before availability checks", async () => {
|
||||
@@ -309,17 +312,12 @@ describe("models list/status", () => {
|
||||
expect(runtime.log.mock.calls[0]?.[0]).toBe("zai/glm-4.7");
|
||||
});
|
||||
|
||||
it("models list provider filter normalizes z.ai alias", async () => {
|
||||
await expectZaiProviderFilter("z.ai");
|
||||
});
|
||||
|
||||
it("models list provider filter normalizes Z.AI alias casing", async () => {
|
||||
await expectZaiProviderFilter("Z.AI");
|
||||
});
|
||||
|
||||
it("models list provider filter normalizes z-ai alias", async () => {
|
||||
await expectZaiProviderFilter("z-ai");
|
||||
});
|
||||
it.each(["z.ai", "Z.AI", "z-ai"] as const)(
|
||||
"models list provider filter normalizes %s alias",
|
||||
async (provider) => {
|
||||
await expectZaiProviderFilter(provider);
|
||||
},
|
||||
);
|
||||
|
||||
it("models list marks auth as unavailable when ZAI key is missing", async () => {
|
||||
setDefaultZaiRegistry({ available: false });
|
||||
@@ -331,57 +329,67 @@ describe("models list/status", () => {
|
||||
expect(payload.models[0]?.available).toBe(false);
|
||||
});
|
||||
|
||||
it("models list resolves antigravity opus 4.6 thinking from 4.5 template", async () => {
|
||||
const payload = await runGoogleAntigravityListCase({
|
||||
it.each([
|
||||
{
|
||||
name: "thinking",
|
||||
configuredModelId: "claude-opus-4-6-thinking",
|
||||
templateId: "claude-opus-4-5-thinking",
|
||||
templateName: "Claude Opus 4.5 Thinking",
|
||||
});
|
||||
expectAntigravityModel(payload, {
|
||||
key: "google-antigravity/claude-opus-4-6-thinking",
|
||||
available: false,
|
||||
includesTags: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("models list resolves antigravity opus 4.6 (non-thinking) from 4.5 template", async () => {
|
||||
const payload = await runGoogleAntigravityListCase({
|
||||
expectedKey: "google-antigravity/claude-opus-4-6-thinking",
|
||||
},
|
||||
{
|
||||
name: "non-thinking",
|
||||
configuredModelId: "claude-opus-4-6",
|
||||
templateId: "claude-opus-4-5",
|
||||
templateName: "Claude Opus 4.5",
|
||||
});
|
||||
expectAntigravityModel(payload, {
|
||||
key: "google-antigravity/claude-opus-4-6",
|
||||
available: false,
|
||||
includesTags: true,
|
||||
});
|
||||
});
|
||||
expectedKey: "google-antigravity/claude-opus-4-6",
|
||||
},
|
||||
] as const)(
|
||||
"models list resolves antigravity opus 4.6 $name from 4.5 template",
|
||||
async ({ configuredModelId, templateId, templateName, expectedKey }) => {
|
||||
const payload = await runGoogleAntigravityListCase({
|
||||
configuredModelId,
|
||||
templateId,
|
||||
templateName,
|
||||
});
|
||||
expectAntigravityModel(payload, {
|
||||
key: expectedKey,
|
||||
available: false,
|
||||
includesTags: true,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it("models list marks synthesized antigravity opus 4.6 thinking as available when template is available", async () => {
|
||||
const payload = await runGoogleAntigravityListCase({
|
||||
it.each([
|
||||
{
|
||||
name: "thinking",
|
||||
configuredModelId: "claude-opus-4-6-thinking",
|
||||
templateId: "claude-opus-4-5-thinking",
|
||||
templateName: "Claude Opus 4.5 Thinking",
|
||||
available: true,
|
||||
});
|
||||
expectAntigravityModel(payload, {
|
||||
key: "google-antigravity/claude-opus-4-6-thinking",
|
||||
available: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("models list marks synthesized antigravity opus 4.6 (non-thinking) as available when template is available", async () => {
|
||||
const payload = await runGoogleAntigravityListCase({
|
||||
expectedKey: "google-antigravity/claude-opus-4-6-thinking",
|
||||
},
|
||||
{
|
||||
name: "non-thinking",
|
||||
configuredModelId: "claude-opus-4-6",
|
||||
templateId: "claude-opus-4-5",
|
||||
templateName: "Claude Opus 4.5",
|
||||
available: true,
|
||||
});
|
||||
expectAntigravityModel(payload, {
|
||||
key: "google-antigravity/claude-opus-4-6",
|
||||
available: true,
|
||||
});
|
||||
});
|
||||
expectedKey: "google-antigravity/claude-opus-4-6",
|
||||
},
|
||||
] as const)(
|
||||
"models list marks synthesized antigravity opus 4.6 $name as available when template is available",
|
||||
async ({ configuredModelId, templateId, templateName, expectedKey }) => {
|
||||
const payload = await runGoogleAntigravityListCase({
|
||||
configuredModelId,
|
||||
templateId,
|
||||
templateName,
|
||||
available: true,
|
||||
});
|
||||
expectAntigravityModel(payload, {
|
||||
key: expectedKey,
|
||||
available: true,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it("models list prefers registry availability over provider auth heuristics", async () => {
|
||||
const payload = await runGoogleAntigravityListCase({
|
||||
@@ -472,13 +480,10 @@ describe("models list/status", () => {
|
||||
makeGoogleAntigravityTemplate("claude-opus-4-5-thinking", "Claude Opus 4.5 Thinking"),
|
||||
];
|
||||
|
||||
const { loadModelRegistry } = await import("./models/list.registry.js");
|
||||
await expect(loadModelRegistry({})).rejects.toThrow("model discovery unavailable");
|
||||
});
|
||||
|
||||
it("toModelRow does not crash without cfg/authStore when availability is undefined", async () => {
|
||||
const { toModelRow } = await import("./models/list.registry.js");
|
||||
|
||||
const row = toModelRow({
|
||||
model: makeGoogleAntigravityTemplate(
|
||||
"claude-opus-4-6-thinking",
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
|
||||
const createClackPrompterMock = vi.hoisted(() => vi.fn());
|
||||
const runOnboardingWizardMock = vi.hoisted(() => vi.fn());
|
||||
const restoreTerminalStateMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock("../wizard/clack-prompter.js", () => ({ createClackPrompter: createClackPrompterMock }));
|
||||
vi.mock("../wizard/onboarding.js", () => ({ runOnboardingWizard: runOnboardingWizardMock }));
|
||||
vi.mock("../terminal/restore.js", () => ({ restoreTerminalState: restoreTerminalStateMock }));
|
||||
|
||||
import { WizardCancelledError } from "../wizard/prompts.js";
|
||||
import { runInteractiveOnboarding } from "./onboard-interactive.js";
|
||||
|
||||
const runtime: RuntimeEnv = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
exit: vi.fn(),
|
||||
};
|
||||
|
||||
describe("runInteractiveOnboarding", () => {
|
||||
beforeEach(() => {
|
||||
createClackPrompterMock.mockReset();
|
||||
runOnboardingWizardMock.mockReset();
|
||||
restoreTerminalStateMock.mockReset();
|
||||
(runtime.log as ReturnType<typeof vi.fn>).mockClear();
|
||||
(runtime.error as ReturnType<typeof vi.fn>).mockClear();
|
||||
(runtime.exit as ReturnType<typeof vi.fn>).mockClear();
|
||||
|
||||
createClackPrompterMock.mockReturnValue({});
|
||||
runOnboardingWizardMock.mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
it("exits with code 1 when the wizard is cancelled", async () => {
|
||||
runOnboardingWizardMock.mockRejectedValue(new WizardCancelledError());
|
||||
|
||||
await runInteractiveOnboarding({} as never, runtime);
|
||||
|
||||
expect(runtime.exit).toHaveBeenCalledWith(1);
|
||||
expect(restoreTerminalStateMock).toHaveBeenCalledWith("onboarding finish", {
|
||||
resumeStdinIfPaused: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("rethrows non-cancel errors", async () => {
|
||||
const err = new Error("boom");
|
||||
runOnboardingWizardMock.mockRejectedValue(err);
|
||||
|
||||
await expect(runInteractiveOnboarding({} as never, runtime)).rejects.toThrow("boom");
|
||||
|
||||
expect(runtime.exit).not.toHaveBeenCalled();
|
||||
expect(restoreTerminalStateMock).toHaveBeenCalledWith("onboarding finish", {
|
||||
resumeStdinIfPaused: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -69,4 +69,17 @@ describe("runInteractiveOnboarding", () => {
|
||||
Number.MAX_SAFE_INTEGER;
|
||||
expect(restoreOrder).toBeLessThan(exitOrder);
|
||||
});
|
||||
|
||||
it("rethrows non-cancel errors after restoring terminal state", async () => {
|
||||
const runtime = makeRuntime();
|
||||
const err = new Error("boom");
|
||||
mocks.runOnboardingWizard.mockRejectedValueOnce(err);
|
||||
|
||||
await expect(runInteractiveOnboarding({} as never, runtime)).rejects.toThrow("boom");
|
||||
|
||||
expect(runtime.exit).not.toHaveBeenCalled();
|
||||
expect(mocks.restoreTerminalState).toHaveBeenCalledWith("onboarding finish", {
|
||||
resumeStdinIfPaused: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user