252 lines
8.0 KiB
TypeScript
252 lines
8.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { parsePublishedDocumentForCommunityRuleDisplay } from "../../lib/create/publishedDocumentToDisplaySections";
|
|
|
|
describe("parsePublishedDocumentForCommunityRuleDisplay", () => {
|
|
it("returns [] for non-object document", () => {
|
|
expect(parsePublishedDocumentForCommunityRuleDisplay(null)).toEqual([]);
|
|
});
|
|
|
|
it("drops Overview and appends Values + methods with value body text", () => {
|
|
const doc = {
|
|
sections: [
|
|
{
|
|
categoryName: "Overview",
|
|
entries: [{ title: "Community", body: "Our river cleanup org." }],
|
|
},
|
|
],
|
|
coreValues: [
|
|
{ chipId: "1", label: "Ecology", meaning: "We protect water.", signals: "Litter = violation." },
|
|
],
|
|
methodSelections: {
|
|
communication: [
|
|
{
|
|
id: "signal",
|
|
label: "Signal",
|
|
sections: {
|
|
corePrinciple: "Privacy first.",
|
|
logisticsAdmin: "Admins rotate.",
|
|
codeOfConduct: "No doxxing.",
|
|
},
|
|
},
|
|
],
|
|
},
|
|
};
|
|
const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
|
|
expect(out.map((s) => s.categoryName)).toEqual(["Values", "Communication"]);
|
|
expect(out[0].entries[0].title).toBe("Ecology");
|
|
expect(out[0].entries[0].body).toBe(
|
|
"We protect water.\n\nLitter = violation.",
|
|
);
|
|
expect(out[0].entries[0].blocks).toBeUndefined();
|
|
expect(out[1].entries[0].title).toBe("Signal");
|
|
expect(out[1].entries[0].blocks?.length).toBeGreaterThanOrEqual(3);
|
|
});
|
|
|
|
it("strips Overview but keeps other categories when both exist", () => {
|
|
const doc = {
|
|
sections: [
|
|
{ categoryName: "Overview", entries: [{ title: "Community", body: "x" }] },
|
|
{ categoryName: "Membership", entries: [{ title: "Open", body: "y" }] },
|
|
],
|
|
};
|
|
const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
|
|
expect(out.map((s) => s.categoryName)).toEqual(["Membership"]);
|
|
});
|
|
|
|
it("prefers document.coreValues over a parallel Values section in document.sections", () => {
|
|
const doc = {
|
|
sections: [
|
|
{
|
|
categoryName: "Values",
|
|
entries: [{ title: "From template", body: "Template body" }],
|
|
},
|
|
],
|
|
coreValues: [
|
|
{ label: "Should not duplicate", meaning: "x", signals: "y" },
|
|
],
|
|
};
|
|
const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
|
|
expect(out.length).toBe(1);
|
|
expect(out[0].categoryName).toBe("Values");
|
|
expect(out[0].entries[0].title).toBe("Should not duplicate");
|
|
expect(out[0].entries[0].body).toBe("x\n\ny");
|
|
});
|
|
|
|
it("enriches empty core value copy from presets (label match)", () => {
|
|
const doc = {
|
|
sections: [],
|
|
coreValues: [
|
|
{ chipId: "", label: "Interdependence", meaning: "", signals: "" },
|
|
],
|
|
};
|
|
const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
|
|
expect(out[0].entries[0].body).toMatch(/survival and success/);
|
|
});
|
|
|
|
it("replaces template placeholder bodies with preset copy, Values first", () => {
|
|
const placeholder =
|
|
"Suggested focus for this governance area. Replace with your own language in the create flow.";
|
|
const doc = {
|
|
sections: [
|
|
{
|
|
categoryName: "Communication",
|
|
entries: [{ title: "Slack", body: placeholder }],
|
|
},
|
|
{
|
|
categoryName: "Values",
|
|
entries: [{ title: "Adaptability", body: placeholder }],
|
|
},
|
|
],
|
|
};
|
|
const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
|
|
expect(out.map((s) => s.categoryName)).toEqual(["Values", "Communication"]);
|
|
expect(out[0].entries[0].body).not.toContain("Suggested focus");
|
|
expect(out[0].entries[0].body.length).toBeGreaterThan(20);
|
|
expect(out[1].entries[0].blocks?.length).toBeGreaterThanOrEqual(1);
|
|
expect(out[1].entries[0].blocks?.[0]?.body?.length).toBeGreaterThan(10);
|
|
});
|
|
|
|
it("matches parseDocumentSectionsForDisplay when no coreValues or methodSelections", () => {
|
|
const doc = {
|
|
sections: [
|
|
{ categoryName: "X", entries: [{ title: "t", body: "b" }] },
|
|
],
|
|
};
|
|
expect(parsePublishedDocumentForCommunityRuleDisplay(doc)).toEqual(
|
|
doc.sections,
|
|
);
|
|
});
|
|
|
|
it("replaces stale document.sections method category with full methodSelections (custom rules)", () => {
|
|
const customId = "b7c0a9f3-0000-4000-8000-000000000001";
|
|
const doc = {
|
|
sections: [
|
|
{
|
|
categoryName: "Communication",
|
|
entries: [
|
|
{
|
|
title: "Slack",
|
|
body: "Only template row; custom card missing from sections.",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
methodSelections: {
|
|
communication: [
|
|
{
|
|
id: "slack",
|
|
label: "Slack",
|
|
sections: {
|
|
corePrinciple: "Slack principle",
|
|
logisticsAdmin: "Slack logistics",
|
|
codeOfConduct: "Slack conduct",
|
|
},
|
|
},
|
|
{
|
|
id: customId,
|
|
label: "My custom comms",
|
|
sections: {
|
|
corePrinciple: "Custom principle",
|
|
logisticsAdmin: "",
|
|
codeOfConduct: "",
|
|
},
|
|
},
|
|
],
|
|
},
|
|
};
|
|
const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
|
|
const comm = out.find((s) => s.categoryName === "Communication");
|
|
expect(comm).toBeDefined();
|
|
expect(comm?.entries.map((e) => e.title)).toEqual([
|
|
"Slack",
|
|
"My custom comms",
|
|
]);
|
|
expect(
|
|
comm?.entries.some(
|
|
(e) => e.title === "My custom comms" && e.blocks?.length,
|
|
),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("includes wizard field blocks when methodSelections preset sections are empty (custom UUID)", () => {
|
|
const customId = "b7c0a9f3-0000-4000-8000-000000000001";
|
|
const doc = {
|
|
sections: [
|
|
{
|
|
categoryName: "Communication",
|
|
entries: [{ title: "Stale template row", body: "ignored after merge" }],
|
|
},
|
|
],
|
|
methodSelections: {
|
|
communication: [
|
|
{
|
|
id: customId,
|
|
label: "Custom method title",
|
|
sections: {
|
|
corePrinciple: "",
|
|
logisticsAdmin: "",
|
|
codeOfConduct: "",
|
|
},
|
|
},
|
|
],
|
|
},
|
|
customMethodCardFieldBlocksById: {
|
|
[customId]: [
|
|
{
|
|
kind: "text" as const,
|
|
id: "f1",
|
|
blockTitle: "Expectations",
|
|
placeholderText: "Answer stored only on field blocks.",
|
|
},
|
|
],
|
|
},
|
|
};
|
|
const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
|
|
const comm = out.find((s) => s.categoryName === "Communication");
|
|
expect(comm?.entries.map((e) => e.title)).toEqual(["Custom method title"]);
|
|
expect(comm?.entries[0]?.blocks).toEqual([
|
|
{ label: "Expectations", body: "Answer stored only on field blocks." },
|
|
]);
|
|
});
|
|
|
|
it("exposes custom upload image blocks with imageUrl for CommunityRule display", () => {
|
|
const customId = "b7c0a9f3-0000-4000-8000-000000000002";
|
|
const doc = {
|
|
sections: [],
|
|
methodSelections: {
|
|
communication: [
|
|
{
|
|
id: customId,
|
|
label: "Policy with photo",
|
|
sections: {
|
|
corePrinciple: "",
|
|
logisticsAdmin: "",
|
|
codeOfConduct: "",
|
|
},
|
|
},
|
|
],
|
|
},
|
|
customMethodCardFieldBlocksById: {
|
|
[customId]: [
|
|
{
|
|
kind: "upload" as const,
|
|
id: "u1",
|
|
blockTitle: "Site photo",
|
|
fileName: "garden.jpg",
|
|
assetUrl: "/api/uploads/11111111-1111-4111-8111-111111111111",
|
|
},
|
|
],
|
|
},
|
|
};
|
|
const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
|
|
const comm = out.find((s) => s.categoryName === "Communication");
|
|
expect(comm?.entries[0]?.blocks).toEqual([
|
|
{
|
|
label: "Site photo",
|
|
body: "",
|
|
imageUrl: "/api/uploads/11111111-1111-4111-8111-111111111111",
|
|
},
|
|
]);
|
|
});
|
|
});
|