Keep listed published rules public and guest-claim rules unlisted, with semantic document markup and share chrome that stays clickable.

Guest publishes remain share-by-link but stay out of the catalog and sitemap, and their pages send noindex until claimed. The published-rule view now uses heading and list markup matching Markdown export, and top banners sit below the header so Share is not covered.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
adilalloandCursor committed 2026-09-17 17:42:01 -06:00
1 parent 77b0ec8ad8
commit 1445cb7e1e
27 files changed
+524 -86

No files matched your search

+103
View File
@@ -0,0 +1,103 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const isDatabaseConfiguredMock = vi.fn();
const findUniqueMock = vi.fn();
const findManyMock = vi.fn();
vi.mock("../../lib/server/env", () => ({
isDatabaseConfigured: () => isDatabaseConfiguredMock(),
}));
vi.mock("../../lib/server/db", () => ({
prisma: {
publishedRule: {
findUnique: (...args: unknown[]) => findUniqueMock(...args),
findMany: (...args: unknown[]) => findManyMock(...args),
},
},
}));
import {
getPublicPublishedRuleById,
listListedPublishedRules,
listListedPublishedRulesForSitemap,
} from "../../lib/server/publishedRules";
import { LISTED_PUBLISHED_RULE_WHERE } from "../../lib/publishedRuleAccess";
beforeEach(() => {
isDatabaseConfiguredMock.mockReset();
findUniqueMock.mockReset();
findManyMock.mockReset();
});
describe("getPublicPublishedRuleById", () => {
it("returns isListed false for guest-claim rows without exposing claim tokens", async () => {
isDatabaseConfiguredMock.mockReturnValue(true);
findUniqueMock.mockResolvedValueOnce({
id: "guest-1",
title: "Guest rule",
summary: null,
document: {},
createdAt: new Date("2026-01-01T00:00:00.000Z"),
updatedAt: new Date("2026-01-02T00:00:00.000Z"),
userId: null,
claimTokenHash: "secret-hash",
});
const rule = await getPublicPublishedRuleById("guest-1");
expect(rule).toMatchObject({
id: "guest-1",
title: "Guest rule",
isListed: false,
});
expect(rule).not.toHaveProperty("userId");
expect(rule).not.toHaveProperty("claimTokenHash");
});
it("returns isListed true for owned rules", async () => {
isDatabaseConfiguredMock.mockReturnValue(true);
findUniqueMock.mockResolvedValueOnce({
id: "owned-1",
title: "Owned",
summary: "Hi",
document: {},
createdAt: new Date("2026-01-01T00:00:00.000Z"),
updatedAt: new Date("2026-01-02T00:00:00.000Z"),
userId: "user-1",
claimTokenHash: null,
});
const rule = await getPublicPublishedRuleById("owned-1");
expect(rule?.isListed).toBe(true);
});
});
describe("listListedPublishedRules", () => {
it("queries the listed-rule where clause", async () => {
isDatabaseConfiguredMock.mockReturnValue(true);
findManyMock.mockResolvedValueOnce([]);
await listListedPublishedRules(10);
expect(findManyMock).toHaveBeenCalledWith(
expect.objectContaining({
where: LISTED_PUBLISHED_RULE_WHERE,
take: 10,
}),
);
});
it("returns null when the database is not configured", async () => {
isDatabaseConfiguredMock.mockReturnValue(false);
expect(await listListedPublishedRules(10)).toBeNull();
expect(findManyMock).not.toHaveBeenCalled();
});
});
describe("listListedPublishedRulesForSitemap", () => {
it("returns an empty list when the database is not configured", async () => {
isDatabaseConfiguredMock.mockReturnValue(false);
expect(await listListedPublishedRulesForSitemap()).toEqual([]);
expect(findManyMock).not.toHaveBeenCalled();
});
});