From 06a05ccee5a60e472c65d29739f9440d3aefefd2 Mon Sep 17 00:00:00 2001 From: Dotta Date: Mon, 13 Apr 2026 08:24:55 -0500 Subject: [PATCH] Update invite approval request copy --- ui/src/pages/InviteLanding.test.tsx | 70 +++++++++++++++++++++++++++++ ui/src/pages/InviteLanding.tsx | 15 ++++--- 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/ui/src/pages/InviteLanding.test.tsx b/ui/src/pages/InviteLanding.test.tsx index 8294879ac65..94364a384bc 100644 --- a/ui/src/pages/InviteLanding.test.tsx +++ b/ui/src/pages/InviteLanding.test.tsx @@ -348,6 +348,76 @@ describe("InviteLandingPage", () => { }); }); + it("shows the pending approval page with the company icon and linked access instructions", async () => { + acceptInviteMock.mockResolvedValue({ + id: "join-1", + companyId: "company-1", + requestType: "human", + status: "pending_approval", + }); + getSessionMock.mockResolvedValue({ + session: { id: "session-1", userId: "user-1" }, + user: { + id: "user-1", + name: "Jane Example", + email: "jane@example.com", + image: null, + }, + }); + + const root = createRoot(container); + const queryClient = new QueryClient({ + defaultOptions: { queries: { retry: false } }, + }); + + await act(async () => { + root.render( + + + + } /> + + + , + ); + }); + await flushReact(); + await flushReact(); + + const continueButton = Array.from(container.querySelectorAll("button")).find( + (button) => button.textContent === "Accept invite", + ); + expect(continueButton).not.toBeNull(); + + await act(async () => { + continueButton?.dispatchEvent(new MouseEvent("click", { bubbles: true })); + }); + await flushReact(); + await flushReact(); + + expect(acceptInviteMock).toHaveBeenCalledWith("pcp_invite_test", { requestType: "human" }); + expect(container.textContent).toContain("Request to join Acme Robotics"); + expect(container.textContent).toContain("A company admin must approve your request to join."); + expect(container.textContent).toContain( + "Ask them to visit Company Settings → Access to approve your request.", + ); + expect(container.querySelector('img[alt="Acme Robotics logo"]')).not.toBeNull(); + expect(container.textContent).not.toContain("http://localhost/company/settings/access"); + + const approvalLinks = Array.from(container.querySelectorAll("a")).filter( + (link) => link.textContent === "Company Settings → Access", + ); + expect(approvalLinks).toHaveLength(2); + const expectedApprovalUrl = `${window.location.origin}/company/settings/access`; + for (const link of approvalLinks) { + expect(link.getAttribute("href")).toBe(expectedApprovalUrl); + } + + await act(async () => { + root.unmount(); + }); + }); + it("redirects straight to the company after sign-in when the user already has access", async () => { listCompaniesMock.mockResolvedValue([{ id: "company-1", name: "Acme Robotics" }]); diff --git a/ui/src/pages/InviteLanding.tsx b/ui/src/pages/InviteLanding.tsx index ecfec7d5adc..2068ebc3e6f 100644 --- a/ui/src/pages/InviteLanding.tsx +++ b/ui/src/pages/InviteLanding.tsx @@ -353,6 +353,7 @@ export function InviteLandingPage() { const onboardingTextUrl = readNestedString(payload.onboarding, ["textInstructions", "url"]); const joinedNow = !showsAgentForm && payload.status === "approved"; const approvalUrl = `${window.location.origin}/company/settings/access`; + const approverLabel = invitedByUserName ?? "A company admin"; return (
@@ -365,7 +366,7 @@ export function InviteLandingPage() { className="h-12 w-12 border border-zinc-800 rounded-none" />

- {joinedNow ? "You joined the company" : "Request submitted"} + {joinedNow ? "You joined the company" : `Request to join ${companyDisplayName}`}

{joinedNow ? ( @@ -377,20 +378,20 @@ export function InviteLandingPage() { ) : (

- {invitedByUserName - ? `${invitedByUserName} must approve your request to join.` - : "Your request is pending approval."} - {" "}Ask them to visit the link below to approve it. + {approverLabel} must approve your request to join.

Approval page

- {approvalUrl} + Company Settings → Access
+

+ Ask them to visit Company Settings → Access to approve your request. +

Refresh this page after you've been approved — you'll be redirected automatically.