Files
automaker/apps/server/tests/unit/providers/provider-factory.test.ts
2025-12-13 20:17:24 +01:00

235 lines
8.1 KiB
TypeScript

import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { ProviderFactory } from "@/providers/provider-factory.js";
import { ClaudeProvider } from "@/providers/claude-provider.js";
describe("provider-factory.ts", () => {
let consoleSpy: any;
beforeEach(() => {
consoleSpy = {
warn: vi.spyOn(console, "warn").mockImplementation(() => {}),
};
});
afterEach(() => {
consoleSpy.warn.mockRestore();
});
describe("getProviderForModel", () => {
describe("Claude models (claude-* prefix)", () => {
it("should return ClaudeProvider for claude-opus-4-5-20251101", () => {
const provider = ProviderFactory.getProviderForModel(
"claude-opus-4-5-20251101"
);
expect(provider).toBeInstanceOf(ClaudeProvider);
});
it("should return ClaudeProvider for claude-sonnet-4-20250514", () => {
const provider = ProviderFactory.getProviderForModel(
"claude-sonnet-4-20250514"
);
expect(provider).toBeInstanceOf(ClaudeProvider);
});
it("should return ClaudeProvider for claude-haiku-4-5", () => {
const provider = ProviderFactory.getProviderForModel("claude-haiku-4-5");
expect(provider).toBeInstanceOf(ClaudeProvider);
});
it("should be case-insensitive for claude models", () => {
const provider = ProviderFactory.getProviderForModel(
"CLAUDE-OPUS-4-5-20251101"
);
expect(provider).toBeInstanceOf(ClaudeProvider);
});
});
describe("Claude aliases", () => {
it("should return ClaudeProvider for 'haiku'", () => {
const provider = ProviderFactory.getProviderForModel("haiku");
expect(provider).toBeInstanceOf(ClaudeProvider);
});
it("should return ClaudeProvider for 'sonnet'", () => {
const provider = ProviderFactory.getProviderForModel("sonnet");
expect(provider).toBeInstanceOf(ClaudeProvider);
});
it("should return ClaudeProvider for 'opus'", () => {
const provider = ProviderFactory.getProviderForModel("opus");
expect(provider).toBeInstanceOf(ClaudeProvider);
});
it("should be case-insensitive for aliases", () => {
const provider1 = ProviderFactory.getProviderForModel("HAIKU");
const provider2 = ProviderFactory.getProviderForModel("Sonnet");
const provider3 = ProviderFactory.getProviderForModel("Opus");
expect(provider1).toBeInstanceOf(ClaudeProvider);
expect(provider2).toBeInstanceOf(ClaudeProvider);
expect(provider3).toBeInstanceOf(ClaudeProvider);
});
});
describe("Unknown models", () => {
it("should default to ClaudeProvider for unknown model", () => {
const provider = ProviderFactory.getProviderForModel("unknown-model-123");
expect(provider).toBeInstanceOf(ClaudeProvider);
});
it("should warn when defaulting to Claude", () => {
ProviderFactory.getProviderForModel("random-model");
expect(consoleSpy.warn).toHaveBeenCalledWith(
expect.stringContaining("Unknown model prefix")
);
expect(consoleSpy.warn).toHaveBeenCalledWith(
expect.stringContaining("random-model")
);
expect(consoleSpy.warn).toHaveBeenCalledWith(
expect.stringContaining("defaulting to Claude")
);
});
it("should handle empty string", () => {
const provider = ProviderFactory.getProviderForModel("");
expect(provider).toBeInstanceOf(ClaudeProvider);
expect(consoleSpy.warn).toHaveBeenCalled();
});
it("should default to ClaudeProvider for gpt models (not supported)", () => {
const provider = ProviderFactory.getProviderForModel("gpt-5.2");
expect(provider).toBeInstanceOf(ClaudeProvider);
expect(consoleSpy.warn).toHaveBeenCalled();
});
it("should default to ClaudeProvider for o-series models (not supported)", () => {
const provider = ProviderFactory.getProviderForModel("o1");
expect(provider).toBeInstanceOf(ClaudeProvider);
expect(consoleSpy.warn).toHaveBeenCalled();
});
});
});
describe("getAllProviders", () => {
it("should return array of all providers", () => {
const providers = ProviderFactory.getAllProviders();
expect(Array.isArray(providers)).toBe(true);
});
it("should include ClaudeProvider", () => {
const providers = ProviderFactory.getAllProviders();
const hasClaudeProvider = providers.some(
(p) => p instanceof ClaudeProvider
);
expect(hasClaudeProvider).toBe(true);
});
it("should return exactly 1 provider", () => {
const providers = ProviderFactory.getAllProviders();
expect(providers).toHaveLength(1);
});
it("should create new instances each time", () => {
const providers1 = ProviderFactory.getAllProviders();
const providers2 = ProviderFactory.getAllProviders();
expect(providers1[0]).not.toBe(providers2[0]);
});
});
describe("checkAllProviders", () => {
it("should return installation status for all providers", async () => {
const statuses = await ProviderFactory.checkAllProviders();
expect(statuses).toHaveProperty("claude");
});
it("should call detectInstallation on each provider", async () => {
const statuses = await ProviderFactory.checkAllProviders();
expect(statuses.claude).toHaveProperty("installed");
});
it("should return correct provider names as keys", async () => {
const statuses = await ProviderFactory.checkAllProviders();
const keys = Object.keys(statuses);
expect(keys).toContain("claude");
expect(keys).toHaveLength(1);
});
});
describe("getProviderByName", () => {
it("should return ClaudeProvider for 'claude'", () => {
const provider = ProviderFactory.getProviderByName("claude");
expect(provider).toBeInstanceOf(ClaudeProvider);
});
it("should return ClaudeProvider for 'anthropic'", () => {
const provider = ProviderFactory.getProviderByName("anthropic");
expect(provider).toBeInstanceOf(ClaudeProvider);
});
it("should be case-insensitive", () => {
const provider1 = ProviderFactory.getProviderByName("CLAUDE");
const provider2 = ProviderFactory.getProviderByName("ANTHROPIC");
expect(provider1).toBeInstanceOf(ClaudeProvider);
expect(provider2).toBeInstanceOf(ClaudeProvider);
});
it("should return null for unknown provider", () => {
const provider = ProviderFactory.getProviderByName("unknown");
expect(provider).toBeNull();
});
it("should return null for empty string", () => {
const provider = ProviderFactory.getProviderByName("");
expect(provider).toBeNull();
});
it("should create new instance each time", () => {
const provider1 = ProviderFactory.getProviderByName("claude");
const provider2 = ProviderFactory.getProviderByName("claude");
expect(provider1).not.toBe(provider2);
expect(provider1).toBeInstanceOf(ClaudeProvider);
expect(provider2).toBeInstanceOf(ClaudeProvider);
});
});
describe("getAllAvailableModels", () => {
it("should return array of models", () => {
const models = ProviderFactory.getAllAvailableModels();
expect(Array.isArray(models)).toBe(true);
});
it("should include models from all providers", () => {
const models = ProviderFactory.getAllAvailableModels();
expect(models.length).toBeGreaterThan(0);
});
it("should return models with required fields", () => {
const models = ProviderFactory.getAllAvailableModels();
models.forEach((model) => {
expect(model).toHaveProperty("id");
expect(model).toHaveProperty("name");
expect(typeof model.id).toBe("string");
expect(typeof model.name).toBe("string");
});
});
it("should include Claude models", () => {
const models = ProviderFactory.getAllAvailableModels();
// Claude models should include claude-* in their IDs
const hasClaudeModels = models.some((m) =>
m.id.toLowerCase().includes("claude")
);
expect(hasClaudeModels).toBe(true);
});
});
});