Show invited people the Rule, let them copy its cards for their community, and replace an expired invitation link.
This commit is contained in:
1 parent
727a92a9ac
commit
3c984e00c5
37 files changed
+1962
-19
No files matched your search
@@ -130,6 +130,24 @@ describe("CompletedScreen", () => {
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows copy-ready toast when copied query is set", () => {
|
||||
sessionStorage.setItem(
|
||||
CREATE_FLOW_LAST_PUBLISHED_KEY,
|
||||
JSON.stringify({
|
||||
...storedRuleFixture,
|
||||
copiedFromTitle: "Juniper Street Food Share",
|
||||
}),
|
||||
);
|
||||
mockSearchParams({ copied: "1" });
|
||||
render(<CompletedScreen />);
|
||||
expect(screen.getByText("Your copy is ready")).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
"It started from Juniper Street Food Share’s Rule. Read it through and change what does not fit before you invite your members.",
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows post-publish toast in status region when celebrate query is set", () => {
|
||||
mockSearchParams({
|
||||
[CREATE_FLOW_COMPLETED_CELEBRATE_QUERY]:
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
import { renderWithProviders as render, screen } from "../utils/test-utils";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import "@testing-library/jest-dom/vitest";
|
||||
import { ExpiredInviteScreen } from "../../app/(app)/invite/_components/ExpiredInviteScreen";
|
||||
|
||||
const { navMock, resendMock } = vi.hoisted(() => ({
|
||||
navMock: {
|
||||
searchParams: new URLSearchParams("token=abcdefghijkl"),
|
||||
push: vi.fn(),
|
||||
},
|
||||
resendMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("next/navigation", () => ({
|
||||
useRouter: () => ({
|
||||
push: navMock.push,
|
||||
replace: vi.fn(),
|
||||
prefetch: vi.fn(),
|
||||
refresh: vi.fn(),
|
||||
back: vi.fn(),
|
||||
forward: vi.fn(),
|
||||
}),
|
||||
useSearchParams: () => navMock.searchParams,
|
||||
usePathname: () => "/invite/expired",
|
||||
}));
|
||||
|
||||
vi.mock("../../lib/create/api", () => ({
|
||||
resendExpiredStakeholderInvite: (...args: unknown[]) => resendMock(...args),
|
||||
}));
|
||||
|
||||
describe("ExpiredInviteScreen", () => {
|
||||
beforeEach(() => {
|
||||
navMock.searchParams = new URLSearchParams("token=abcdefghijkl");
|
||||
navMock.push.mockReset();
|
||||
resendMock.mockReset();
|
||||
resendMock.mockResolvedValue({ ok: true });
|
||||
});
|
||||
|
||||
it("asks for the invited email and sends a new link", async () => {
|
||||
const user = userEvent.setup();
|
||||
render(<ExpiredInviteScreen />);
|
||||
|
||||
expect(
|
||||
screen.getByRole("heading", { name: "This link has expired" }),
|
||||
).toBeInTheDocument();
|
||||
await user.type(
|
||||
screen.getByLabelText("Email address"),
|
||||
"inv@example.com",
|
||||
);
|
||||
await user.click(
|
||||
screen.getByRole("button", { name: "Send a new link" }),
|
||||
);
|
||||
|
||||
expect(resendMock).toHaveBeenCalledWith(
|
||||
"abcdefghijkl",
|
||||
"inv@example.com",
|
||||
);
|
||||
expect(
|
||||
await screen.findByRole("heading", { name: "Check your email" }),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,68 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { renderWithProviders as render, screen } from "../utils/test-utils";
|
||||
import "@testing-library/jest-dom/vitest";
|
||||
import { InvitedRuleView } from "../../app/(app)/invite/_components/InvitedRuleView";
|
||||
|
||||
vi.mock("next/navigation", () => ({
|
||||
useRouter: () => ({
|
||||
replace: vi.fn(),
|
||||
push: vi.fn(),
|
||||
prefetch: vi.fn(),
|
||||
refresh: vi.fn(),
|
||||
back: vi.fn(),
|
||||
forward: vi.fn(),
|
||||
}),
|
||||
}));
|
||||
|
||||
const document = {
|
||||
sections: [
|
||||
{
|
||||
categoryName: "Values",
|
||||
entries: [
|
||||
{
|
||||
title: "Care",
|
||||
body: "We care for each other.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
describe("InvitedRuleView", () => {
|
||||
it("names the inviter by email and offers Make a copy", () => {
|
||||
render(
|
||||
<InvitedRuleView
|
||||
ruleId="rule-1"
|
||||
title="Juniper Street Food Share"
|
||||
summary="Neighbors sharing food."
|
||||
document={document}
|
||||
updatedAt="2026-11-03T00:00:00.000Z"
|
||||
inviterEmail="maya@example.com"
|
||||
viewerEmail="reader@example.com"
|
||||
countsSpoken="one value and zero cards"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByText("maya@example.com invited you to read this Rule"),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
"Their Rule sets out how they talk, who belongs, how they decide and what happens when they disagree.",
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getAllByRole("button", { name: "Make a copy of this Rule" })
|
||||
.length,
|
||||
).toBeGreaterThan(0);
|
||||
expect(
|
||||
screen.getByText("Only people the community invites"),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
"Every Rule starts private. Only the people the community invites can read it until the person who holds the pen turns on a link.",
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByText("Care")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -46,7 +46,7 @@ describe("CreateFlowTextFieldScreen (community description)", () => {
|
||||
<CreateFlowTextFieldScreen
|
||||
messageNamespace="create.community.communityContext"
|
||||
stateField="communityContext"
|
||||
locationField="communityLocation"
|
||||
locationField
|
||||
maxLength={200}
|
||||
multiline
|
||||
/>,
|
||||
|
||||
Reference in new issue
Block a user