diff --git a/apps/web/src/features/settings/ai/connected-apps.test.tsx b/apps/web/src/features/settings/ai/connected-apps.test.tsx
new file mode 100644
index 000000000..56879c4ed
--- /dev/null
+++ b/apps/web/src/features/settings/ai/connected-apps.test.tsx
@@ -0,0 +1,49 @@
+// @vitest-environment happy-dom
+
+import { fireEvent, render, screen, waitFor, within } from "@testing-library/react";
+import { expect, it, vi } from "vitest";
+import { i18n } from "@lingui/core";
+import { I18nProvider } from "@lingui/react";
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+
+const oauth2 = vi.hoisted(() => ({ getConsents: vi.fn(), publicClient: vi.fn(), deleteConsent: vi.fn() }));
+vi.mock("@/libs/auth/client", () => ({ authClient: { oauth2 } }));
+
+i18n.loadAndActivate({ locale: "en", messages: {} });
+const { ConnectedAppsSection } = await import("./connected-apps");
+
+it("shows registered application names, keeps unnamed or unavailable clients revocable, and revokes the consent", async () => {
+ oauth2.getConsents.mockResolvedValue({
+ data: [
+ { id: "consent-1", clientId: "codex-client-id", scopes: ["api:read"] },
+ { id: "consent-2", clientId: "unnamed-client-id", scopes: ["api:read"] },
+ { id: "consent-3", clientId: "unavailable-client-id", scopes: ["api:read"] },
+ ],
+ error: null,
+ });
+ oauth2.publicClient.mockImplementation(({ query }: { query: { client_id: string } }) => {
+ if (query.client_id === "unavailable-client-id") return Promise.reject(new Error("Network unavailable"));
+ return Promise.resolve({
+ data: { client_name: query.client_id === "codex-client-id" ? "Codex" : null },
+ error: null,
+ });
+ });
+ oauth2.deleteConsent.mockResolvedValue({ error: null });
+
+ render(
+
{connection.clientId}
+{connection.clientName}
{connection.scopes.join(", ")}