Skip to content

Commit 14fc1de

Browse files
authored
Merge pull request #219 from ONSdigital/EAR-2439-Mutually-Exclusive-Logic-Not-Applied
EAR-2439 mutually exclusive logic not applied when mutually exclusive answer has only one option
2 parents 659b6e8 + da6cbae commit 14fc1de

File tree

6 files changed

+140
-11
lines changed

6 files changed

+140
-11
lines changed

src/eq_schema/builders/basicQuestionnaireJSON.js

+36
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,42 @@ const questionnaireJson = {
9292
},
9393
],
9494
},
95+
{
96+
id: "3",
97+
title: "<p>Section 3</p>",
98+
folders: [
99+
{
100+
id: "folder-3",
101+
enabled: false,
102+
pages: [
103+
{
104+
id: "4",
105+
title: "<p>Page 4</p>",
106+
pageType: "QuestionPage",
107+
routingRuleSet: null,
108+
confirmation: null,
109+
answers: [
110+
{
111+
id: "5",
112+
type: "Number",
113+
label: "Answer 5",
114+
},
115+
{
116+
id: "6",
117+
type: "MutuallyExclusive",
118+
options: [
119+
{
120+
id: "exclusive-option-1",
121+
label: "Not known",
122+
},
123+
],
124+
},
125+
],
126+
},
127+
],
128+
},
129+
],
130+
},
95131
],
96132
};
97133

src/eq_schema/builders/routing2/newRoutingDestination/index.js

+24-9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const { getValueSource } = require("../../valueSource");
66
const { getListFromAll } = require("../../../../utils/functions/listGetters");
77

88
const { flatMap, filter, find } = require("lodash");
9+
const { getAnswerById } = require("../../../../utils/functions/answerGetters");
910

1011
const authorConditions = {
1112
UNANSWERED: "Unanswered",
@@ -122,16 +123,30 @@ const buildAnswerObject = (
122123
return SelectedOptions;
123124
}
124125

125-
if (condition === "OneOf") {
126-
const swapOptionValues = ([optionValues[0], optionValues[1]] = [
127-
optionValues[1],
128-
optionValues[0],
129-
]);
130-
const SelectedOptions = {
131-
[routingConditionConversion(condition)]: swapOptionValues,
132-
};
126+
const leftSideAnswer = getAnswerById(ctx, left.answerId);
133127

134-
return SelectedOptions;
128+
if (condition === "OneOf") {
129+
if (
130+
leftSideAnswer &&
131+
leftSideAnswer.type === "MutuallyExclusive" &&
132+
leftSideAnswer.options.length === 1
133+
) {
134+
const SelectedOptions = {
135+
[routingConditionConversion("AllOf")]: optionValues,
136+
};
137+
138+
return SelectedOptions;
139+
} else {
140+
const swapOptionValues = ([optionValues[0], optionValues[1]] = [
141+
optionValues[1],
142+
optionValues[0],
143+
]);
144+
const SelectedOptions = {
145+
[routingConditionConversion(condition)]: swapOptionValues,
146+
};
147+
148+
return SelectedOptions;
149+
}
135150
}
136151

137152
const SelectedOptions = {

src/eq_schema/builders/routing2/newRoutingDestination/index.test.js

+30
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,36 @@ describe("Should build a runner representation of a binary expression", () => {
181181
});
182182
});
183183

184+
describe("With mutually exclusive answers", () => {
185+
it("should return all of condition for mutually exclusive answers with one option", () => {
186+
const expression = {
187+
left: {
188+
answerId: "6",
189+
type: "Answer",
190+
},
191+
condition: "OneOf",
192+
right: {
193+
type: "SelectedOptions",
194+
optionIds: ["exclusive-option-1"],
195+
},
196+
};
197+
198+
const runnerExpression = checkValidRoutingType(expression, {
199+
questionnaireJson,
200+
});
201+
202+
expect(runnerExpression).toMatchObject({
203+
"all-in": [
204+
["Not known"],
205+
{
206+
identifier: "answer6",
207+
source: "answers",
208+
},
209+
],
210+
});
211+
});
212+
});
213+
184214
describe("With metadata", () => {
185215
describe("Text metadata", () => {
186216
it("should return correct metadata object for text metadata", () => {

src/eq_schema/builders/routing2/translateRoutingDestination/index.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ describe("Translation of a routing destination", () => {
5757
logical: "NextPage",
5858
};
5959
expect(
60-
translateRoutingDestination(authorDestination, "3", { questionnaireJson })
60+
translateRoutingDestination(authorDestination, "4", { questionnaireJson })
6161
).toMatchObject({ group: "confirmation-group" });
6262
});
6363

@@ -66,7 +66,7 @@ describe("Translation of a routing destination", () => {
6666
logical: "NextPage",
6767
};
6868
expect(
69-
translateRoutingDestination(authorDestination, "3", {
69+
translateRoutingDestination(authorDestination, "4", {
7070
questionnaireJson: questionnaireJsonWithSummary,
7171
})
7272
).toMatchObject({ group: "summary-group" });

src/utils/functions/answerGetters.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const { getPages } = require("./pageGetters");
2+
const { flatMap } = require("lodash");
3+
4+
const getAnswerById = (ctx, answerId) => {
5+
const pages = getPages(ctx);
6+
const answers = flatMap(pages, (page) => page.answers);
7+
8+
return answers.find((answer) => answer.id === answerId);
9+
};
10+
11+
module.exports = { getAnswerById };
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const { getAnswerById } = require("./answerGetters");
2+
3+
describe("getAnswerById", () => {
4+
it("should return an answer by id", () => {
5+
const ctx = {
6+
questionnaireJson: {
7+
sections: [
8+
{
9+
folders: [
10+
{
11+
pages: [
12+
{
13+
answers: [
14+
{
15+
id: "1",
16+
label: "Answer 1",
17+
},
18+
{
19+
id: "2",
20+
label: "Answer 2",
21+
},
22+
],
23+
},
24+
],
25+
},
26+
],
27+
},
28+
],
29+
},
30+
};
31+
32+
expect(getAnswerById(ctx, "2")).toMatchObject({
33+
id: "2",
34+
label: "Answer 2",
35+
});
36+
});
37+
});

0 commit comments

Comments
 (0)