mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-10-26 01:34:51 +08:00
* feat: Enhance OpenCode provider configuration and import functionality - Added support for built-in provider defaults in OpenCode configuration. - Updated OpenCode provider options to allow omitting npm and model definitions. - Improved import logic for OpenCode providers from live config, ensuring existing credentials are respected. - Introduced tests for credential handling and built-in provider editing. - Enhanced UI components to reflect changes in provider configuration and selection. - Added localization for new built-in defaults feature. * refactor(tests): enhance test environment isolation and settings management * Refactor OpenCode provider handling and validation - Removed TestSettingsGuard to simplify settings management during tests. - Enhanced validation in handleDuplicateProvider to ensure npm and model definitions are provided for non-OMO providers. - Updated OpenCodeFormFields to conditionally allow built-in defaults based on props. - Improved ProviderForm to manage existing OpenCode overrides and prevent incomplete copies from being added. - Added comprehensive tests for OpenCode provider duplication and validation scenarios. - Introduced new error messages for better user feedback on provider requirements. - Created opencode_tests.rs to cover various scenarios for OpenCode provider imports and updates. --------- Co-authored-by: Jason <farion1231@gmail.com>
148 lines
3.9 KiB
TypeScript
148 lines
3.9 KiB
TypeScript
import { act, renderHook } from "@testing-library/react";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
import { useOpencodeFormState } from "@/components/providers/forms/hooks/useOpencodeFormState";
|
|
|
|
const renderOpencodeFormState = (
|
|
initialSettingsConfig: Record<string, unknown>,
|
|
) => {
|
|
let settingsConfig = JSON.stringify(initialSettingsConfig);
|
|
const onSettingsConfigChange = vi.fn((nextConfig: string) => {
|
|
settingsConfig = nextConfig;
|
|
});
|
|
|
|
const hook = renderHook(() =>
|
|
useOpencodeFormState({
|
|
appId: "opencode",
|
|
initialData: { settingsConfig: initialSettingsConfig },
|
|
onSettingsConfigChange,
|
|
getSettingsConfig: () => settingsConfig,
|
|
}),
|
|
);
|
|
|
|
return {
|
|
...hook,
|
|
onSettingsConfigChange,
|
|
getSettingsConfig: () => settingsConfig,
|
|
};
|
|
};
|
|
|
|
describe("useOpencodeFormState", () => {
|
|
it("edits an existing built-in override without inventing a package or models", () => {
|
|
const { result, getSettingsConfig } = renderOpencodeFormState({
|
|
name: "OpenCode Go",
|
|
options: { apiKey: "test-key" },
|
|
});
|
|
|
|
expect(result.current.opencodeNpm).toBe("");
|
|
expect(result.current.opencodeModels).toEqual({});
|
|
act(() => result.current.handleOpencodeApiKeyChange("edited-test-key"));
|
|
expect(JSON.parse(getSettingsConfig())).toEqual({
|
|
name: "OpenCode Go",
|
|
options: { apiKey: "edited-test-key" },
|
|
});
|
|
});
|
|
|
|
it("hydrates provider headers from options", () => {
|
|
const { result } = renderOpencodeFormState({
|
|
npm: "@ai-sdk/openai-compatible",
|
|
options: {
|
|
headers: {
|
|
"HTTP-Referer": "https://cc-switch.app",
|
|
"X-Title": "CC Switch",
|
|
},
|
|
},
|
|
models: {},
|
|
});
|
|
|
|
expect(result.current.opencodeHeaders).toEqual({
|
|
"HTTP-Referer": "https://cc-switch.app",
|
|
"X-Title": "CC Switch",
|
|
});
|
|
});
|
|
|
|
it("writes provider headers to options", () => {
|
|
const { result, getSettingsConfig } = renderOpencodeFormState({
|
|
npm: "@ai-sdk/openai-compatible",
|
|
options: {},
|
|
models: {},
|
|
});
|
|
|
|
act(() => {
|
|
result.current.handleOpencodeHeadersChange({
|
|
"X-Title": "CC Switch",
|
|
});
|
|
});
|
|
|
|
expect(JSON.parse(getSettingsConfig()).options.headers).toEqual({
|
|
"X-Title": "CC Switch",
|
|
});
|
|
});
|
|
|
|
it("removes options.headers when all provider headers are removed", () => {
|
|
const { result, getSettingsConfig } = renderOpencodeFormState({
|
|
npm: "@ai-sdk/openai-compatible",
|
|
options: {
|
|
headers: {
|
|
"X-Title": "CC Switch",
|
|
},
|
|
},
|
|
models: {},
|
|
});
|
|
|
|
act(() => {
|
|
result.current.handleOpencodeHeadersChange({});
|
|
});
|
|
|
|
expect(JSON.parse(getSettingsConfig()).options.headers).toBeUndefined();
|
|
});
|
|
|
|
it("preserves legitimate headers whose names start with header-", () => {
|
|
const { result, getSettingsConfig } = renderOpencodeFormState({
|
|
npm: "@ai-sdk/openai-compatible",
|
|
options: {
|
|
headers: {
|
|
"header-version": "v1",
|
|
"X-Title": "Old",
|
|
},
|
|
},
|
|
models: {},
|
|
});
|
|
|
|
act(() => {
|
|
result.current.handleOpencodeHeadersChange({
|
|
"header-version": "v1",
|
|
"X-Title": "New",
|
|
});
|
|
});
|
|
|
|
expect(JSON.parse(getSettingsConfig()).options.headers).toEqual({
|
|
"header-version": "v1",
|
|
"X-Title": "New",
|
|
});
|
|
});
|
|
|
|
it("preserves legitimate options whose names start with option-", () => {
|
|
const { result, getSettingsConfig } = renderOpencodeFormState({
|
|
npm: "@ai-sdk/openai-compatible",
|
|
options: {
|
|
"option-mode": "legacy",
|
|
timeout: 100,
|
|
},
|
|
models: {},
|
|
});
|
|
|
|
act(() => {
|
|
result.current.handleOpencodeExtraOptionsChange({
|
|
"option-mode": "legacy",
|
|
timeout: "200",
|
|
"draft-option:123": "",
|
|
});
|
|
});
|
|
|
|
expect(JSON.parse(getSettingsConfig()).options).toEqual({
|
|
"option-mode": "legacy",
|
|
timeout: 200,
|
|
});
|
|
});
|
|
});
|