From eea818220925f4fee0b0d934c86711aa9d1b37ce Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Date: Tue, 30 Jun 2026 02:13:33 -0300 Subject: [PATCH] =?UTF-8?q?refactor(dashboard):=20T11=20=E2=80=94=20drop?= =?UTF-8?q?=20duplicate=20caveman=20on/off=20toggle=20from=20the=20compres?= =?UTF-8?q?sion=20settings=20tab=20(#5524)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Integrated into release/v3.8.42 (round 3). T11 consolidate duplicate caveman controls; i18n'd the panel hint string (source key). --- .../components/CompressionSettingsTab.tsx | 45 ++----- src/i18n/messages/en.json | 1 + ...ession-settings-tab-consolidation.test.tsx | 115 ++++++++++++++++++ 3 files changed, 129 insertions(+), 32 deletions(-) create mode 100644 tests/unit/compression-settings-tab-consolidation.test.tsx diff --git a/src/app/(dashboard)/dashboard/settings/components/CompressionSettingsTab.tsx b/src/app/(dashboard)/dashboard/settings/components/CompressionSettingsTab.tsx index 60e3ef473e..a68426f21d 100644 --- a/src/app/(dashboard)/dashboard/settings/components/CompressionSettingsTab.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/CompressionSettingsTab.tsx @@ -416,38 +416,20 @@ export default function CompressionSettingsTab() { config.defaultMode !== "lite" && config.cavemanConfig && (
-
-
-

- {t("compressionCavemanConfig")} -

-

- {t("compressionCavemanConfigDesc")} -

-
- + {/* Engine on/off is owned by the single-source panel (/dashboard/context/settings): + the panel's `engines.caveman.enabled` is authoritative (planResolution.ts). This tab + keeps only the advanced caveman tuning the panel does not expose. */} +
+

+ {t("compressionCavemanConfig")} +

+

+ {t("compressionCavemanConfigDesc")} {t("compressionCavemanPanelHint")}{" "} + /dashboard/context/settings +

- {config.cavemanConfig.enabled && ( - <> + <>

{t("compressionRoles")}

@@ -534,8 +516,7 @@ export default function CompressionSettingsTab() { className="w-full min-h-[80px] px-3 py-2 text-sm rounded-lg border border-border bg-surface text-text-main font-mono resize-y" />
- - )} +
)} diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 12a34a0ab4..8029041ba5 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -5637,6 +5637,7 @@ "compressionPreserveSystem": "Preserve System Prompt", "compressionCavemanConfig": "Caveman Engine Configuration", "compressionCavemanConfigDesc": "Fine-tune the rule-based compression engine", + "compressionCavemanPanelHint": "Its on/off and level are set in the panel:", "compressionRoles": "Compress Message Roles", "compressionRoleUser": "User", "compressionRoleAssistant": "Assistant", diff --git a/tests/unit/compression-settings-tab-consolidation.test.tsx b/tests/unit/compression-settings-tab-consolidation.test.tsx new file mode 100644 index 0000000000..3f3f730081 --- /dev/null +++ b/tests/unit/compression-settings-tab-consolidation.test.tsx @@ -0,0 +1,115 @@ +// @vitest-environment jsdom +import React from "react"; +import { act } from "react"; +import { createRoot } from "react-dom/client"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +// next-intl → echo the key so we can assert on stable identifiers. +vi.mock("next-intl", () => ({ + useTranslations: () => (key: string) => key, +})); + +vi.mock("next/link", () => ({ + default: ({ children, href }: { children: React.ReactNode; href: string }) => ( + {children} + ), +})); + +vi.mock("@/shared/components", () => ({ + Card: ({ children, className }: { children: React.ReactNode; className?: string }) => ( +
+ {children} +
+ ), + Button: ({ children, onClick }: { children?: React.ReactNode; onClick?: () => void }) => ( + + ), +})); + +const CONFIG = { + enabled: true, + defaultMode: "standard", + autoTriggerTokens: 0, + cacheMinutes: 5, + preserveSystemPrompt: true, + comboOverrides: {}, + cavemanConfig: { + enabled: true, + compressRoles: ["user"], + skipRules: [], + minMessageLength: 50, + preservePatterns: [], + intensity: "full", + }, + cavemanOutputMode: { enabled: false, intensity: "full", autoClarity: true }, + rtkConfig: { enabled: true, intensity: "standard" }, +}; + +let container: HTMLDivElement; +let root: ReturnType | undefined; + +beforeEach(() => { + container = document.createElement("div"); + document.body.appendChild(container); + vi.stubGlobal( + "fetch", + vi.fn((url: string) => { + const u = String(url); + if (u.includes("/api/settings/compression")) { + return Promise.resolve({ ok: true, json: () => Promise.resolve(CONFIG) }); + } + if (u.includes("/api/compression/rules")) { + return Promise.resolve({ ok: true, json: () => Promise.resolve({ rules: [] }) }); + } + return Promise.resolve({ ok: false, json: () => Promise.resolve(null) }); + }) + ); +}); + +afterEach(() => { + act(() => root?.unmount()); + root = undefined; + container.remove(); + vi.unstubAllGlobals(); + vi.restoreAllMocks(); +}); + +async function renderTab() { + const { default: CompressionSettingsTab } = await import( + "@/app/(dashboard)/dashboard/settings/components/CompressionSettingsTab" + ); + await act(async () => { + root = createRoot(container); + root.render(); + }); + // Drain the on-mount fetch → json → setState microtask chain. + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, 0)); + }); +} + +describe("CompressionSettingsTab — compression controls consolidation (T11)", () => { + it("renders the read-only TokenSaver summary that links to the unified panel", async () => { + await renderTab(); + const hrefs = Array.from(container.querySelectorAll("a")).map((a) => a.getAttribute("href")); + expect(hrefs).toContain("/dashboard/context/settings"); + expect(container.textContent).toContain("tokenSaverTitle"); + }); + + it("does not render a duplicate caveman engine on/off toggle (panel owns on/off)", async () => { + await renderTab(); + const note = container.querySelector('[data-testid="caveman-panel-note"]'); + expect(note).not.toBeNull(); + // The note points users to the single-source panel... + expect(note?.textContent).toContain("/dashboard/context/settings"); + // ...and the caveman header no longer carries its own enable toggle button. + expect(note?.querySelector("button")).toBeNull(); + }); + + it("keeps the advanced caveman tuning the panel does not expose", async () => { + await renderTab(); + expect(container.textContent).toContain("compressionRoleUser"); + expect(container.textContent).toContain("compressionSkipRules"); + expect(container.textContent).toContain("compressionPreservePatterns"); + }); +});