diff --git a/apps/web/src/components/ComposerUsageIndicator.test.tsx b/apps/web/src/components/ComposerUsageIndicator.test.tsx
new file mode 100644
index 000000000..a0e0fe334
--- /dev/null
+++ b/apps/web/src/components/ComposerUsageIndicator.test.tsx
@@ -0,0 +1,155 @@
+import {
+ EnvironmentId,
+ ProviderDriverKind,
+ ProviderInstanceId,
+ type ServerProvider,
+} from "@t3tools/contracts";
+import { renderToStaticMarkup } from "react-dom/server";
+import { describe, expect, it } from "vite-plus/test";
+
+import { deriveComposerUsage, hasComposerUsageContent } from "../providerUsageAccounts";
+import { shouldShowComposerContextStrip } from "./BranchToolbar.logic";
+import { ComposerUsageIndicator } from "./ComposerUsageIndicator";
+
+const prime: ServerProvider = {
+ instanceId: ProviderInstanceId.make("primeAgent"),
+ driver: ProviderDriverKind.make("primeAgent"),
+ enabled: true,
+ installed: true,
+ version: null,
+ status: "ready",
+ auth: { status: "authenticated" },
+ checkedAt: "2026-09-10T12:00:00.000Z",
+ models: [
+ { slug: "default", name: "Prime Agent Default", isCustom: false, capabilities: null },
+ {
+ slug: "prime-inference/claude-haiku-4-5",
+ name: "Claude Haiku 4.5",
+ subProvider: "prime-inference",
+ isCustom: false,
+ capabilities: null,
+ },
+ {
+ slug: "openai/gpt-5.6",
+ name: "GPT-5.6",
+ subProvider: "openai",
+ isCustom: false,
+ capabilities: null,
+ },
+ {
+ slug: "openai-codex/gpt-5.6",
+ name: "GPT-5.6",
+ subProvider: "openai-codex",
+ isCustom: false,
+ capabilities: null,
+ },
+ ],
+ slashCommands: [],
+ skills: [],
+};
+const codex: ServerProvider = {
+ ...prime,
+ instanceId: ProviderInstanceId.make("codex"),
+ driver: ProviderDriverKind.make("codex"),
+ displayName: "Codex Work",
+ models: [],
+ auth: { status: "authenticated", accountId: "codex-account" },
+ usageLimits: {
+ source: "codex",
+ checkedAt: "2026-09-10T12:00:00.000Z",
+ windows: [{ label: "Session", usedPercent: 37, windowDurationMins: 300 }],
+ },
+};
+
+function renderUsage(
+ selectedModel: string | null,
+ options: { enabled?: boolean; backends?: ServerProvider["backends"] } = {},
+) {
+ const usage = deriveComposerUsage({
+ providerStatuses: [
+ codex,
+ { ...prime, ...(options.backends ? { backends: options.backends } : {}) },
+ ],
+ selectedInstanceId: prime.instanceId,
+ selectedModel,
+ enabled: options.enabled ?? true,
+ });
+ // Exercise the gate ChatView uses when there are no other reasons to show the strip.
+ const showStrip = shouldShowComposerContextStrip({
+ hasActiveProject: true,
+ isGitRepo: false,
+ showEnvironmentIndicator: false,
+ hostsRestingComposerControls: false,
+ hasCapacityReading: hasComposerUsageContent(usage),
+ });
+ const html = renderToStaticMarkup(
+ ,
+ );
+ return { html, showStrip, usage };
+}
+
+describe("ComposerUsageIndicator", () => {
+ it.each(["prime-inference/claude-haiku-4-5", "openai/gpt-5.6"])(
+ "keeps the strip visible and explains unreported capacity for %s",
+ (selectedModel) => {
+ const { html, showStrip } = renderUsage(selectedModel);
+
+ expect(showStrip).toBe(true);
+ expect(html).toContain(">Capacity not reported for this backend");
+ expect(html).not.toContain("Codex Work");
+ expect(html).not.toContain("37%");
+ expect(html).not.toContain("