Fix an issue where null values were causing an error in automation loops (#14083)

* fixes an issue where nulls weren't being handled correctly in loops

* remove log

* update recursive gate to be more specific

* use lodash for object check
This commit is contained in:
Peter Clement 2024-07-03 10:07:44 +01:00 committed by GitHub
parent f6360d42c8
commit 9809bf1a91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 105 additions and 1 deletions

View File

@ -1,4 +1,5 @@
import * as automationUtils from "./automationUtils"
import { isPlainObject } from "lodash"
type ObjValue = {
[key: string]: string | ObjValue
@ -18,6 +19,10 @@ function replaceBindingsRecursive(
value: string | ObjValue,
loopStepNumber: number
) {
if (value === null || value === undefined) {
return value
}
if (typeof value === "object") {
for (const [innerKey, innerValue] of Object.entries(value)) {
if (typeof innerValue === "string") {
@ -25,7 +30,11 @@ function replaceBindingsRecursive(
innerValue,
`steps.${loopStepNumber}`
)
} else if (typeof innerValue === "object") {
} else if (
innerValue &&
isPlainObject(innerValue) &&
Object.keys(innerValue).length > 0
) {
value[innerKey] = replaceBindingsRecursive(innerValue, loopStepNumber)
}
}

View File

@ -4,6 +4,7 @@ import { loopAutomation } from "../../tests/utilities/structures"
import { context } from "@budibase/backend-core"
import * as setup from "./utilities"
import { Table } from "@budibase/types"
import * as loopUtils from "../loopUtils"
import { LoopInput, LoopStepType } from "../../definitions/automations"
describe("Attempt to run a basic loop automation", () => {
@ -51,4 +52,98 @@ describe("Attempt to run a basic loop automation", () => {
})
expect(resp.steps[2].outputs.iterations).toBe(1)
})
describe("replaceFakeBindings", () => {
it("should replace loop bindings in nested objects", () => {
const originalStepInput = {
schema: {
name: {
type: "string",
constraints: {
type: "string",
length: { maximum: null },
presence: false,
},
name: "name",
display: { type: "Text" },
},
},
row: {
tableId: "ta_aaad4296e9f74b12b1b90ef7a84afcad",
name: "{{ loop.currentItem.pokemon }}",
},
}
const loopStepNumber = 3
const result = loopUtils.replaceFakeBindings(
originalStepInput,
loopStepNumber
)
expect(result).toEqual({
schema: {
name: {
type: "string",
constraints: {
type: "string",
length: { maximum: null },
presence: false,
},
name: "name",
display: { type: "Text" },
},
},
row: {
tableId: "ta_aaad4296e9f74b12b1b90ef7a84afcad",
name: "{{ steps.3.currentItem.pokemon }}",
},
})
})
it("should handle null values in nested objects", () => {
const originalStepInput = {
nullValue: null,
nestedNull: {
someKey: null,
},
validValue: "{{ loop.someValue }}",
}
const loopStepNumber = 2
const result = loopUtils.replaceFakeBindings(
originalStepInput,
loopStepNumber
)
expect(result).toEqual({
nullValue: null,
nestedNull: {
someKey: null,
},
validValue: "{{ steps.2.someValue }}",
})
})
it("should handle empty objects and arrays", () => {
const originalStepInput = {
emptyObject: {},
emptyArray: [],
nestedEmpty: {
emptyObj: {},
emptyArr: [],
},
}
const loopStepNumber = 1
const result = loopUtils.replaceFakeBindings(
originalStepInput,
loopStepNumber
)
expect(result).toEqual(originalStepInput)
})
})
})