From b21919f9b0e50c7ad351b464a26800bf22b10dec Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Tue, 25 Oct 2022 15:19:07 +0100 Subject: [PATCH] Handle multiple automation loop bindings --- .../SetupPanel/AutomationBlockSetup.svelte | 2 +- .../server/src/automations/automationUtils.js | 34 ++++++++++++------- .../unitTests/automationUtils.spec.js | 17 ++++++++++ 3 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 packages/server/src/automations/unitTests/automationUtils.spec.js diff --git a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte index bb70938dfe..4fd2f40391 100644 --- a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte +++ b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte @@ -120,7 +120,7 @@ allSteps[idx]?.stepId === ActionStepID.LOOP && allSteps.find(x => x.blockToLoop === block.id) - // If the previous block was a loop block, decerement the index so the following + // If the previous block was a loop block, decrement the index so the following // steps are in the correct order if (wasLoopBlock) { loopBlockCount++ diff --git a/packages/server/src/automations/automationUtils.js b/packages/server/src/automations/automationUtils.js index 0646e453c2..493efe34d2 100644 --- a/packages/server/src/automations/automationUtils.js +++ b/packages/server/src/automations/automationUtils.js @@ -82,24 +82,34 @@ exports.getError = err => { } exports.substituteLoopStep = (hbsString, substitute) => { - let blocks = [] let checkForJS = isJSBinding(hbsString) + let substitutedHbsString = "" + let open = checkForJS ? `$("` : "{{" + let closed = checkForJS ? `")` : "}}" if (checkForJS) { hbsString = decodeJSBinding(hbsString) - blocks.push(hbsString) - } else { - blocks = findHBSBlocks(hbsString) } - for (let block of blocks) { - block = block.replace(/loop/, substitute) - if (checkForJS) { - hbsString = encodeJSBinding(block) - } else { - hbsString = block + let pointer = 0, + openPointer = 0, + closedPointer = 0 + while (pointer < hbsString.length) { + openPointer = hbsString.indexOf(open, pointer) + closedPointer = hbsString.indexOf(closed, pointer) + 2 + if (openPointer < 0 || closedPointer < 0) { + substitutedHbsString += hbsString.substring(pointer) + break } + let before = hbsString.substring(pointer, openPointer) + let block = hbsString + .substring(openPointer, closedPointer) + .replace(/loop/, substitute) + substitutedHbsString += before + block + pointer = closedPointer } - - return hbsString + if (checkForJS) { + substitutedHbsString = encodeJSBinding(substitutedHbsString) + } + return substitutedHbsString } exports.stringSplit = value => { diff --git a/packages/server/src/automations/unitTests/automationUtils.spec.js b/packages/server/src/automations/unitTests/automationUtils.spec.js new file mode 100644 index 0000000000..0992bd6eb2 --- /dev/null +++ b/packages/server/src/automations/unitTests/automationUtils.spec.js @@ -0,0 +1,17 @@ +const automationUtils = require("../automationUtils") + +describe("automationUtils", () => { + test("substituteLoopStep should allow multiple loop binding substitutes", () => { + expect(automationUtils.substituteLoopStep( + `{{ loop.currentItem._id }} {{ loop.currentItem._id }} {{ loop.currentItem._id }}`, + "step.2")) + .toBe(`{{ step.2.currentItem._id }} {{ step.2.currentItem._id }} {{ step.2.currentItem._id }}`) + }) + + test("substituteLoopStep should handle not subsituting outside of curly braces", () => { + expect(automationUtils.substituteLoopStep( + `loop {{ loop.currentItem._id }}loop loop{{ loop.currentItem._id }}loop`, + "step.2")) + .toBe(`loop {{ step.2.currentItem._id }}loop loop{{ step.2.currentItem._id }}loop`) + }) +}) \ No newline at end of file