diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/autoAnswerableOptions.test.ts b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/autoAnswerableOptions.test.ts index 17dd4d107a..052fe91482 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/autoAnswerableOptions.test.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/__tests__/preview/autoAnswerableOptions.test.ts @@ -1,18 +1,20 @@ import { Store, useStore } from "../../store"; +import { clickContinue } from "../utils"; const { getState, setState } = useStore; -const { resetPreview, autoAnswerableOptions } = getState(); +const { resetPreview, autoAnswerableOptions, computePassport } = getState(); // Find additional auto-answering tests at: // - src/pages/FlowEditor/lib/automations.blanks.test.ts // - src/pages/FlowEditor/lib/automations.parentChild.test.ts // - src/pages/FlowEditor/lib/automations.planningConstraintNots.test.ts +// - src/pages/FlowEditor/lib/automations.setValue.test.ts describe("Returns undefined and does not auto-answer any options", () => { beforeEach(() => { resetPreview(); }); - + test("If the node is not a Question or Checklist type", () => { setState({ flow: { @@ -41,67 +43,346 @@ describe("Returns undefined and does not auto-answer any options", () => { }); test("If we've never seen another node with this `fn` before", () => { - setState({ - flow: singleNodeFlow, - breadcrumbs: {} + setState({ + flow: singleNodeFlow, + breadcrumbs: {} }); - + expect(autoAnswerableOptions("Question")).not.toBeDefined(); }); }); -describe("Questions", () => { - test.todo("Auto-answer the option that exactly matches a passport value"); +describe("Questions and Checklists", () => { + beforeEach(() => { + resetPreview(); + setState({ flow }); + }); + + test("Auto-answer the option that exactly matches a passport value", () => { + clickContinue("InitialChecklistFood", { answers: ["InitialChecklistOptionFruit"], auto: false }); + expect(computePassport()?.data).toEqual({ "foods": ["fruit"] }); - test.todo("Auto-answer the less granular option when there's a single more granular passport value and no more granular options available"); + expect(autoAnswerableOptions("QuestionFruit")).toEqual(["QuestionFruitYesOption"]); + }); - test.todo("Auto-answer the single most granular, left-most option when there are many matching passport values"); + test("Auto-answer the less granular option when there's a single more granular passport value and no more granular options available", () => { + clickContinue("InitialChecklistFood", { answers: ["InitialChecklistOptionFruit"], auto: false }); + expect(computePassport()?.data).toEqual({ "foods": ["fruit"] }); - test.todo("Auto-answer through the blank path when we have seen this node `fn` but there are no matching passport values"); + // Answer a followup question and confirm passport only stores most granular value + clickContinue("QuestionFruitType", { answers: ["OptionFruitTypeRedGrapes"], auto: false }); + expect(computePassport()?.data).toEqual({ "foods": ["fruit.grapes.red"] }); - test.todo("Auto-answer through the blank path when we have not seen this node `fn` but we have seen all possible option `val`"); -}); + expect(autoAnswerableOptions("QuestionFruitTypeLessGranular")).toEqual(["OptionFruitTypeLessGranularGrapes"]); + }); + + test("Puts to user when we have seen this node `fn`, we do not have passport vals, and we have NOT seen all possible option `val`", () => { + clickContinue("InitialChecklistFood", { answers: ["InitialChecklistOptionBlank"], auto: false }); + expect(computePassport()?.data).toEqual({}); -describe("Checklists", () => { - test.todo("Auto-answer all options that exactly match passport values"); + expect(autoAnswerableOptions("QuestionChocolate")).toBeUndefined(); + }); - test.todo("Auto-answer all less granular options when there are more granular passport values and not more granular options available"); + test("Auto-answers when we have seen this node `fn`, we have passport vals but not matching ones, and we have NOT seen all possible option `val`", () => { + clickContinue("InitialChecklistFood", { answers: ["InitialChecklistOptionFruit"], auto: false }); + expect(computePassport()?.data).toEqual({ "foods": ["fruit"] }); - test.todo("Auto-answer through the blank path when we have seen this node `fn` but there are no matching passport values"); + expect(autoAnswerableOptions("QuestionChocolate")).toEqual(["QuestionChocolateOptionBlank"]); + }); - test.todo("Auto-answer through the blank path when we have not seen this node `fn` but we have seen all possible option `val`"); + test.todo("Auto-answer the single most granular, left-most option when there are many matching passport values"); }); +const flow: Store.Flow = { + "_root": { + "edges": [ + "InitialChecklistFood", + "QuestionChocolate", + "QuestionFruit", + "QuestionRyeBread", + "LastChecklistFood" + ] + }, + "OptionFruitTypeGreenGrapes": { + "data": { + "val": "fruit.grapes.green", + "text": "Green grapes" + }, + "type": 200 + }, + "QuestionChocolateOptionYes": { + "data": { + "val": "chocolate", + "text": "Yes" + }, + "type": 200 + }, + "LastChecklistOptionBread": { + "data": { + "val": "bread", + "text": "Bread" + }, + "type": 200 + }, + "InitialChecklistOptionBread": { + "data": { + "val": "bread", + "text": "Bread" + }, + "type": 200, + "edges": [ + "QuestionBreadType" + ] + }, + "QuestionBreadType": { + "data": { + "fn": "foods", + "tags": [], + "text": "Which bread?", + "forceSelection": false + }, + "type": 100, + "edges": [ + "OptionBreadTypeBagel", + "OptionBreadTypeSourdough" + ] + }, + "OptionBreadTypeSourdough": { + "data": { + "val": "bread.sourdough", + "text": "Sourdough" + }, + "type": 200 + }, + "OptionFruitTypeRedGrapes": { + "data": { + "val": "fruit.grapes.red", + "text": "Red grapes" + }, + "type": 200 + }, + "OptionFruitTypeLessGranularBlank": { + "data": { + "text": "Another kind of fruit" + }, + "type": 200 + }, + "OptionBreadTypeBagel": { + "data": { + "val": "bread.bagel", + "text": "Bagel" + }, + "type": 200 + }, + "LastChecklistOptionBlank": { + "data": { + "text": "None" + }, + "type": 200 + }, + "QuestionRyeBread": { + "data": { + "fn": "foods", + "text": "Do you have rye bread?" + }, + "type": 100, + "edges": [ + "OptionRyeBreadYes", + "OptionRyeBreadBlank" + ] + }, + "QuestionFruit": { + "data": { + "fn": "foods", + "text": "Do you have fruit?" + }, + "type": 100, + "edges": [ + "QuestionFruitYesOption", + "QuestionFruitBlankOption" + ] + }, + "LastChecklistOptionFruit": { + "data": { + "val": "fruit", + "text": "Fruit" + }, + "type": 200 + }, + "OptionRyeBreadBlank": { + "data": { + "text": "No" + }, + "type": 200 + }, + "QuestionFruitYesOption": { + "data": { + "val": "fruit", + "text": "Yes" + }, + "type": 200, + "edges": [ + "QuestionFruitTypeLessGranular" + ] + }, + "InitialChecklistFood": { + "data": { + "fn": "foods", + "tags": [], + "text": "Which foods do you want?", + "allRequired": false, + "forceSelection": false + }, + "type": 105, + "edges": [ + "InitialChecklistOptionFruit", + "InitialChecklistOptionBread", + "InitialChecklistOptionBlank" + ] + }, + "OptionRyeBreadYes": { + "data": { + "val": "bread.rye", + "text": "Yes" + }, + "type": 200 + }, + "OptionFruitTypeBanana": { + "data": { + "val": "fruit.bananas", + "text": "Bananas" + }, + "type": 200 + }, + "QuestionChocolateOptionBlank": { + "data": { + "text": "No" + }, + "type": 200 + }, + "LastChecklistFood": { + "data": { + "fn": "foods", + "tags": [], + "text": "Which do you have?", + "allRequired": false + }, + "type": 105, + "edges": [ + "LastChecklistOptionFruit", + "LastChecklistOptionBread", + "LastChecklistOptionChocolate", + "LastChecklistOptionBlank" + ] + }, + "QuestionChocolate": { + "data": { + "fn": "foods", + "tags": [], + "text": "Do you have chocolate?", + "forceSelection": false + }, + "type": 100, + "edges": [ + "QuestionChocolateOptionYes", + "QuestionChocolateOptionBlank" + ] + }, + "LastChecklistOptionChocolate": { + "data": { + "val": "chocolate", + "text": "Chocolate" + }, + "type": 200 + }, + "QuestionFruitBlankOption": { + "data": { + "text": "No" + }, + "type": 200 + }, + "InitialChecklistOptionFruit": { + "data": { + "val": "fruit", + "text": "Fruit" + }, + "type": 200, + "edges": [ + "QuestionFruitType" + ] + }, + "OptionFruitTypeLessGranularGrapes": { + "data": { + "val": "fruit.grapes", + "text": "Grapes" + }, + "type": 200 + }, + "QuestionFruitTypeLessGranular": { + "data": { + "fn": "foods", + "tags": [], + "text": "Which kind of fruit do you have?", + "forceSelection": false + }, + "type": 100, + "edges": [ + "OptionFruitTypeLessGranularGrapes", + "OptionFruitTypeLessGranularBlank" + ] + }, + "InitialChecklistOptionBlank": { + "data": { + "text": "None of these" + }, + "type": 200 + }, + "QuestionFruitType": { + "data": { + "fn": "foods", + "tags": [], + "text": "Which fruit?", + "forceSelection": false + }, + "type": 100, + "edges": [ + "OptionFruitTypeBanana", + "OptionFruitTypeRedGrapes", + "OptionFruitTypeGreenGrapes" + ] + } +}; + const singleNodeFlow: Store.Flow = { "_root": { - "edges": [ - "Question" - ] + "edges": [ + "Question" + ] }, "Question": { - "type": 100, - "data": { - "fn": "direction", - "text": "Which direction?", - "forceSelection": false - }, - "edges": [ - "Option1", - "Option2" - ] + "type": 100, + "data": { + "fn": "direction", + "text": "Which direction?", + "forceSelection": false + }, + "edges": [ + "Option1", + "Option2" + ] }, "Option1": { - "type": 200, - "data": { - "text": "Left", - "val": "left" - } + "type": 200, + "data": { + "text": "Left", + "val": "left" + } }, "Option2": { - "type": 200, - "data": { - "text": "Right", - "val": "right" - } + "type": 200, + "data": { + "text": "Right", + "val": "right" + } } }; \ No newline at end of file