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.
+
+ Ask them to visit Company Settings → Access to approve your request.
+
Refresh this page after you've been approved — you'll be redirected automatically.