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>
104 lines
3.0 KiB
TypeScript
104 lines
3.0 KiB
TypeScript
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();
|
|
});
|
|
});
|