diff --git a/packages/server/src/automations/tests/executeScript.spec.ts b/packages/server/src/automations/tests/executeScript.spec.ts index fa30e642bc..e9cc389dfe 100644 --- a/packages/server/src/automations/tests/executeScript.spec.ts +++ b/packages/server/src/automations/tests/executeScript.spec.ts @@ -1,50 +1,132 @@ -import { getConfig, afterAll as _afterAll, runStep, actions } from "./utilities" +import { createAutomationBuilder } from "./utilities/AutomationTestBuilder" +import * as automation from "../index" +import * as setup from "./utilities" +import { Table, AutomationStatus } from "@budibase/types" -describe("test the execute script action", () => { - let config = getConfig() +describe("Execute Script Automations", () => { + let config = setup.getConfig(), + table: Table - beforeAll(async () => { + beforeEach(async () => { + await automation.init() await config.init() + table = await config.createTable() + await config.createRow() }) - afterAll(_afterAll) - it("should be able to execute a script", async () => { - const res = await runStep(config, actions.EXECUTE_SCRIPT.stepId, { - code: "return 1 + 1", + afterAll(setup.afterAll) + + it("should execute a basic script and return the result", async () => { + const builder = createAutomationBuilder({ + name: "Basic Script Execution", }) - expect(res.value).toEqual(2) - expect(res.success).toEqual(true) + + const results = await builder + .appAction({ fields: {} }) + .executeScript({ code: "return 2 + 2" }, { stepId: "basic-script-step" }) + .run() + + expect(results.steps[0].outputs.result).toEqual(4) }) - it("should handle a null value", async () => { - const res = await runStep(config, actions.EXECUTE_SCRIPT.stepId, { - code: null, + it("should access bindings from previous steps", async () => { + const builder = createAutomationBuilder({ + name: "Access Bindings", }) - expect(res.response.message).toEqual("Invalid inputs") - expect(res.success).toEqual(false) + + const results = await builder + .appAction({ fields: { data: [1, 2, 3] } }) + .executeScript( + { + code: "return steps['trigger'].fields.data.map(x => x * 2)", + }, + { stepId: "binding-script-step" } + ) + .run() + + expect(results.steps[0].outputs.result).toEqual([2, 4, 6]) }) - it("should be able to get a value from context", async () => { - const res = await runStep( - config, - actions.EXECUTE_SCRIPT.stepId, - { - code: "return steps.map(d => d.value)", - }, - { - steps: [{ value: 0 }, { value: 1 }], - } + it("should handle script execution errors gracefully", async () => { + const builder = createAutomationBuilder({ + name: "Handle Script Errors", + }) + + const results = await builder + .appAction({ fields: {} }) + .executeScript( + { code: "return nonexistentVariable.map(x => x)" }, + { stepId: "error-script-step" } + ) + .run() + + expect(results.steps[0].outputs.error).toContain( + "ReferenceError: nonexistentVariable is not defined" ) - expect(res.value).toEqual([0, 1]) - expect(res.response).toBeUndefined() - expect(res.success).toEqual(true) + expect(results.steps[0].outputs.success).toEqual(false) }) - it("should be able to handle an error gracefully", async () => { - const res = await runStep(config, actions.EXECUTE_SCRIPT.stepId, { - code: "return something.map(x => x.name)", + it("should handle conditional logic in scripts", async () => { + const builder = createAutomationBuilder({ + name: "Conditional Script Logic", }) - expect(res.response).toEqual("ReferenceError: something is not defined") - expect(res.success).toEqual(false) + + const results = await builder + .appAction({ fields: { value: 10 } }) + .executeScript( + { + code: ` + if (steps['trigger'].fields.value > 5) { + return "Value is greater than 5"; + } else { + return "Value is 5 or less"; + } + `, + }, + { stepId: "conditional-logic-step" } + ) + .run() + + expect(results.steps[0].outputs.result).toEqual("Value is greater than 5") + }) + + it("should use multiple steps and validate script execution", async () => { + const builder = createAutomationBuilder({ + name: "Multi-Step Script Execution", + }) + + const results = await builder + .appAction({ fields: {} }) + .serverLog( + { text: "Starting multi-step automation" }, + { stepId: "start-log-step" } + ) + .createRow( + { row: { name: "Test Row", value: 42, tableId: "12345" } }, + { stepId: "create-row-step" } + ) + .executeScript( + { + code: ` + const createdRow = steps['create-row-step'].outputs; + return createdRow.row.value * 2; + `, + }, + { stepId: "script-step" } + ) + .serverLog( + { + text: `Final result is {{ steps['script-step'].outputs.result }}`, + }, + { stepId: "final-log-step" } + ) + .run() + + expect(results.steps[0].outputs.message).toContain( + "Starting multi-step automation" + ) + expect(results.steps[1].outputs.row.value).toEqual(42) + expect(results.steps[2].outputs.result).toEqual(84) + expect(results.steps[3].outputs.message).toContain("Final result is 84") }) }) diff --git a/packages/server/src/automations/tests/utilities/AutomationTestBuilder.ts b/packages/server/src/automations/tests/utilities/AutomationTestBuilder.ts index 76832d6a9a..78830adf2c 100644 --- a/packages/server/src/automations/tests/utilities/AutomationTestBuilder.ts +++ b/packages/server/src/automations/tests/utilities/AutomationTestBuilder.ts @@ -34,6 +34,7 @@ import { SearchFilters, Branch, FilterStepInputs, + ExecuteScriptStepInputs, } from "@budibase/types" import TestConfiguration from "../../../tests/utilities/TestConfiguration" import * as setup from "../utilities" @@ -201,6 +202,18 @@ class BaseStepBuilder { ) } + executeScript( + input: ExecuteScriptStepInputs, + opts?: { stepName?: string; stepId?: string } + ): this { + return this.step( + AutomationActionStepId.EXECUTE_SCRIPT, + BUILTIN_ACTION_DEFINITIONS.EXECUTE_SCRIPT, + input, + opts + ) + } + filter(input: FilterStepInputs): this { return this.step( AutomationActionStepId.FILTER,