From 0710b03f10f4961178fd6fc37d6a30845d068364 Mon Sep 17 00:00:00 2001 From: Thomas Kosiewski Date: Mon, 26 Oct 2026 14:34:15 +0000 Subject: [PATCH 1/2] tests: drop browser exports only tests used --- .../Settings/Sections/GoalsSection.test.tsx | 12 ++--- .../Settings/Sections/GoalsSection.tsx | 21 -------- .../hooks/useModelsFromSettings.test.ts | 2 +- src/browser/hooks/useModelsFromSettings.ts | 5 +- src/browser/stories/helpers/contrast.ts | 19 -------- .../highlighting/highlightDiffChunk.test.ts | 11 ++++- .../utils/highlighting/highlightDiffChunk.ts | 13 ----- .../utils/highlighting/highlightsEngine.ts | 2 +- .../messages/StreamingTPSCalculator.test.ts | 2 +- .../utils/messages/StreamingTPSCalculator.ts | 12 ++--- src/browser/utils/workflowRunMessages.test.ts | 6 ++- src/browser/utils/workflowRunMessages.ts | 3 +- src/browser/utils/workspaceStorage.test.ts | 48 ------------------- src/browser/utils/workspaceStorage.ts | 11 ----- src/common/constants/storage.ts | 2 +- 15 files changed, 29 insertions(+), 140 deletions(-) diff --git a/src/browser/features/Settings/Sections/GoalsSection.test.tsx b/src/browser/features/Settings/Sections/GoalsSection.test.tsx index 29bf49a8ffd..bf984246f97 100644 --- a/src/browser/features/Settings/Sections/GoalsSection.test.tsx +++ b/src/browser/features/Settings/Sections/GoalsSection.test.tsx @@ -14,9 +14,9 @@ import { type GoalDefaultsUpdate = Parameters[0]; -import { GoalsSection } from "./GoalsSection"; +import { GoalDefaultsControls } from "./GoalsSection"; -function renderGoalsSection(config: { goalDefaults?: GoalDefaults } = {}) { +function renderGoalDefaultsControls(config: { goalDefaults?: GoalDefaults } = {}) { const current: Partial = { ...config }; const updateGoalDefaults = mock(({ goalDefaults }: GoalDefaultsUpdate) => { // The real input is partial; the backend stores it normalized, as getConfig returns it. @@ -36,7 +36,7 @@ function renderGoalsSection(config: { goalDefaults?: GoalDefaults } = {}) { const view = render( - + ); @@ -44,7 +44,7 @@ function renderGoalsSection(config: { goalDefaults?: GoalDefaults } = {}) { return { view, updateGoalDefaults }; } -describe("GoalsSection", () => { +describe("GoalDefaultsControls", () => { let cleanupDom: (() => void) | null = null; beforeEach(() => { @@ -59,7 +59,7 @@ describe("GoalsSection", () => { }); test("renders default goal settings", async () => { - const { view } = renderGoalsSection(); + const { view } = renderGoalDefaultsControls(); const budgetInput = (await waitFor(() => view.getByLabelText("Default goal budget in dollars") @@ -73,7 +73,7 @@ describe("GoalsSection", () => { }); test("persists edited goal defaults", async () => { - const { view, updateGoalDefaults } = renderGoalsSection({ + const { view, updateGoalDefaults } = renderGoalDefaultsControls({ goalDefaults: { ...DEFAULT_GOAL_DEFAULTS, defaultBudgetCents: 300 }, }); diff --git a/src/browser/features/Settings/Sections/GoalsSection.tsx b/src/browser/features/Settings/Sections/GoalsSection.tsx index ac1fce0c185..72496ec2c8f 100644 --- a/src/browser/features/Settings/Sections/GoalsSection.tsx +++ b/src/browser/features/Settings/Sections/GoalsSection.tsx @@ -1,4 +1,3 @@ -import { Target } from "lucide-react"; import { useEffect, useState } from "react"; import { Input } from "@/browser/components/Input/Input"; import { useAPI } from "@/browser/contexts/API"; @@ -169,23 +168,3 @@ export function GoalDefaultsControls(props: GoalDefaultsControlsProps) { ); } - -export function GoalsSection() { - return ( -
-
-

Goals

-

- Workspace goals let you pin an objective to a workspace and track progress across turns. -

-
-
-
-
- -
-
- ); -} diff --git a/src/browser/hooks/useModelsFromSettings.test.ts b/src/browser/hooks/useModelsFromSettings.test.ts index 607e8e4b7c0..8cc9cd87526 100644 --- a/src/browser/hooks/useModelsFromSettings.test.ts +++ b/src/browser/hooks/useModelsFromSettings.test.ts @@ -8,10 +8,10 @@ import * as RoutingModule from "@/browser/hooks/useRouting"; import { filterHiddenModels, getDefaultModel, - getSuggestedModels, useModelsFromSettings, } from "./useModelsFromSettings"; import { KNOWN_MODELS } from "@/common/constants/knownModels"; +import { getSuggestedModels } from "@/common/utils/ai/selectableModels"; import type { ProviderConfigInfo, ProviderModelEntry, diff --git a/src/browser/hooks/useModelsFromSettings.ts b/src/browser/hooks/useModelsFromSettings.ts index 870d92daad3..5c988d01e3f 100644 --- a/src/browser/hooks/useModelsFromSettings.ts +++ b/src/browser/hooks/useModelsFromSettings.ts @@ -26,15 +26,14 @@ import { dedupeKeepFirst, filterHiddenModels, getCustomModels, - getSuggestedModels, isAuthoritativeProviderModelAccessible as isAuthoritativeProviderModelAccessibleIn, isProviderConfigured, } from "@/common/utils/ai/selectableModels"; import { getProviderModelEntryId } from "@/common/utils/providers/modelEntries"; // The selector pipeline lives in @/common (shared with the backend models_list -// tool); these two stay exported for existing importers/tests. -export { filterHiddenModels, getSuggestedModels }; +// tool); this one stays exported for existing importers. +export { filterHiddenModels }; const BUILT_IN_MODEL_SET = new Set(BUILT_IN_MODELS); // Module-level so the default keeps a stable identity across renders. diff --git a/src/browser/stories/helpers/contrast.ts b/src/browser/stories/helpers/contrast.ts index 5f110af3f5c..37ea7d36d5e 100644 --- a/src/browser/stories/helpers/contrast.ts +++ b/src/browser/stories/helpers/contrast.ts @@ -95,25 +95,6 @@ export function textContrast(element: HTMLElement): number { return contrastRatio(over(toRgba(getComputedStyle(element).color), background), background); } -/** - * WCAG 2.x contrast of an element's text on its own (often translucent) background drawn over - * the opaque color `base`, a computed color string. Lets a play check a tinted chip on every - * background its row can have (for example the selected row color), not only the current one. - */ -export function textContrastOnBase(element: HTMLElement, base: string): number { - const style = getComputedStyle(element); - const background = over(toRgba(style.backgroundColor), toRgba(base)); - return contrastRatio(over(toRgba(style.color), background), background); -} - -/** The nearest ancestor of `element` (or itself) whose background is opaque. */ -export function opaqueBackgroundOwner(element: HTMLElement): HTMLElement | null { - for (let node: HTMLElement | null = element; node; node = node.parentElement) { - if (toRgba(getComputedStyle(node).backgroundColor)[3] === 1) return node; - } - return null; -} - /** * WCAG 2.x contrast of the CSS color `color` drawn on the background behind `element`. Lets a * play check a color value (for example a replacement in a syntax theme) on the backgrounds the diff --git a/src/browser/utils/highlighting/highlightDiffChunk.test.ts b/src/browser/utils/highlighting/highlightDiffChunk.test.ts index 338103c7ce8..5399c56c48d 100644 --- a/src/browser/utils/highlighting/highlightDiffChunk.test.ts +++ b/src/browser/utils/highlighting/highlightDiffChunk.test.ts @@ -1,7 +1,7 @@ import { - highlightDiffChunk, highlightDiffChunks, isWithinDiffHighlightSyncBudget, + type HighlightedChunk, } from "./highlightDiffChunk"; import type { DiffChunk } from "./diffChunking"; @@ -11,7 +11,14 @@ import type { DiffChunk } from "./diffChunking"; * WASM loads on first test (~100ms), then cached for subsequent tests */ -describe("highlightDiffChunk", () => { +// One chunk through the batch API that DiffRenderer calls. +async function highlightDiffChunk(chunk: DiffChunk, language: string): Promise { + const highlighted = await highlightDiffChunks([chunk], language); + expect(highlighted).toHaveLength(1); + return highlighted[0]; +} + +describe("highlightDiffChunks", () => { const mockChunk: DiffChunk = { type: "add", lines: ["const x = 1;", "const y = 2;"], diff --git a/src/browser/utils/highlighting/highlightDiffChunk.ts b/src/browser/utils/highlighting/highlightDiffChunk.ts index 39fefd228cd..b07d2bba11c 100644 --- a/src/browser/utils/highlighting/highlightDiffChunk.ts +++ b/src/browser/utils/highlighting/highlightDiffChunk.ts @@ -52,19 +52,6 @@ export interface HighlightedChunk { usedFallback: boolean; // True if highlighting failed } -/** - * Highlight a chunk of code using Shiki. - * Falls back to plain text on error, except a worker start timeout, which rejects. - */ -export async function highlightDiffChunk( - chunk: DiffChunk, - language: string, - themeMode: ThemeMode = "dark" -): Promise { - const [highlighted] = await highlightDiffChunks([chunk], language, themeMode); - return highlighted ?? createFallbackChunk(chunk); -} - interface DiffLineRef { chunkIndex: number; lineIndex: number; diff --git a/src/browser/utils/highlighting/highlightsEngine.ts b/src/browser/utils/highlighting/highlightsEngine.ts index 9a9eae91185..595669bbde6 100644 --- a/src/browser/utils/highlighting/highlightsEngine.ts +++ b/src/browser/utils/highlighting/highlightsEngine.ts @@ -6,7 +6,7 @@ * Shiki only for the languages Highlights does not know (ini, nginx, prisma, ...). * * Output contract: the same HTML shape Shiki's `codeToHtml` produces, so every caller - * (`extractShikiLines`, `highlightDiffChunk`, the contrast stories) works unchanged: + * (`extractShikiLines`, `highlightDiffChunks`, the contrast stories) works unchanged: *
TOKENS\n…
* Each token is `TEXT`. * We do not use Highlights' own `codeToHtml()`: it has no per-line spans, and one span can diff --git a/src/browser/utils/messages/StreamingTPSCalculator.test.ts b/src/browser/utils/messages/StreamingTPSCalculator.test.ts index 105eef02cf4..4cba9fab579 100644 --- a/src/browser/utils/messages/StreamingTPSCalculator.test.ts +++ b/src/browser/utils/messages/StreamingTPSCalculator.test.ts @@ -1,5 +1,5 @@ import { describe, test, expect } from "bun:test"; -import { calculateTPS, calculateTokenCount, type DeltaRecord } from "./StreamingTPSCalculator"; +import { calculateTPS, calculateTokenCount, type DeltaRecord } from "@/common/utils/tokens/tps"; describe("StreamingTPSCalculator", () => { describe("calculateTokenCount", () => { diff --git a/src/browser/utils/messages/StreamingTPSCalculator.ts b/src/browser/utils/messages/StreamingTPSCalculator.ts index 88387fa34b9..a8260c5e1e7 100644 --- a/src/browser/utils/messages/StreamingTPSCalculator.ts +++ b/src/browser/utils/messages/StreamingTPSCalculator.ts @@ -5,16 +5,10 @@ * Designed to be independently testable from the main aggregator. */ -import { - calculateTPS, - calculateTokenCount, - createDeltaStorage, - type DeltaRecord, - type DeltaRecordStorage, -} from "@/common/utils/tokens/tps"; +import { createDeltaStorage, type DeltaRecordStorage } from "@/common/utils/tokens/tps"; -export { calculateTPS, calculateTokenCount, createDeltaStorage }; -export type { DeltaRecord, DeltaRecordStorage }; +export { createDeltaStorage }; +export type { DeltaRecordStorage }; /** * Maximum reasonable TPS for sanity checking. diff --git a/src/browser/utils/workflowRunMessages.test.ts b/src/browser/utils/workflowRunMessages.test.ts index 038581c48b9..1c4b0a68bc6 100644 --- a/src/browser/utils/workflowRunMessages.test.ts +++ b/src/browser/utils/workflowRunMessages.test.ts @@ -1,9 +1,11 @@ import { describe, expect, test } from "bun:test"; -import { buildWorkflowResultContextMessage } from "@/common/utils/workflowRunMessages"; import { - buildWorkflowRunCardMessage, + buildWorkflowResultContextMessage, filterWorkflowDisplayOnlyMessages, +} from "@/common/utils/workflowRunMessages"; +import { + buildWorkflowRunCardMessage, getWorkflowRunCardProjection, hasWorkflowRunToolCallMessage, } from "./workflowRunMessages"; diff --git a/src/browser/utils/workflowRunMessages.ts b/src/browser/utils/workflowRunMessages.ts index ee372d83fb3..a099b2349f6 100644 --- a/src/browser/utils/workflowRunMessages.ts +++ b/src/browser/utils/workflowRunMessages.ts @@ -10,13 +10,12 @@ import { WORKFLOW_RUN_CARD_DISPLAY_METADATA_TYPE, WORKFLOW_TRIGGER_DISPLAY_METADATA_TYPE, buildWorkflowRunCardMessage, - filterWorkflowDisplayOnlyMessages, isWorkflowRunEmittingToolName, type WorkflowRunCardInput, type WorkflowRunCardResult, } from "@/common/utils/workflowRunMessages"; -export { buildWorkflowRunCardMessage, filterWorkflowDisplayOnlyMessages }; +export { buildWorkflowRunCardMessage }; function getLatestWorkflowResult(run: WorkflowRunRecord): unknown { return run.events.findLast((event) => event.type === "result")?.result ?? null; diff --git a/src/browser/utils/workspaceStorage.test.ts b/src/browser/utils/workspaceStorage.test.ts index ba0253029d9..2226fe4b8a7 100644 --- a/src/browser/utils/workspaceStorage.test.ts +++ b/src/browser/utils/workspaceStorage.test.ts @@ -1,17 +1,13 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { GlobalWindow } from "happy-dom"; import { restoreDomGlobals, saveDomGlobals } from "../../../tests/ui/domGlobals"; -import { QuotaLimitedStorage } from "../../../tests/ui/quotaLimitedStorage"; import { copyWorkspaceStorage, deleteWorkspaceStorage, - migrateWorkspaceStorage, } from "@/browser/utils/workspaceStorage"; import { - getAutoExpandPrefsKey, getReviewsKey, - getPersistedKeyRegistration, getDesktopPopoutKey, getMCPTestResultsKey, getPinnedTodoExpandedKey, @@ -78,50 +74,6 @@ describe("deleteWorkspaceStorage", () => { }); }); -describe("migrateWorkspaceStorage", () => { - beforeEach(() => { - saveDomGlobals(); - }); - - afterEach(() => { - restoreDomGlobals(); - }); - - // The copy no longer throws when a write fails; deleting the source anyway would erase the - // only persisted copy of the scope's model/review/name state. - test("keeps the source keys when a destination write fails", () => { - const storage = new QuotaLimitedStorage(60); - const domWindow = new GlobalWindow() as unknown as Window & typeof globalThis; - Object.defineProperty(domWindow, "localStorage", { value: storage, configurable: true }); - globalThis.window = domWindow; - globalThis.document = domWindow.document; - globalThis.localStorage = storage; - const sourceKey = getAutoExpandPrefsKey("__pending__/repo"); - storage.setItem(sourceKey, JSON.stringify("anthropic:claude-opus")); - - migrateWorkspaceStorage("__pending__/repo", "ws-destination"); - - expect(storage.getItem(sourceKey)).toBe(JSON.stringify("anthropic:claude-opus")); - }); - - // A value over the destination's budget can only live there in memory, so without an owner bound - // the source must stay the durable copy. - test("keeps a source value without an owner bound that is over its budget at the destination", () => { - const domWindow = new GlobalWindow() as unknown as Window & typeof globalThis; - globalThis.window = domWindow; - globalThis.document = domWindow.document; - globalThis.localStorage = domWindow.localStorage; - const sourceKey = getAutoExpandPrefsKey("__pending__/repo2"); - const budget = getPersistedKeyRegistration(sourceKey)!.maxValueChars; - const legacyValue = JSON.stringify("m".repeat(budget)); - localStorage.setItem(sourceKey, legacyValue); - - migrateWorkspaceStorage("__pending__/repo2", "ws-destination2"); - - expect(localStorage.getItem(sourceKey)).toBe(legacyValue); - }); -}); - describe("copyWorkspaceStorage", () => { beforeEach(() => { saveDomGlobals(); diff --git a/src/browser/utils/workspaceStorage.ts b/src/browser/utils/workspaceStorage.ts index 4fc1e8c5090..ffe741de164 100644 --- a/src/browser/utils/workspaceStorage.ts +++ b/src/browser/utils/workspaceStorage.ts @@ -59,14 +59,3 @@ export function deleteWorkspaceStorage(workspaceId: string): void { export function listWorkspaceStorageGcCandidateKeys(): string[] { return listPersistedStateKeys([""]).filter(isWorkspaceStorageGcCandidateKey); } - -/** - * Migrate all workspace-specific localStorage keys from old to new workspace ID - * Should be called when a workspace is renamed to preserve settings. - * If any copy fails (e.g. the quota is full), the old keys are kept: the write helpers report - * failure instead of throwing, and deleting anyway would erase the only persisted copy. - */ -export function migrateWorkspaceStorage(oldWorkspaceId: string, newWorkspaceId: string): void { - if (!copyWorkspaceStorage(oldWorkspaceId, newWorkspaceId)) return; - deleteWorkspaceStorage(oldWorkspaceId); -} diff --git a/src/common/constants/storage.ts b/src/common/constants/storage.ts index 386fedba2c5..53176691154 100644 --- a/src/common/constants/storage.ts +++ b/src/common/constants/storage.ts @@ -784,7 +784,7 @@ export interface WorkspaceKeyRegistration { scope: "workspaceId"; getKey: (scopeId: string) => string; kind: PersistedKeyKind; - /** Copied to the new workspace on fork (and to the new scope on migrateWorkspaceStorage). */ + /** Copied to the new workspace on fork. */ copyOnFork: boolean; /** Longest accepted serialized value (UTF-16 code units); 0 refuses every write. */ maxValueChars: number; From 0ca38c7952c821fc2e4f75cdfc85413a749a9d19 Mon Sep 17 00:00:00 2001 From: Thomas Kosiewski Date: Mon, 26 Oct 2026 14:34:48 +0000 Subject: [PATCH 2/2] fmt --- src/browser/utils/workspaceStorage.test.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/browser/utils/workspaceStorage.test.ts b/src/browser/utils/workspaceStorage.test.ts index 2226fe4b8a7..aba110bbc47 100644 --- a/src/browser/utils/workspaceStorage.test.ts +++ b/src/browser/utils/workspaceStorage.test.ts @@ -2,10 +2,7 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { GlobalWindow } from "happy-dom"; import { restoreDomGlobals, saveDomGlobals } from "../../../tests/ui/domGlobals"; -import { - copyWorkspaceStorage, - deleteWorkspaceStorage, -} from "@/browser/utils/workspaceStorage"; +import { copyWorkspaceStorage, deleteWorkspaceStorage } from "@/browser/utils/workspaceStorage"; import { getReviewsKey, getDesktopPopoutKey,