Edit flow configured

This commit is contained in:
adilallo
2026-04-29 18:29:16 -06:00
parent 3a9727bceb
commit fc845d8308
39 changed files with 681 additions and 165 deletions
+21 -1
View File
@@ -12,12 +12,22 @@ import {
* window globals. Keeps the test readable vs. threading refs everywhere.
*/
function Harness() {
const { state, updateState, resetCustomRuleSelections } = useCreateFlow();
const {
state,
updateState,
resetCustomRuleSelections,
setMethodSectionsPinCommitted,
} = useCreateFlow();
(window as unknown as { __updateState: typeof updateState }).__updateState =
updateState;
(
window as unknown as { __resetCustomRule: typeof resetCustomRuleSelections }
).__resetCustomRule = resetCustomRuleSelections;
(
window as unknown as {
__setPin: typeof setMethodSectionsPinCommitted;
}
).__setPin = setMethodSectionsPinCommitted;
return (
<>
<div data-testid="title">{state.title ?? ""}</div>
@@ -33,6 +43,9 @@ function Harness() {
<div data-testid="snapshot">
{(state.coreValuesChipsSnapshot ?? []).map((r) => r.id).join(",")}
</div>
<div data-testid="pin-method">
{state.methodSectionsPinCommitted?.communication ? "yes" : "no"}
</div>
</>
);
}
@@ -79,6 +92,12 @@ describe("CreateFlowContext — resetCustomRuleSelections", () => {
"consensus-decision-making",
);
act(() => {
(window as unknown as { __setPin: (s: unknown, v: boolean) => void })
.__setPin("communication", true);
});
expect(screen.getByTestId("pin-method").textContent).toBe("yes");
act(() => {
getResetCustomRule()();
});
@@ -88,6 +107,7 @@ describe("CreateFlowContext — resetCustomRuleSelections", () => {
expect(screen.getByTestId("comm").textContent).toBe("");
expect(screen.getByTestId("details").textContent).toBe("");
expect(screen.getByTestId("snapshot").textContent).toBe("");
expect(screen.getByTestId("pin-method").textContent).toBe("no");
});
it("is a no-op when no custom-rule selections were set", () => {
+12
View File
@@ -205,4 +205,16 @@ describe("Rule Component", () => {
expect(screen.getByText("CE")).toBeInTheDocument();
});
it("shows template recommended tag when collapsed and recommended is true", () => {
render(<Rule {...defaultProps} recommended />);
expect(screen.getByText("RECOMMENDED")).toBeInTheDocument();
});
it("does not show template recommended tag when expanded", () => {
render(<Rule {...defaultProps} recommended expanded categories={[]} />);
expect(screen.queryByText("RECOMMENDED")).not.toBeInTheDocument();
});
});
@@ -0,0 +1,18 @@
import { describe, expect, it } from "vitest";
import { createFlowStepForFacetGroup } from "../../app/(app)/create/utils/facetGroupToCreateFlowStep";
describe("createFlowStepForFacetGroup", () => {
it("maps facet keys to custom-rule URL segments", () => {
expect(createFlowStepForFacetGroup("coreValues")).toBe("core-values");
expect(createFlowStepForFacetGroup("communication")).toBe(
"communication-methods",
);
expect(createFlowStepForFacetGroup("membership")).toBe("membership-methods");
expect(createFlowStepForFacetGroup("decisionApproaches")).toBe(
"decision-approaches",
);
expect(createFlowStepForFacetGroup("conflictManagement")).toBe(
"conflict-management",
);
});
});
+18
View File
@@ -6,6 +6,7 @@ import {
getPreviousStep,
isValidStep,
getStepIndex,
parseReviewReturnSearchParam,
resolveCreateFlowBackTarget,
} from "../../app/(app)/create/utils/flowSteps";
@@ -104,4 +105,21 @@ describe("flowSteps", () => {
"/create/review-template/mutual-aid?fromFlow=1",
);
});
it("parseReviewReturnSearchParam accepts only final-review and edit-rule", () => {
expect(
parseReviewReturnSearchParam(
new URLSearchParams("reviewReturn=final-review"),
),
).toBe("final-review");
expect(
parseReviewReturnSearchParam(
new URLSearchParams("reviewReturn=edit-rule"),
),
).toBe("edit-rule");
expect(
parseReviewReturnSearchParam(new URLSearchParams("reviewReturn=nope")),
).toBeNull();
expect(parseReviewReturnSearchParam(null)).toBeNull();
});
});
+80
View File
@@ -0,0 +1,80 @@
import { describe, it, expect } from "vitest";
import {
mergeCompactCardIdsWithPinnedSelected,
orderRankedMethodsWithPinnedSelection,
} from "../../lib/create/methodCardDisplayOrder";
describe("orderRankedMethodsWithPinnedSelection", () => {
const methods = [
{ id: "a", rank: "top" },
{ id: "b", rank: "mid" },
{ id: "c", rank: "low" },
];
it("returns ranked order when pinning is inactive", () => {
expect(
orderRankedMethodsWithPinnedSelection(methods, ["c", "b"], false),
).toEqual(methods);
});
it("returns ranked order when there are no selections", () => {
expect(orderRankedMethodsWithPinnedSelection(methods, [], true)).toEqual(
methods,
);
});
it("pins selected ids ahead of ranked tail while preserving ranking in each block", () => {
expect(
orderRankedMethodsWithPinnedSelection(methods, ["c", "a"], true),
).toEqual([
{ id: "c", rank: "low" },
{ id: "a", rank: "top" },
{ id: "b", rank: "mid" },
]);
});
it("dedupes repeated ids in the selection list", () => {
expect(
orderRankedMethodsWithPinnedSelection(methods, ["b", "b", "c"], true),
).toEqual([
{ id: "b", rank: "mid" },
{ id: "c", rank: "low" },
{ id: "a", rank: "top" },
]);
});
});
describe("mergeCompactCardIdsWithPinnedSelected", () => {
const showcaseOrder = ["x", "a", "b", "y", "c"];
const baseCompact = ["a", "y", "b"];
it("delegates when pinning is inactive", () => {
expect(
mergeCompactCardIdsWithPinnedSelected(
showcaseOrder,
baseCompact,
["x"],
false,
3,
),
).toEqual(["a", "y", "b"]);
});
it("pads selected-first then facet-derived compact slots", () => {
expect(
mergeCompactCardIdsWithPinnedSelected(
showcaseOrder,
baseCompact,
["c"],
true,
4,
),
).toEqual(["c", "a", "y", "b"]);
});
it("fills remaining compact slots from showcase tail when facets run short", () => {
expect(
mergeCompactCardIdsWithPinnedSelected(showcaseOrder, [], ["x"], true, 3),
).toEqual(["x", "a", "b"]);
});
});