diff --git a/apps/desktop/layer/renderer/src/modules/entry-content/components/entry-read-history/EntryReadHistory.test.tsx b/apps/desktop/layer/renderer/src/modules/entry-content/components/entry-read-history/EntryReadHistory.test.tsx new file mode 100644 index 000000000..66385179e --- /dev/null +++ b/apps/desktop/layer/renderer/src/modules/entry-content/components/entry-read-history/EntryReadHistory.test.tsx @@ -0,0 +1,113 @@ +import * as React from "react" +import { act } from "react" +import type { Root } from "react-dom/client" +import { createRoot } from "react-dom/client" +import { afterEach, beforeAll, describe, expect, test, vi } from "vitest" + +import { EntryReadHistory } from "./EntryReadHistory" + +const { useEntryReadHistoryMock, useWhoamiMock } = vi.hoisted(() => ({ + useEntryReadHistoryMock: vi.fn(), + useWhoamiMock: vi.fn(), +})) + +vi.mock("@follow/components/ui/avatar-group/index.js", () => ({ + AvatarGroup: ({ children }: { children: React.ReactNode }) => ( +
{children}
+ ), +})) + +vi.mock("@follow/store/entry/hooks", () => ({ + useEntryReadHistory: useEntryReadHistoryMock, +})) + +vi.mock("@follow/store/user/hooks", () => ({ + useWhoami: useWhoamiMock, +})) + +vi.mock("~/hooks/biz/useRouteParams", () => ({ + getRouteParams: vi.fn(() => ({ view: 0 })), +})) + +vi.mock("~/providers/app-grid-layout-container-provider", () => ({ + useAppLayoutGridContainerWidth: vi.fn(() => 800), +})) + +vi.mock("./EntryUser", () => ({ + EntryUser: ({ userId }: { userId: string }) => {userId}, +})) + +const renderComponent = async (element: React.ReactNode) => { + const container = document.createElement("div") + document.body.append(container) + + const root = createRoot(container) + + await act(async () => { + root.render(element) + }) + + return { container, root } +} + +describe("EntryReadHistory", () => { + let root: Root | null = null + let container: HTMLElement | null = null + + beforeAll(() => { + ;(globalThis as typeof globalThis & { React: typeof React }).React = React + ;( + globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT: boolean } + ).IS_REACT_ACT_ENVIRONMENT = true + }) + + afterEach(async () => { + if (root) { + await act(async () => { + root?.unmount() + }) + } + + container?.remove() + root = null + container = null + vi.clearAllMocks() + }) + + test("renders nothing when read history has no displayable users", async () => { + useWhoamiMock.mockReturnValue({ id: "me" }) + useEntryReadHistoryMock.mockReturnValue({ + entryReadHistories: { + userIds: ["me"], + }, + total: 1, + }) + ;({ container, root } = await renderComponent()) + + expect(container?.innerHTML).toBe("") + }) + + test("renders nothing when read history is unavailable", async () => { + useWhoamiMock.mockReturnValue({ id: "me" }) + useEntryReadHistoryMock.mockReturnValue({ + total: 0, + }) + ;({ container, root } = await renderComponent()) + + expect(container?.innerHTML).toBe("") + }) + + test("renders users when read history has other readers", async () => { + useWhoamiMock.mockReturnValue({ id: "me" }) + useEntryReadHistoryMock.mockReturnValue({ + entryReadHistories: { + userIds: ["me", "reader-1"], + }, + total: 2, + }) + ;({ container, root } = await renderComponent()) + + expect(container?.querySelector('[data-testid="avatar-group"]')).not.toBeNull() + expect(container?.querySelector('[data-testid="entry-user"]')?.textContent).toBe("reader-1") + }) +}) diff --git a/apps/desktop/layer/renderer/src/modules/entry-content/components/entry-read-history/EntryReadHistory.tsx b/apps/desktop/layer/renderer/src/modules/entry-content/components/entry-read-history/EntryReadHistory.tsx index ee6e2211b..0a3a5135f 100644 --- a/apps/desktop/layer/renderer/src/modules/entry-content/components/entry-read-history/EntryReadHistory.tsx +++ b/apps/desktop/layer/renderer/src/modules/entry-content/components/entry-read-history/EntryReadHistory.tsx @@ -37,13 +37,12 @@ export const EntryReadHistory: Component<{ entryId: string }> = ({ entryId }) => const LIMIT = getLimit(appGirdContainerWidth) - const placeholder =
- if (!entryHistory) return placeholder - if (!me) return placeholder + if (!entryHistory) return null + if (!me) return null const displayUsers = entryHistory.userIds.filter((id) => id !== me?.id).slice(0, LIMIT) - if (displayUsers.length === 0) return placeholder + if (displayUsers.length === 0) return null return (