Fix user card send friend request disabled when it should not be

This commit is contained in:
Kalle
2026-09-25 07:20:16 +03:00
parent ef540fe8c1
commit fff02b78ea
5 changed files with 85 additions and 6 deletions

View File

@@ -95,15 +95,39 @@ export function UserCard({
withMutualFriends?: boolean;
children: React.ReactNode;
}) {
const { t } = useTranslation(["common", "q"]);
const lookedUpData = useUserCardData(userId);
const data = dataProp ?? lookedUpData;
if (!data) return <>{children}</>;
// keyed so friendship state doesn't carry over to another user e.g. when navigating between user pages
return (
<UserCardPopover
key={data.id}
data={data}
withMutualFriends={withMutualFriends}
>
{children}
</UserCardPopover>
);
}
function UserCardPopover({
data,
withMutualFriends,
children,
}: {
data: UserCardData;
withMutualFriends: boolean;
children: React.ReactNode;
}) {
const { t } = useTranslation(["common", "q"]);
// on narrow viewports the card is placed vertically so React Aria can shift it to stay on-screen
const placement = useLayoutSize() === "mobile" ? "bottom" : "right";
const user = useUser();
const isOwnCard = user?.id === data?.id;
const isOwnCard = user?.id === data.id;
const [isOpen, setIsOpen] = React.useState(false);
// outside the popover so the modals survive it closing when they take focus
@@ -120,7 +144,6 @@ export function UserCard({
if (!nextIsOpen) return;
if (friendshipLoadedRef.current) return;
if (isOwnCard) return;
if (typeof data?.id !== "number") return;
friendshipLoadedRef.current = true;
fetcher.load(
@@ -148,8 +171,6 @@ export function UserCard({
setIsReportDialogOpen(true);
};
if (!data) return <>{children}</>;
return (
<>
<SendouPopover

View File

@@ -0,0 +1,5 @@
---
navItem: u
type: bug
---
User card no longer shows a friend request as pending for the wrong user after moving between user pages

View File

@@ -49,6 +49,17 @@ export class UserCard {
);
}
async sendFriendRequest() {
await waitForPOSTResponse(this.page, () =>
this.locators.sendFriendRequestButton.click(),
);
}
async close() {
await this.page.keyboard.press("Escape");
await expect(this.locators.banner).not.toBeVisible();
}
async openReportDialog() {
await this.locators.reportUserButton.click();
return new ReportUserDialog(this.page);

View File

@@ -3,6 +3,7 @@ import { userPage } from "~/utils/urls";
import { navigate } from "../../helpers/playwright";
import { TeamPage } from "../team/team-page";
import { TopSearchPlayerPage } from "../top-search/top-search-player-page";
import { UserCard } from "./user-card";
import { UserEditProfilePage } from "./user-edit-profile-page";
import { UserEditWidgetsPage } from "./user-edit-widgets-page";
import { UserResultsPage } from "./user-results-page";
@@ -76,6 +77,14 @@ export class UserPage {
return this.page.getByRole("heading", { name: username });
}
/** Opens the user card from the username heading. */
openUserCard(username: string) {
return UserCard.open(
this.page,
this.usernameHeading(username).getByRole("button"),
);
}
async openEditProfile() {
await this.locators.editProfileButton.click();
return new UserEditProfilePage(this.page);

View File

@@ -1,10 +1,12 @@
import { NZAP_TEST_ID } from "~/db/seed/constants";
import { NZAP_TEST_DISCORD_ID, NZAP_TEST_ID } from "~/db/seed/constants";
import { ADMIN_ID } from "~/features/admin/admin-constants";
import { SENDOUQ_LOOKING_PAGE } from "~/utils/urls";
import { expect, impersonate, test } from "./helpers/playwright";
import { FriendsPage } from "./pages/friends/friends-page";
import { LFGPage } from "./pages/lfg/lfg-page";
import { GlobalSearchDialog } from "./pages/search/global-search-dialog";
import { SendouQLookingPage } from "./pages/sendouq/sendouq-looking-page";
import { UserPage } from "./pages/user/user-page";
test.describe("User card", () => {
test("edits banner and bio from the looking page", async ({
@@ -126,4 +128,35 @@ test.describe("User card friend request", () => {
await expect(card.locators.pendingFriendRequestButton).toBeDisabled();
await expect(card.locators.acceptFriendRequestButton).not.toBeVisible();
});
test("sending a request does not mark another user's card pending after navigating between user pages", async ({
page,
factories,
}) => {
const otherUsername = "FriendTarget";
await factories.UserFactory.create({ discordName: otherUsername });
await impersonate(page);
const userPage = new UserPage(page);
await userPage.goto(NZAP_TEST_DISCORD_ID);
const nzapCard = await userPage.openUserCard("N-ZAP");
await nzapCard.sendFriendRequest();
await expect(nzapCard.locators.pendingFriendRequestButton).toBeVisible();
await nzapCard.close();
const search = new GlobalSearchDialog(page);
await search.open();
await search.selectType("users");
await search.search(otherUsername);
await search.selectOption(otherUsername);
await expect(userPage.usernameHeading(otherUsername)).toBeVisible();
const otherCard = await userPage.openUserCard(otherUsername);
await expect(otherCard.locators.sendFriendRequestButton).toBeVisible();
await expect(
otherCard.locators.pendingFriendRequestButton,
).not.toBeVisible();
});
});