6e59793643
- F1 [blocking]: share-modal.test.tsx + comment-content-view.test.tsx mocked page-query without usePageMetaQuery → 3 tests threw (ShareModal uses it directly, comment-content-view via MentionContent). Added usePageMetaQuery to both mocks (the space-tree mocks were already fixed; these two were missed). - F2: restored refetchOnMount:true on useGetSpacesQuery — ["spaces"] is invalidated only by same-tab mutations (no socket path), so a cross-actor change (an admin adding/removing THIS user from a space) left the list stale until a hard reload. The other refetchOnMount removals (favorites/watched — per-user, same-tab-only gap) stay removed. - F3: corrected the trash-list + recent-changes KEEP comments — both keys ARE invalidated (trash-list by 3 mutations, recent-changes by page CRUD), but invalidateQueries only marks an UNMOUNTED query stale without refetching, so the mount refetch closes the gap. The old "never invalidated" wording was wrong and risked a maintainer deleting a live invalidation as dead code. - F4: tests for the two load-bearing pure paths — invalidate-on-update-page (the undefined-guard: a title-only event keeps the icon; sibling/unrelated subtrees untouched) and breadcrumb-path-equal (equal chain → true; any id/slugId/name/ icon change or length diff → false; both-null → true). Exported breadcrumbPathEqual for the test. Gate: client tsc 0; the 4 affected/new test files 33 passed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
76 lines
2.4 KiB
TypeScript
76 lines
2.4 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
|
|
import { MantineProvider } from "@mantine/core";
|
|
import { MemoryRouter } from "react-router-dom";
|
|
|
|
// matchMedia / storage are stubbed globally in vitest.setup.ts.
|
|
|
|
// Enabling a public share must NOT silently expose the whole sub-tree (#216):
|
|
// the create call defaults includeSubPages to false. This was a one-literal,
|
|
// security-relevant default with no test — lock it.
|
|
|
|
const createMutateAsync = vi.fn(async () => ({}));
|
|
const deleteMutateAsync = vi.fn(async () => ({}));
|
|
|
|
// No existing share for this page (toggle starts OFF).
|
|
let shareData: any = undefined;
|
|
|
|
vi.mock("react-i18next", () => ({
|
|
useTranslation: () => ({ t: (key: string) => key }),
|
|
}));
|
|
|
|
vi.mock("@/features/share/queries/share-query.ts", () => ({
|
|
useCreateShareMutation: () => ({ mutateAsync: createMutateAsync }),
|
|
useDeleteShareMutation: () => ({ mutateAsync: deleteMutateAsync }),
|
|
useUpdateShareMutation: () => ({ mutateAsync: vi.fn() }),
|
|
useShareForPageQuery: () => ({ data: shareData }),
|
|
}));
|
|
|
|
vi.mock("@/features/page/queries/page-query.ts", () => ({
|
|
usePageQuery: () => ({ data: { id: "page-1", title: "Doc" } }),
|
|
usePageMetaQuery: () => ({ data: { id: "page-1", title: "Doc" } }),
|
|
}));
|
|
|
|
vi.mock("@/features/space/queries/space-query.ts", () => ({
|
|
useSpaceQuery: () => ({ data: { settings: {} } }),
|
|
}));
|
|
|
|
import ShareModal from "./share-modal";
|
|
|
|
function renderModal() {
|
|
return render(
|
|
<MemoryRouter>
|
|
<MantineProvider>
|
|
<ShareModal readOnly={false} />
|
|
</MantineProvider>
|
|
</MemoryRouter>,
|
|
);
|
|
}
|
|
|
|
describe("ShareModal — enabling a share defaults includeSubPages to false (#216)", () => {
|
|
beforeEach(() => {
|
|
createMutateAsync.mockClear();
|
|
deleteMutateAsync.mockClear();
|
|
shareData = undefined;
|
|
});
|
|
|
|
it("creates the share with includeSubPages: false when the user turns it on", async () => {
|
|
renderModal();
|
|
|
|
// Open the share popover.
|
|
fireEvent.click(screen.getByRole("button", { name: "Share" }));
|
|
|
|
// The "Share to web" toggle is the only switch in the not-yet-shared state.
|
|
const toggle = await screen.findByRole("switch");
|
|
fireEvent.click(toggle);
|
|
|
|
await waitFor(() => expect(createMutateAsync).toHaveBeenCalledTimes(1));
|
|
expect(createMutateAsync).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
pageId: "page-1",
|
|
includeSubPages: false,
|
|
}),
|
|
);
|
|
});
|
|
});
|