Edit flow configured
This commit is contained in:
@@ -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", () => {
|
||||
|
||||
@@ -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",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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"]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user