Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Update IndexedNode to always have a parentId property #462

Merged
merged 3 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 1 addition & 64 deletions src/models/session/logic.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import type { OrderedBreadcrumbs, OrderedFlow } from "../../types";
import { ComponentType } from "../../types";
import { findNextNodeOfType, sortBreadcrumbs, sortFlow } from "./logic";
import * as branching from "./mocks/branching-flow";
import { sortBreadcrumbs, sortFlow } from "./logic";
import * as complex from "./mocks/complex-flow-breadcrumbs";
import * as large from "./mocks/large-real-life-flow";
import * as sectioned from "./mocks/section-flow-breadcrumbs";
Expand Down Expand Up @@ -77,67 +75,6 @@ describe("sortBreadcrumbs", () => {
});
});

describe("findNextNodeOfType", () => {
test("it finds the next node in a simple flow", () => {
const nextNode = findNextNodeOfType({
flow: simple.flow,
breadcrumbs: {
firstQuestion: {
auto: false,
answers: ["firstAnswer"],
},
},
componentType: ComponentType.Question,
});
expect(nextNode).toEqual({
id: "secondQuestion",
parentId: "firstQuestion",
type: ComponentType.Question,
edges: ["secondAnswer"],
data: {
text: "Second Question",
},
});
});

test("it finds the next node in a branching flow", () => {
const multiselectChecklistBreadcrumbs = {
Section1: { auto: true },
Question1: { auto: false, answers: ["Question1AnswerA"] },
Section2: { auto: true },
Question2: { auto: false, answers: ["Question2AnswerB"] },
Checklist1: {
auto: false,
answers: ["ChecklistOptionB", "ChecklistOptionC"],
},
};
const nextNoticeNode = findNextNodeOfType({
flow: branching.flow,
breadcrumbs: multiselectChecklistBreadcrumbs,
componentType: ComponentType.Notice,
});
expect(nextNoticeNode).toEqual({
id: "NoticeB",
parentId: "ChecklistOptionB", // this isn't really the parent but the previous node
sectionId: "Section2",
data: { color: "#EFEFEF", title: "Reached B", resetButton: false },
type: ComponentType.Notice,
});
const nextSectionNode = findNextNodeOfType({
flow: branching.flow,
breadcrumbs: multiselectChecklistBreadcrumbs,
componentType: ComponentType.Section,
});
expect(nextSectionNode).toEqual({
id: "Section3",
parentId: "EndOfSection2Notice",
sectionId: "Section3",
data: { title: "Section Three" },
type: ComponentType.Section,
});
});
});

function expectReasonableExecutionTime<T>(fn: () => T, timeout: number): T {
const testStartTime = new Date().getTime();
const out = fn();
Expand Down
49 changes: 7 additions & 42 deletions src/models/session/logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ComponentType } from "../../types";
export function sortFlow(flow: FlowGraph): OrderedFlow {
let sectionId: string | undefined;
const nodes: IndexedNode[] = [];
const searchNodeEdges = (id: string, parentId?: string) => {
const searchNodeEdges = (id: string, parentId: string) => {
// skip already added nodes
if (nodes.map((n) => n.id).includes(id)) return;
const foundNode = flow[id];
Expand All @@ -27,21 +27,21 @@ export function sortFlow(flow: FlowGraph): OrderedFlow {
sectionId = foundNode.type == ComponentType.Section ? id : sectionId;
nodes.push({
id,
parentId: parentId || null,
sectionId,
parentId,
...(sectionId && { sectionId }),
type: foundNode.type!,
edges: foundNode.edges,
...(foundNode.edges && { edges: foundNode.edges }),
data: foundNode.data,
});
foundNode.edges?.forEach((childEdgeId) => {
searchNodeEdges(childEdgeId, id);
});
};
let parentId: string;

flow._root.edges.forEach((rootEdgeId) => {
searchNodeEdges(rootEdgeId, parentId);
parentId = rootEdgeId;
searchNodeEdges(rootEdgeId, "_root");
});

return nodes;
}

Expand Down Expand Up @@ -107,41 +107,6 @@ export function sortBreadcrumbs(
return orderedBreadcrumbs;
}

export function findNextNodeOfType({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function (and associated tests) has been removed as it's not used, and doesn't work as expected.

flow,
breadcrumbs,
componentType,
}: {
flow: FlowGraph;
breadcrumbs: Breadcrumbs;
componentType: ComponentType;
}): IndexedNode | undefined {
const orderedBreadcrumbs = sortBreadcrumbs(flow, breadcrumbs);
const lastCrumb = orderedBreadcrumbs.at(-1)!;
const sortedFlow = sortFlow(flow);
const sortedFlowLastNodeIndex = sortedFlow.findIndex(
(n) => n.id == lastCrumb.id,
);
const truncatedFlow = sortedFlow.slice(sortedFlowLastNodeIndex);

for (const node of truncatedFlow) {
const parentNodeIsLastCrumb = node.parentId === lastCrumb.id;
if (parentNodeIsLastCrumb && node.type === componentType) {
return node;
}
const parentNodeIsCrumbAnswer =
node.parentId &&
lastCrumb.answers &&
lastCrumb.answers.includes(node.parentId!);
if (parentNodeIsCrumbAnswer && node.type === componentType) {
return node;
}
}
// when the above fails, fallback to a naïve scan of matching upcoming nodes
// FIXME: this approach does not respect flow branching logic
return truncatedFlow.find((n) => n.type === componentType);
}

const isSectionNode = (nodeOrCrumb: Node | Crumb): nodeOrCrumb is Node =>
"type" in nodeOrCrumb && nodeOrCrumb.type === ComponentType.Section;

Expand Down
110 changes: 0 additions & 110 deletions src/models/session/mocks/branching-flow.ts

This file was deleted.

12 changes: 6 additions & 6 deletions src/models/session/mocks/complex-flow-breadcrumbs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ export const flow: FlowGraph = {
export const orderedFlow: OrderedFlow = [
{
id: "Imks7j68BD",
parentId: null,
parentId: "_root",
data: {
fn: "item",
text: "shopping trolley",
Expand Down Expand Up @@ -275,7 +275,7 @@ export const orderedFlow: OrderedFlow = [
},
{
id: "HV0gV8DOil",
parentId: "Imks7j68BD",
parentId: "_root",
data: {
fn: "item",
text: "shopping trolley (should be skipped)",
Expand Down Expand Up @@ -322,7 +322,7 @@ export const orderedFlow: OrderedFlow = [
},
{
id: "2PT6bTPTqj",
parentId: "HV0gV8DOil",
parentId: "_root",
data: {
fn: "item",
text: "contains",
Expand Down Expand Up @@ -411,7 +411,7 @@ export const orderedFlow: OrderedFlow = [
},
{
id: "3H2bGdzpIN",
parentId: "2PT6bTPTqj",
parentId: "_root",
data: {
fn: "item",
text: "Does the basket contain apples?",
Expand All @@ -438,7 +438,7 @@ export const orderedFlow: OrderedFlow = [
},
{
id: "AFX3QwbOCd",
parentId: "3H2bGdzpIN",
parentId: "_root",
data: {
fn: "item",
text: "Which does the basket contain?",
Expand Down Expand Up @@ -497,7 +497,7 @@ export const normalizedFlow: NormalizedFlow = [
allRequired: false,
},
type: ComponentType.Checklist,
parentId: null,
parentId: "_root",
rootNodeId: "Imks7j68BD",
edges: ["EqfqaqZ6CH", "I8DznYCKVg", "pXFKKRG6lE", "7tV1uvR9ng"],
},
Expand Down
Loading