fix(integrations): name a managed profile without a display name by its username

The connect cards read the display name alone, so a profile created without
one rendered "Connect for" with nobody after it. Use the account label the
switcher and the banner use.
This commit is contained in:
Marc-André Bombeck committed 2026-10-22 02:31:56 +02:00
1 parent 25d7a01d9d
commit 11cd7fbeb6
2 files changed
+25 -12

No files matched your search

@@ -7,17 +7,19 @@ import { renderToStaticMarkup } from "react-dom/server";
import type { ConnectionHealth } from "@/lib/integrations/connection-health";
const NAMED_RECORD = {
accountId: "record-1",
recordKind: "managed",
username: "managed-1",
displayName: "Managed record" as string | null,
fullName: null as string | null,
};
let activeRecord = NAMED_RECORD;
vi.mock("@/hooks/use-auth", () => ({
useAuth: () => ({
user: {
id: "guardian",
accountAccess: {
active: {
accountId: "record-1",
recordKind: "managed",
displayName: "Managed record",
},
},
accountAccess: { active: activeRecord },
},
isAuthenticated: true,
isLoading: false,
@@ -78,6 +80,7 @@ describe("<ManagedIntegrationStatus>", () => {
beforeEach(() => {
payload = undefined;
loading = false;
activeRecord = NAMED_RECORD;
});
it("renders one shared card per provider from health, with controls on the OAuth ones", () => {
@@ -140,6 +143,16 @@ describe("<ManagedIntegrationStatus>", () => {
);
});
it("names a profile without a display name by its username", () => {
activeRecord = { ...NAMED_RECORD, displayName: null };
payload = withHealth({});
const html = render();
expect(html.match(/Connects for managed-1</g)).toHaveLength(6);
expect(html.match(/>Connect for managed-1</g)).toHaveLength(6);
expect(html).not.toMatch(/Connects? for </);
expect(html).toContain('aria-label="managed-1"');
});
it("paints the cards while loading without claiming a state", () => {
loading = true;
const html = render();
@@ -28,6 +28,7 @@ import {
queryKeys,
} from "@/lib/query-keys";
import { assertRecordSettingsResponseForRecord } from "@/lib/record-settings/response";
import { accountLabel } from "@/lib/sharing/account-access-view";
type ManagedIntegrationKey = keyof typeof INTEGRATION_DISPLAY_NAMES;
@@ -90,7 +91,9 @@ export function ManagedIntegrationStatus() {
enabled: activeRecord?.recordKind === "managed" && recordId !== null,
});
const recordName = activeRecord?.displayName ?? "";
// Named the way the switcher and the banner name it: a profile created
// without a display name still has a name to connect for.
const recordName = activeRecord ? accountLabel(activeRecord) : "";
const invalidateStatus = () =>
queryClient.invalidateQueries({
@@ -248,10 +251,7 @@ export function ManagedIntegrationStatus() {
<ExternalLink className="size-3" aria-hidden="true" />
</a>
</p>
<ul
className="space-y-4"
aria-label={activeRecord?.displayName ?? undefined}
>
<ul className="space-y-4" aria-label={recordName || undefined}>
{entries.map((entry) => (
<li key={entry.integration}>
<IntegrationCard