From 3878a16c4fbe2f17ade545a8aaf7825dc0d49a29 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 28 Nov 2025 15:53:25 +0800 Subject: [PATCH] fix: pre-release fixes for code formatting, i18n, and test suite - Run cargo fmt to fix Rust code formatting (lib.rs) - Add missing i18n keys: migration.success, agents.title (zh/en/ja) - Replace hardcoded strings "Agents" and "MCP" with t() calls in App.tsx - Fix test mocks and assertions: - Add providersApi.updateTrayMenu to useSettings.test.tsx mock - Update SettingsPage mock path in App.test.tsx - Fix toast message assertion in integration/SettingsDialog.test.tsx - Add autoSaveSettings to SettingsDialog component test mock - Fix loading state test to check spinner instead of title - Update import button name matching for selected file state - Fix save button test to switch to advanced tab first - Remove obsolete cancel button test (button no longer exists) Test results improved from 99 passed / 17 failed to 104 passed / 11 failed --- src-tauri/src/lib.rs | 6 ++-- src/App.tsx | 4 +-- src/i18n/locales/en.json | 6 ++++ src/i18n/locales/ja.json | 6 ++++ src/i18n/locales/zh.json | 6 ++++ tests/components/SettingsDialog.test.tsx | 39 +++++++++-------------- tests/hooks/useSettings.test.tsx | 4 +++ tests/integration/App.test.tsx | 4 +-- tests/integration/SettingsDialog.test.tsx | 2 +- 9 files changed, 46 insertions(+), 31 deletions(-) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index fbfc96f9..5d02a807 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -71,7 +71,8 @@ impl TrayTexts { }, "ja" => Self { show_main: "メインウィンドウを開く", - no_provider_hint: " (プロバイダーがまだありません。メイン画面から追加してください)", + no_provider_hint: + " (プロバイダーがまだありません。メイン画面から追加してください)", quit: "終了", }, _ => Self { @@ -521,7 +522,8 @@ pub fn run() { unsafe { use objc2::msg_send; - let _: () = msg_send![&*ns_window, setBackgroundColor: &*bg_color]; + let _: () = + msg_send![&*ns_window, setBackgroundColor: &*bg_color]; } } else { log::warn!("Failed to retain NSWindow reference"); diff --git a/src/App.tsx b/src/App.tsx index 97a01e40..6102c53a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -391,7 +391,7 @@ function App() { t("prompts.title", { appName: t(`apps.${activeApp}`) })} {currentView === "skills" && t("skills.title")} {currentView === "mcp" && t("mcp.unifiedPanel.title")} - {currentView === "agents" && "Agents"} + {currentView === "agents" && t("agents.title")} ) : ( @@ -512,7 +512,7 @@ function App() { size="sm" onClick={() => setCurrentView("mcp")} className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5" - title="MCP" + title={t("mcp.title")} > diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 92d6b678..dc8ed69e 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -833,5 +833,11 @@ "colorLabel": "Icon Color", "selectIcon": "Select Icon", "preview": "Preview" + }, + "migration": { + "success": "Configuration migrated successfully" + }, + "agents": { + "title": "Agents" } } diff --git a/src/i18n/locales/ja.json b/src/i18n/locales/ja.json index ed099ff5..5a5394ad 100644 --- a/src/i18n/locales/ja.json +++ b/src/i18n/locales/ja.json @@ -833,5 +833,11 @@ "colorLabel": "アイコンカラー", "selectIcon": "アイコンを選択", "preview": "プレビュー" + }, + "migration": { + "success": "設定の移行が完了しました" + }, + "agents": { + "title": "エージェント" } } diff --git a/src/i18n/locales/zh.json b/src/i18n/locales/zh.json index e379bfcc..e6b10ac7 100644 --- a/src/i18n/locales/zh.json +++ b/src/i18n/locales/zh.json @@ -833,5 +833,11 @@ "colorLabel": "图标颜色", "selectIcon": "选择图标", "preview": "预览" + }, + "migration": { + "success": "配置迁移成功" + }, + "agents": { + "title": "智能体" } } diff --git a/tests/components/SettingsDialog.test.tsx b/tests/components/SettingsDialog.test.tsx index 9a65cfcb..d27827e7 100644 --- a/tests/components/SettingsDialog.test.tsx +++ b/tests/components/SettingsDialog.test.tsx @@ -35,6 +35,7 @@ interface SettingsMock { resetDirectory: ReturnType; resetAppConfigDir: ReturnType; saveSettings: ReturnType; + autoSaveSettings: ReturnType; resetSettings: ReturnType; acknowledgeRestart: ReturnType; } @@ -66,6 +67,7 @@ const createSettingsMock = (overrides: Partial = {}) => { resetDirectory: vi.fn(), resetAppConfigDir: vi.fn(), saveSettings: vi.fn().mockResolvedValue({ requiresRestart: false }), + autoSaveSettings: vi.fn().mockResolvedValue({ requiresRestart: false }), resetSettings: vi.fn(), acknowledgeRestart: vi.fn(), }; @@ -247,7 +249,8 @@ describe("SettingsPage Component", () => { render(); expect(screen.queryByText("language:zh")).not.toBeInTheDocument(); - expect(screen.getByText("settings.title")).toBeInTheDocument(); + // 加载状态下显示 spinner 而不是表单内容 + expect(document.querySelector(".animate-spin")).toBeInTheDocument(); }); it("should reset import/export status when dialog transitions to open", () => { @@ -264,6 +267,7 @@ describe("SettingsPage Component", () => { it("should render general and advanced tabs and trigger child callbacks", () => { const onOpenChange = vi.fn(); + // 设置 selectedFile 后,按钮显示 settings.import(可执行导入) importExportMock = createImportExportMock({ selectedFile: "/tmp/config.json", }); @@ -284,21 +288,20 @@ describe("SettingsPage Component", () => { }); fireEvent.click(screen.getByText("settings.tabAdvanced")); - fireEvent.click( - screen.getByRole("button", { name: "settings.selectConfigFile" }), - ); - expect(importExportMock.selectImportFile).toHaveBeenCalled(); + // 有文件时,点击导入按钮执行 importConfig + fireEvent.click( + screen.getByRole("button", { name: /settings\.import/ }), + ); + expect(importExportMock.importConfig).toHaveBeenCalled(); fireEvent.click( screen.getByRole("button", { name: "settings.exportConfig" }), ); expect(importExportMock.exportConfig).toHaveBeenCalled(); - fireEvent.click(screen.getByRole("button", { name: "settings.import" })); - expect(importExportMock.importConfig).toHaveBeenCalled(); - - fireEvent.click(screen.getByRole("button", { name: "common.clear" })); + // 清除选择按钮 + fireEvent.click(screen.getByRole("button", { name: "Clear selection" })); expect(importExportMock.clearSelection).toHaveBeenCalled(); }); @@ -330,7 +333,9 @@ describe("SettingsPage Component", () => { render(); - fireEvent.click(screen.getByText("common.save")); + // 保存按钮在 advanced tab 中 + fireEvent.click(screen.getByText("settings.tabAdvanced")); + fireEvent.click(screen.getByRole("button", { name: /common\.save/ })); await waitFor(() => { expect(settingsMock.saveSettings).toHaveBeenCalledTimes(1); @@ -341,20 +346,6 @@ describe("SettingsPage Component", () => { }); }); - it("should reset settings and close dialog when clicking cancel", () => { - const onOpenChange = vi.fn(); - - render(); - - fireEvent.click(screen.getByText("common.cancel")); - - expect(settingsMock.resetSettings).toHaveBeenCalledTimes(1); - expect(settingsMock.acknowledgeRestart).toHaveBeenCalledTimes(1); - expect(importExportMock.clearSelection).toHaveBeenCalledTimes(1); - expect(importExportMock.resetStatus).toHaveBeenCalledTimes(2); - expect(onOpenChange).toHaveBeenCalledWith(false); - }); - it("should show restart prompt and allow immediate restart after save", async () => { settingsMock = createSettingsMock({ requiresRestart: true, diff --git a/tests/hooks/useSettings.test.tsx b/tests/hooks/useSettings.test.tsx index b6251979..a3035011 100644 --- a/tests/hooks/useSettings.test.tsx +++ b/tests/hooks/useSettings.test.tsx @@ -8,6 +8,7 @@ const useSettingsQueryMock = vi.fn(); const setAppConfigDirOverrideMock = vi.fn(); const applyClaudePluginConfigMock = vi.fn(); const syncCurrentProvidersLiveMock = vi.fn(); +const updateTrayMenuMock = vi.fn(); const toastErrorMock = vi.fn(); const toastSuccessMock = vi.fn(); @@ -52,6 +53,9 @@ vi.mock("@/lib/api", () => ({ syncCurrentProvidersLive: (...args: unknown[]) => syncCurrentProvidersLiveMock(...args), }, + providersApi: { + updateTrayMenu: (...args: unknown[]) => updateTrayMenuMock(...args), + }, })); const createSettingsFormMock = (overrides: Record = {}) => ({ diff --git a/tests/integration/App.test.tsx b/tests/integration/App.test.tsx index 7a456ca5..177eb403 100644 --- a/tests/integration/App.test.tsx +++ b/tests/integration/App.test.tsx @@ -109,8 +109,8 @@ vi.mock("@/components/ConfirmDialog", () => ({ ) : null, })); -vi.mock("@/components/settings/SettingsDialog", () => ({ - SettingsDialog: ({ open, onOpenChange, onImportSuccess }: any) => +vi.mock("@/components/settings/SettingsPage", () => ({ + SettingsPage: ({ open, onOpenChange, onImportSuccess }: any) => open ? (