Skip to content

Commit

Permalink
Merge pull request #207 from amattu2/amattu2/issue206
Browse files Browse the repository at this point in the history
fix: Post Chip embeds missing interactivity
  • Loading branch information
amattu2 authored Sep 15, 2024
2 parents 384314d + 1870410 commit 844206e
Show file tree
Hide file tree
Showing 14 changed files with 434 additions and 35 deletions.
126 changes: 126 additions & 0 deletions src/components/ListLinkChip/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import React from "react";
import { render } from "@testing-library/react";
import { BrowserRouter as Router } from "react-router-dom";
import userEvent from "@testing-library/user-event";
import ListLinkChip from "./index";
import { LookupStatus, ListLookupResponse } from "../../hooks/useListLookup";

const mockUseListLookup = jest.fn<ListLookupResponse, [string]>();
jest.mock("../../hooks/useListLookup", () => ({
...jest.requireActual("../../hooks/useListLookup"),
__esModule: true,
default: (uuid: string) => mockUseListLookup(uuid),
}));

describe("Basic Functionality", () => {
beforeEach(() => {
jest.clearAllMocks();
});

it("should render a chip embed for the list if it exists", () => {
mockUseListLookup.mockReturnValue([
{
status: LookupStatus.Success,
list: { uuid: "test-uuid", name: "Test List" } as List,
},
jest.fn(),
jest.fn(),
]);

const { getByTestId } = render(<ListLinkChip uuid="test-uuid" />, { wrapper: Router });

expect(getByTestId("list-chip")).toBeInTheDocument();
expect(getByTestId("list-chip")).toHaveTextContent("Test List");
expect(getByTestId("list-chip")).toHaveAttribute("href", "/list/test-uuid");
expect(getByTestId("list-chip")).toHaveStyle("cursor: pointer;");
});

it("should open the list page when the chip is clicked", async () => {
mockUseListLookup.mockReturnValue([
{
status: LookupStatus.Success,
list: { uuid: "test-uuid", name: "Test List" } as List,
},
jest.fn(),
jest.fn(),
]);

const { getByTestId } = render(<ListLinkChip uuid="test-uuid" />, { wrapper: Router });

await userEvent.click(getByTestId("list-chip"));

expect(window.location.pathname).toBe("/list/test-uuid");
});

it("should render the original link to the list page if the list does not have a name", () => {
mockUseListLookup.mockReturnValue([
{
status: LookupStatus.Success,
list: { uuid: "test-uuid" } as List,
},
jest.fn(),
jest.fn(),
]);

const { getByText, queryByTestId } = render(<ListLinkChip uuid="test-uuid" />, {
wrapper: Router,
});

expect(getByText(`${window.origin}/list/test-uuid`)).toBeInTheDocument();
expect(queryByTestId("list-chip")).not.toBeInTheDocument();
});

it("should render a link to the list page if the list does not exist", () => {
mockUseListLookup.mockReturnValue([
{
status: LookupStatus.Success,
list: null,
},
jest.fn(),
jest.fn(),
]);

const { getByText, queryByTestId } = render(<ListLinkChip uuid="test-uuid" />, {
wrapper: Router,
});

expect(getByText(`${window.origin}/list/test-uuid`)).toBeInTheDocument();
expect(queryByTestId("list-chip")).not.toBeInTheDocument();
});

it("should render a link to the list page if the list lookup fails", () => {
mockUseListLookup.mockReturnValue([
{
status: LookupStatus.Error,
list: null,
},
jest.fn(),
jest.fn(),
]);

const { getByText, queryByTestId } = render(<ListLinkChip uuid="test-uuid" />, {
wrapper: Router,
});

expect(getByText(`${window.origin}/list/test-uuid`)).toBeInTheDocument();
expect(queryByTestId("list-chip")).not.toBeInTheDocument();
});

it("should render a link to the list page if the list lookup is pending", () => {
mockUseListLookup.mockReturnValue([
{
status: LookupStatus.Loading,
list: null,
},
jest.fn(),
jest.fn(),
]);

const { getByText, queryByTestId } = render(<ListLinkChip uuid="test-uuid" />, {
wrapper: Router,
});

expect(getByText(`${window.origin}/list/test-uuid`)).toBeInTheDocument();
expect(queryByTestId("list-chip")).not.toBeInTheDocument();
});
});
1 change: 1 addition & 0 deletions src/components/ListLinkChip/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const ListLinkChip: FC<Props> = ({ uuid }: Props) => {
to={`/list/${uuid}`}
size="small"
data-testid="list-chip"
clickable
/>
);
};
Expand Down
73 changes: 73 additions & 0 deletions src/components/MentionChip/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React from "react";
import { render } from "@testing-library/react";
import { BrowserRouter as Router } from "react-router-dom";
import userEvent from "@testing-library/user-event";
import MentionChip from "./index";
import { LookupStatus, UUIDLookupResponse } from "../../hooks/useUUIDLookup";

