mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-03-23 23:59:24 +08:00
refactor(proxy): remove is_proxy_target in favor of failover_queue
- Remove `is_proxy_target` field from Provider struct (Rust & TypeScript) - Remove related DAO methods: get_proxy_target_provider, set_proxy_target - Remove deprecated Tauri commands: get_proxy_targets, set_proxy_target - Add `is_available()` method to CircuitBreaker for availability checks without consuming HalfOpen probe permits (used in select_providers) - Keep `allow_request()` for actual request gating with permit tracking - Update stream_check to use failover_queue instead of is_proxy_target - Clean up commented-out reset circuit breaker button in ProviderActions - Remove unused useProxyTargets and useSetProxyTarget hooks
This commit is contained in:
@@ -19,6 +19,23 @@ vi.mock("react-i18next", () => ({
|
||||
useTranslation: () => ({ t: tMock }),
|
||||
}));
|
||||
|
||||
vi.mock("@/hooks/useProxyStatus", () => ({
|
||||
useProxyStatus: () => ({
|
||||
status: null,
|
||||
isLoading: false,
|
||||
isRunning: false,
|
||||
isTakeoverActive: false,
|
||||
startWithTakeover: vi.fn(),
|
||||
stopWithRestore: vi.fn(),
|
||||
switchProxyProvider: vi.fn(),
|
||||
checkRunning: vi.fn(),
|
||||
checkTakeoverActive: vi.fn(),
|
||||
isStarting: false,
|
||||
isStopping: false,
|
||||
isPending: false,
|
||||
}),
|
||||
}));
|
||||
|
||||
interface SettingsMock {
|
||||
settings: any;
|
||||
isLoading: boolean;
|
||||
@@ -288,6 +305,7 @@ describe("SettingsPage Component", () => {
|
||||
});
|
||||
|
||||
fireEvent.click(screen.getByText("settings.tabAdvanced"));
|
||||
fireEvent.click(screen.getByText("数据管理"));
|
||||
|
||||
// 有文件时,点击导入按钮执行 importConfig
|
||||
fireEvent.click(
|
||||
@@ -363,6 +381,7 @@ describe("SettingsPage Component", () => {
|
||||
await waitFor(() => {
|
||||
expect(toastSuccessMock).toHaveBeenCalledWith(
|
||||
"settings.devModeRestartHint",
|
||||
expect.objectContaining({ closeButton: true }),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -393,6 +412,7 @@ describe("SettingsPage Component", () => {
|
||||
render(<SettingsPage open={true} onOpenChange={vi.fn()} />);
|
||||
|
||||
fireEvent.click(screen.getByText("settings.tabAdvanced"));
|
||||
fireEvent.click(screen.getByText("配置文件目录"));
|
||||
|
||||
fireEvent.click(screen.getByText("browse-directory"));
|
||||
expect(settingsMock.browseDirectory).toHaveBeenCalledWith("claude");
|
||||
|
||||
@@ -120,6 +120,7 @@ describe("useImportExport Hook (edge cases)", () => {
|
||||
expect(exportConfigMock).toHaveBeenCalledWith("/exports/config.json");
|
||||
expect(toastSuccessMock).toHaveBeenCalledWith(
|
||||
expect.stringContaining("/final/config.json"),
|
||||
expect.objectContaining({ closeButton: true }),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -180,6 +180,7 @@ describe("useImportExport Hook", () => {
|
||||
expect(exportConfigMock).toHaveBeenCalledWith("/export.json");
|
||||
expect(toastSuccessMock).toHaveBeenCalledWith(
|
||||
expect.stringContaining("/backup/export.json"),
|
||||
expect.objectContaining({ closeButton: true }),
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -150,6 +150,7 @@ describe("SettingsPage integration", () => {
|
||||
expect(screen.getByText("language:zh")).toBeInTheDocument(),
|
||||
);
|
||||
fireEvent.click(screen.getByText("settings.tabAdvanced"));
|
||||
fireEvent.click(screen.getByText("配置文件目录"));
|
||||
const appInput = await screen.findByPlaceholderText(
|
||||
"settings.browsePlaceholderApp",
|
||||
);
|
||||
@@ -165,6 +166,7 @@ describe("SettingsPage integration", () => {
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByText("settings.tabAdvanced"));
|
||||
fireEvent.click(screen.getByText("数据管理"));
|
||||
fireEvent.click(screen.getByText("settings.selectConfigFile"));
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId("selected-file").textContent).toContain(
|
||||
@@ -188,6 +190,7 @@ describe("SettingsPage integration", () => {
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByText("settings.tabAdvanced"));
|
||||
fireEvent.click(screen.getByText("配置文件目录"));
|
||||
const appInput = await screen.findByPlaceholderText(
|
||||
"settings.browsePlaceholderApp",
|
||||
);
|
||||
@@ -214,6 +217,7 @@ describe("SettingsPage integration", () => {
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByText("settings.tabAdvanced"));
|
||||
fireEvent.click(screen.getByText("配置文件目录"));
|
||||
|
||||
const browseButtons = screen.getAllByTitle("settings.browseDirectory");
|
||||
const resetButtons = screen.getAllByTitle("settings.resetDefault");
|
||||
@@ -253,6 +257,7 @@ describe("SettingsPage integration", () => {
|
||||
expect(screen.getByText("language:zh")).toBeInTheDocument(),
|
||||
);
|
||||
fireEvent.click(screen.getByText("settings.tabAdvanced"));
|
||||
fireEvent.click(screen.getByText("数据管理"));
|
||||
|
||||
server.use(
|
||||
http.post("http://tauri.local/save_file_dialog", () =>
|
||||
|
||||
@@ -236,4 +236,64 @@ export const handlers = [
|
||||
http.post(`${TAURI_ENDPOINT}/sync_current_providers_live`, () =>
|
||||
success({ success: true }),
|
||||
),
|
||||
|
||||
// Proxy status (for SettingsPage / ProxyPanel hooks)
|
||||
http.post(`${TAURI_ENDPOINT}/get_proxy_status`, () =>
|
||||
success({
|
||||
running: false,
|
||||
address: "127.0.0.1",
|
||||
port: 0,
|
||||
active_connections: 0,
|
||||
total_requests: 0,
|
||||
success_requests: 0,
|
||||
failed_requests: 0,
|
||||
success_rate: 0,
|
||||
uptime_seconds: 0,
|
||||
current_provider: null,
|
||||
current_provider_id: null,
|
||||
last_request_at: null,
|
||||
last_error: null,
|
||||
failover_count: 0,
|
||||
active_targets: [],
|
||||
}),
|
||||
),
|
||||
|
||||
http.post(`${TAURI_ENDPOINT}/is_live_takeover_active`, () => success(false)),
|
||||
|
||||
// Failover / circuit breaker defaults
|
||||
http.post(`${TAURI_ENDPOINT}/get_failover_queue`, () => success([])),
|
||||
http.post(`${TAURI_ENDPOINT}/get_available_providers_for_failover`, () =>
|
||||
success([]),
|
||||
),
|
||||
http.post(`${TAURI_ENDPOINT}/add_to_failover_queue`, () => success(true)),
|
||||
http.post(`${TAURI_ENDPOINT}/remove_from_failover_queue`, () => success(true)),
|
||||
http.post(`${TAURI_ENDPOINT}/reorder_failover_queue`, () => success(true)),
|
||||
http.post(`${TAURI_ENDPOINT}/set_failover_item_enabled`, () => success(true)),
|
||||
|
||||
http.post(`${TAURI_ENDPOINT}/get_circuit_breaker_config`, () =>
|
||||
success({
|
||||
failureThreshold: 3,
|
||||
successThreshold: 2,
|
||||
timeoutSeconds: 60,
|
||||
errorRateThreshold: 50,
|
||||
minRequests: 5,
|
||||
}),
|
||||
),
|
||||
http.post(`${TAURI_ENDPOINT}/update_circuit_breaker_config`, () =>
|
||||
success(true),
|
||||
),
|
||||
http.post(`${TAURI_ENDPOINT}/get_provider_health`, () =>
|
||||
success({
|
||||
provider_id: "mock-provider",
|
||||
app_type: "claude",
|
||||
is_healthy: true,
|
||||
consecutive_failures: 0,
|
||||
last_success_at: null,
|
||||
last_failure_at: null,
|
||||
last_error: null,
|
||||
updated_at: new Date().toISOString(),
|
||||
}),
|
||||
),
|
||||
http.post(`${TAURI_ENDPOINT}/reset_circuit_breaker`, () => success(true)),
|
||||
http.post(`${TAURI_ENDPOINT}/get_circuit_breaker_stats`, () => success(null)),
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user