From 75b4ef229967408599909dd42ce62a1dbded3a71 Mon Sep 17 00:00:00 2001 From: Zhou Mengze Date: Tue, 10 Mar 2026 21:02:13 +0800 Subject: [PATCH] fix: interpolate proxy startup toast address and port (#1399) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 周梦泽 --- src/hooks/useProxyStatus.ts | 2 + tests/hooks/useProxyStatus.test.tsx | 118 ++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 tests/hooks/useProxyStatus.test.tsx diff --git a/src/hooks/useProxyStatus.ts b/src/hooks/useProxyStatus.ts index e2cf3c367..aa6d4a08e 100644 --- a/src/hooks/useProxyStatus.ts +++ b/src/hooks/useProxyStatus.ts @@ -43,6 +43,8 @@ export function useProxyStatus() { onSuccess: (info) => { toast.success( t("proxy.server.started", { + address: info.address, + port: info.port, defaultValue: `代理服务已启动 - ${info.address}:${info.port}`, }), { closeButton: true }, diff --git a/tests/hooks/useProxyStatus.test.tsx b/tests/hooks/useProxyStatus.test.tsx new file mode 100644 index 000000000..ce18e4a05 --- /dev/null +++ b/tests/hooks/useProxyStatus.test.tsx @@ -0,0 +1,118 @@ +import type { ReactNode } from "react"; +import { renderHook, act, waitFor } from "@testing-library/react"; +import { QueryClientProvider } from "@tanstack/react-query"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { useProxyStatus } from "@/hooks/useProxyStatus"; +import { createTestQueryClient } from "../utils/testQueryClient"; + +const toastSuccessMock = vi.fn(); +const toastErrorMock = vi.fn(); +const invokeMock = vi.fn(); + +vi.mock("sonner", () => ({ + toast: { + success: (...args: unknown[]) => toastSuccessMock(...args), + error: (...args: unknown[]) => toastErrorMock(...args), + }, +})); + +vi.mock("@tauri-apps/api/core", () => ({ + invoke: (...args: unknown[]) => invokeMock(...args), +})); + +vi.mock("react-i18next", () => ({ + useTranslation: () => ({ + t: (key: string, options?: Record) => { + if (key === "proxy.server.started") { + return `代理服务已启动 - ${options?.address}:${options?.port}`; + } + + if (typeof options?.defaultValue === "string") { + return options.defaultValue; + } + + return key; + }, + }), +})); + +interface WrapperProps { + children: ReactNode; +} + +function createWrapper() { + const queryClient = createTestQueryClient(); + + const wrapper = ({ children }: WrapperProps) => ( + {children} + ); + + return { wrapper, queryClient }; +} + +describe("useProxyStatus", () => { + beforeEach(() => { + invokeMock.mockReset(); + toastSuccessMock.mockReset(); + toastErrorMock.mockReset(); + + invokeMock.mockImplementation((command: string) => { + if (command === "get_proxy_status") { + return Promise.resolve({ + running: false, + address: "127.0.0.1", + port: 15721, + 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, + }); + } + + if (command === "get_proxy_takeover_status") { + return Promise.resolve({ + claude: false, + codex: false, + gemini: false, + opencode: false, + openclaw: false, + }); + } + + if (command === "start_proxy_server") { + return Promise.resolve({ + address: "127.0.0.1", + port: 15721, + started_at: "2026-03-10T00:00:00Z", + }); + } + + return Promise.resolve(null); + }); + }); + + it("shows interpolated address and port after proxy server starts", async () => { + const { wrapper } = createWrapper(); + const { result } = renderHook(() => useProxyStatus(), { wrapper }); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + await act(async () => { + await result.current.startProxyServer(); + }); + + expect(toastSuccessMock).toHaveBeenCalledWith( + "代理服务已启动 - 127.0.0.1:15721", + { closeButton: true }, + ); + }); +}); \ No newline at end of file