const mockUseUUIDLookup = jest.fn<UUIDLookupResponse, [string]>();
jest.mock("../../hooks/useUUIDLookup", () => ({
...jest.requireActual("../../hooks/useUUIDLookup"),
__esModule: true,
default: (handle: string) => mockUseUUIDLookup(handle),
}));

describe("Basic Functionality", () => {
beforeEach(() => {
jest.clearAllMocks();
});

it("should render a chip embed for the profile if it exists", () => {
mockUseUUIDLookup.mockReturnValue([LookupStatus.Success, { uuid: "test-user-uuid" }]);

const { getByTestId } = render(<MentionChip handle="test-user-handle" />, { wrapper: Router });

expect(getByTestId("mention-chip")).toBeInTheDocument();
expect(getByTestId("mention-chip")).toHaveTextContent("test-user-handle");
expect(getByTestId("mention-chip")).toHaveAttribute("href", "/profile/test-user-uuid");
expect(getByTestId("mention-chip")).toHaveStyle("cursor: pointer;");
});

it("should open the profile page when the chip is clicked", async () => {
mockUseUUIDLookup.mockReturnValue([LookupStatus.Success, { uuid: "test-user-uuid" }]);

const { getByTestId } = render(<MentionChip handle="test-user-handle" />, { wrapper: Router });

await userEvent.click(getByTestId("mention-chip"));

expect(window.location.pathname).toBe("/profile/test-user-uuid");
});

it("should render the original handle if the lookup returns no uuid", () => {
mockUseUUIDLookup.mockReturnValue([LookupStatus.Success, { uuid: null }]);

const { getByText, queryByTestId } = render(<MentionChip handle="test-user-handle" />, {
wrapper: Router,
});

expect(getByText("@test-user-handle")).toBeInTheDocument();
expect(queryByTestId("mention-chip")).not.toBeInTheDocument();
});

it("should render a link to the list page if the list lookup fails", () => {
mockUseUUIDLookup.mockReturnValue([LookupStatus.Error, { uuid: null }]);

const { getByText, queryByTestId } = render(<MentionChip handle="test-user-handle" />, {
wrapper: Router,
});

expect(getByText("@test-user-handle")).toBeInTheDocument();
expect(queryByTestId("mention-chip")).not.toBeInTheDocument();
});

it("should render a link to the list page if the list lookup is pending", () => {
mockUseUUIDLookup.mockReturnValue([LookupStatus.Loading, { uuid: null }]);

const { getByText, queryByTestId } = render(<MentionChip handle="test-user-handle" />, {
wrapper: Router,
});

expect(getByText("@test-user-handle")).toBeInTheDocument();
expect(queryByTestId("mention-chip")).not.toBeInTheDocument();
});
});
1 change: 1 addition & 0 deletions src/components/MentionChip/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const MentionChip: FC<Props> = ({ handle }: Props) => {
to={`/profile/${uuid}`}
size="small"
data-testid="mention-chip"
clickable
/>
);
};
Expand Down
97 changes: 97 additions & 0 deletions src/components/ProfileLinkChip/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from "react";
import { render } from "@testing-library/react";
import { BrowserRouter as Router } from "react-router-dom";
import userEvent from "@testing-library/user-event";
import ProfileLinkChip from "./index";
import { LookupStatus, ProfileLookupResponse } from "../../hooks/useProfileLookup";

