Skip to content

Commit

Permalink
planning constraints _nots test suite
Browse files Browse the repository at this point in the history
  • Loading branch information
jessicamcinchak committed Oct 28, 2024
1 parent 9b522e6 commit efe731d
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { Store, useStore } from "../store";
import { clickContinue } from "./utils";

const { getState, setState } = useStore;
const { upcomingCardIds, resetPreview, autoAnswerableOptions, computePassport } = getState();

describe("Auto-answering using planning constraints `_nots`", () => {
beforeEach(() => {
resetPreview();
setState({ flow });
});

test("When there are postive intersecting constraints and `_nots`", () => {
expect(upcomingCardIds()).toEqual(["PlanningConstraints", "ConservationAreaQuestion", "Article4Question", "FloodZone1Question"]);

// Manually proceed forward through PlanningConstraints as if we've checked 4x datasets: Article 4, Conservation Area, Flood Zone 2, Flood Zone 3
clickContinue("PlanningConstraints", {
data: {
"property.constraints.planning": ["article4"],
"_nots": {
"property.constraints.planning": ["designated.conservationArea", "flood.zone.2", "flood.zone.3"]
}
},
auto: false
});

expect(computePassport()?.data).toHaveProperty("property.constraints.planning");
expect(computePassport()?.data).toHaveProperty(["_nots", "property.constraints.planning"]);

// Confirm auto-answer behavior
expect(autoAnswerableOptions("ConservationAreaQuestion")).toEqual(["ConservationAreaNo"]);
expect(autoAnswerableOptions("Article4Question")).toEqual(["Article4Yes"]);
expect(autoAnswerableOptions("FloodZone1Question")).toEqual(["FloodZone1No"]); // Because we have passport vals, follows blank independent of options
});

test("When there are only negative `_nots` constraints", () => {
expect(upcomingCardIds()).toEqual(["PlanningConstraints", "ConservationAreaQuestion", "Article4Question", "FloodZone1Question"]);

// Manually proceed forward through PlanningConstraints as if we've checked 4x datasets: Article 4, Conservation Area, Flood Zone 2, Flood Zone 3
clickContinue("PlanningConstraints", {
data: {
"_nots": {
"property.constraints.planning": ["article4", "designated.conservationArea", "flood.zone.2", "flood.zone.3"]
}
},
auto: false
});

expect(computePassport()?.data).not.toHaveProperty("property.constraints.planning");
expect(computePassport()?.data).toHaveProperty(["_nots", "property.constraints.planning"]);

// Confirm auto-answer behavior
expect(autoAnswerableOptions("ConservationAreaQuestion")).toEqual(["ConservationAreaNo"]);
expect(autoAnswerableOptions("Article4Question")).toEqual(["Article4No"]);
expect(autoAnswerableOptions("FloodZone1Question")).toBeUndefined(); // Because we do not have positive passport vals, puts to user because unseen option
});
});

const flow: Store.Flow = {
"_root": {
"edges": [
"PlanningConstraints",
"ConservationAreaQuestion",
"Article4Question",
"FloodZone1Question" // flood.zone.1 is NOT fetched or set by Planning Data
]
},
"PlanningConstraints": {
"type": 11,
"data": {
"title": "Planning constraints",
"description": "Planning constraints might limit how you can develop or use the property",
"fn": "property.constraints.planning",
"disclaimer": "<p><strong>This page does not include information about historic planning conditions that may apply to this property.</strong></p>"
}
},
"ConservationAreaQuestion": {
"type": 100,
"data": {
"fn": "property.constraints.planning",
"text": "Are you in a conservation area?",
"forceSelection": false,
"tags": []
},
"edges": [
"ConservationAreaYes",
"ConservationAreaNo"
]
},
"ConservationAreaYes": {
"type": 200,
"data": {
"text": "Yes",
"val": "designated.conservationArea"
}
},
"ConservationAreaNo": {
"type": 200,
"data": {
"text": "No"
}
},
"Article4Question": {
"type": 100,
"data": {
"fn": "property.constraints.planning",
"text": "Do any Article 4 directions apply?",
"forceSelection": false
},
"edges": [
"Article4Yes",
"Article4No"
]
},
"Article4Yes": {
"type": 200,
"data": {
"text": "Yes",
"val": "article4"
}
},
"Article4No": {
"type": 200,
"data": {
"text": "No"
}
},
"FloodZone1Question": {
"type": 100,
"data": {
"description": "<p>(This dataset is not fetched or set via Planning Data)</p>",
"fn": "property.constraints.planning",
"text": "Are you in flood zone 1?",
"forceSelection": false
},
"edges": [
"FloodZone1Yes",
"FloodZone1No"
]
},
"FloodZone1Yes": {
"type": 200,
"data": {
"text": "Yes",
"val": "flood.zone.1"
}
},
"FloodZone1No": {
"type": 200,
"data": {
"text": "No"
}
}
};
10 changes: 4 additions & 6 deletions editor.planx.uk/src/pages/FlowEditor/lib/store/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,14 +468,12 @@ export const previewStore: StateCreator<
const blankOption = options.find((option) => !option.data?.val);
let optionsThatCanBeAutoAnswered: Array<NodeId> = [];

// Get existing passport value(s) for this node's fn & proceed if eligible format (eg not numbers via Calculate nodes)
// Get existing passport value(s) for this node's fn
let passportValues = computePassport().data?.[data.fn];
if (typeof passportValues === "number") return;
if (!Array.isArray(passportValues)) passportValues = [passportValues].filter(Boolean).sort();

// If we have an existing passport value for this fn,
// If we have existing passport value(s) for this fn in an eligible automation format (eg not numbers or plain strings),
// then proceed through the matching option(s) or the blank option independent if other vals have been seen before
if (passportValues.length > 0) {
if (Array.isArray(passportValues) && passportValues.length > 0) {
// Check if the existing passport value(s) startsWith at least one option's val (eg passport retains most granular values only)
const matchingPassportValues = passportValues.filter((passportValue: any) =>
sortedOptions.some((option) =>
Expand Down Expand Up @@ -530,7 +528,7 @@ export const previewStore: StateCreator<
optionsThatCanBeAutoAnswered = optionsThatCanBeAutoAnswered.slice(0, 1);
}

return optionsThatCanBeAutoAnswered;
return optionsThatCanBeAutoAnswered.length > 0 ? optionsThatCanBeAutoAnswered : undefined;
},

/**
Expand Down

0 comments on commit efe731d

Please sign in to comment.