const mockUseProfileLookup = jest.fn<ProfileLookupResponse, [string]>();
jest.mock("../../hooks/useProfileLookup", () => ({
...jest.requireActual("../../hooks/useProfileLookup"),
__esModule: true,
default: (handle: string) => mockUseProfileLookup(handle),
}));

describe("Basic Functionality", () => {
beforeEach(() => {
jest.clearAllMocks();
});

it("should render a chip embed for the username if the profile exists", () => {
mockUseProfileLookup.mockReturnValue([
{ status: LookupStatus.Success, profile: { username: "test_user" } as Profile },
jest.fn(),
jest.fn(),
]);

const { getByTestId } = render(<ProfileLinkChip uuid="test-uuid" />, {
wrapper: Router,
});

expect(getByTestId("mention-chip")).toBeInTheDocument();
expect(getByTestId("mention-chip")).toHaveTextContent("test_user");
expect(getByTestId("mention-chip")).toHaveAttribute("href", "/profile/test-uuid");
expect(getByTestId("mention-chip")).toHaveStyle("cursor: pointer;");
});

it("should open the profile page when the chip is clicked", async () => {
mockUseProfileLookup.mockReturnValue([
{ status: LookupStatus.Success, profile: { username: "test_user" } as Profile },
jest.fn(),
jest.fn(),
]);

const { getByTestId } = render(<ProfileLinkChip uuid="test-user-uuid" />, {
wrapper: Router,
});

await userEvent.click(getByTestId("mention-chip"));

expect(window.location.pathname).toBe("/profile/test-user-uuid");
});

it("should render the localized profile link if the lookup returns no profile", () => {
mockUseProfileLookup.mockReturnValue([
{ status: LookupStatus.Success, profile: null },
jest.fn(),
jest.fn(),
]);

const { getByText, queryByTestId } = render(<ProfileLinkChip uuid="test-nonexistent-uuid" />, {
wrapper: Router,
});

expect(getByText("http://localhost/profile/test-nonexistent-uuid")).toBeInTheDocument();
expect(queryByTestId("mention-chip")).not.toBeInTheDocument();
});

it("should render the localized profile link if the lookup fails", () => {
mockUseProfileLookup.mockReturnValue([
{ status: LookupStatus.Error, profile: null },
jest.fn(),
jest.fn(),
]);

const { getByText, queryByTestId } = render(<ProfileLinkChip uuid="test-user-handle" />, {
wrapper: Router,
});

expect(getByText("http://localhost/profile/test-user-handle")).toBeInTheDocument();
expect(queryByTestId("mention-chip")).not.toBeInTheDocument();
});

it("should render the localized profile link if the lookup is pending", () => {
mockUseProfileLookup.mockReturnValue([
{ status: LookupStatus.Loading, profile: null },
jest.fn(),
jest.fn(),
]);

const { getByText, queryByTestId } = render(<ProfileLinkChip uuid="test-user-handle" />, {
wrapper: Router,
});

expect(getByText("http://localhost/profile/test-user-handle")).toBeInTheDocument();
expect(queryByTestId("mention-chip")).not.toBeInTheDocument();
});
});
10 changes: 4 additions & 6 deletions src/components/ProfileLinkChip/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,10 @@ type Props = {
};

/**
* A profile UUID chip that returns a `@mention` chip
* if the user exists. Otherwise, returns a localized
* link to the profile.
*
* Not to be confused with the `<MentionChip />` itself, which
* is used when `@username` is in the post body.
* A profile embed chip used to pretty-link to a user's profile when a full profile link
* is in a message.
*
* @note This is the opposite of `<MentionChip />`, which is used when a username is known.
* @param {Props} props
* @returns {JSX.Element}
*/
Expand All @@ -33,6 +30,7 @@ const ProfileLinkChip: FC<Props> = ({ uuid }: Props) => {
to={`/profile/${uuid}`}
size="small"
data-testid="mention-chip"
clickable
/>
);
};
Expand Down
Loading

0 comments on commit 844206e

Please sign in to comment.