Simplify calls to createAutomationBuilder.

This commit is contained in:
Sam Rose 2025-02-05 17:39:38 +00:00
parent d2902464c0
commit d62be2629c
No known key found for this signature in database
24 changed files with 109 additions and 143 deletions

View File

@ -107,10 +107,7 @@ describe("/automations", () => {
}) })
it("Should ensure you can't have a branch as not a last step", async () => { it("Should ensure you can't have a branch as not a last step", async () => {
const automation = createAutomationBuilder({ const automation = createAutomationBuilder(config)
name: "String Equality Branching",
appId: config.getAppId(),
})
.appAction({ fields: { status: "active" } }) .appAction({ fields: { status: "active" } })
.branch({ .branch({
activeBranch: { activeBranch: {
@ -134,10 +131,7 @@ describe("/automations", () => {
}) })
it("Should check validation on an automation that has a branch step with no children", async () => { it("Should check validation on an automation that has a branch step with no children", async () => {
const automation = createAutomationBuilder({ const automation = createAutomationBuilder(config)
name: "String Equality Branching",
appId: config.getAppId(),
})
.appAction({ fields: { status: "active" } }) .appAction({ fields: { status: "active" } })
.branch({}) .branch({})
.serverLog({ text: "Inactive user" }) .serverLog({ text: "Inactive user" })
@ -153,10 +147,7 @@ describe("/automations", () => {
}) })
it("Should check validation on a branch step with empty conditions", async () => { it("Should check validation on a branch step with empty conditions", async () => {
const automation = createAutomationBuilder({ const automation = createAutomationBuilder(config)
name: "String Equality Branching",
appId: config.getAppId(),
})
.appAction({ fields: { status: "active" } }) .appAction({ fields: { status: "active" } })
.branch({ .branch({
activeBranch: { activeBranch: {
@ -177,10 +168,7 @@ describe("/automations", () => {
}) })
it("Should check validation on an branch that has a condition that is not valid", async () => { it("Should check validation on an branch that has a condition that is not valid", async () => {
const automation = createAutomationBuilder({ const automation = createAutomationBuilder(config)
name: "String Equality Branching",
appId: config.getAppId(),
})
.appAction({ fields: { status: "active" } }) .appAction({ fields: { status: "active" } })
.branch({ .branch({
activeBranch: { activeBranch: {
@ -252,11 +240,7 @@ describe("/automations", () => {
}) })
it("should be able to access platformUrl, logoUrl and company in the automation", async () => { it("should be able to access platformUrl, logoUrl and company in the automation", async () => {
const result = await createAutomationBuilder({ const result = await createAutomationBuilder(config)
name: "Test Automation",
appId: config.getAppId(),
config,
})
.serverLog({ .serverLog({
text: "{{ settings.url }}", text: "{{ settings.url }}",
}) })

View File

@ -24,7 +24,7 @@ describe("Branching automations", () => {
const branch2LogId = "33333333-3333-3333-3333-333333333333" const branch2LogId = "33333333-3333-3333-3333-333333333333"
const branch2Id = "44444444-4444-4444-4444-444444444444" const branch2Id = "44444444-4444-4444-4444-444444444444"
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.serverLog( .serverLog(
{ text: "Starting automation" }, { text: "Starting automation" },
{ stepName: "FirstLog", stepId: firstLogId } { stepName: "FirstLog", stepId: firstLogId }
@ -82,7 +82,7 @@ describe("Branching automations", () => {
}) })
it("should execute correct branch based on string equality", async () => { it("should execute correct branch based on string equality", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.appAction({ fields: { status: "active" } }) .appAction({ fields: { status: "active" } })
.branch({ .branch({
activeBranch: { activeBranch: {
@ -107,7 +107,7 @@ describe("Branching automations", () => {
}) })
it("should handle multiple conditions with AND operator", async () => { it("should handle multiple conditions with AND operator", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.appAction({ fields: { status: "active", role: "admin" } }) .appAction({ fields: { status: "active", role: "admin" } })
.branch({ .branch({
activeAdminBranch: { activeAdminBranch: {
@ -135,7 +135,7 @@ describe("Branching automations", () => {
}) })
it("should handle multiple conditions with OR operator", async () => { it("should handle multiple conditions with OR operator", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.appAction({ fields: { status: "test", role: "user" } }) .appAction({ fields: { status: "test", role: "user" } })
.branch({ .branch({
specialBranch: { specialBranch: {
@ -167,7 +167,7 @@ describe("Branching automations", () => {
}) })
it("should stop the branch automation when no conditions are met", async () => { it("should stop the branch automation when no conditions are met", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.appAction({ fields: { status: "test", role: "user" } }) .appAction({ fields: { status: "test", role: "user" } })
.createRow({ row: { name: "Test", tableId: table._id } }) .createRow({ row: { name: "Test", tableId: table._id } })
.branch({ .branch({
@ -203,7 +203,7 @@ describe("Branching automations", () => {
}) })
it("evaluate multiple conditions", async () => { it("evaluate multiple conditions", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.appAction({ fields: { test_trigger: true } }) .appAction({ fields: { test_trigger: true } })
.serverLog({ text: "Starting automation" }, { stepId: "aN6znRYHG" }) .serverLog({ text: "Starting automation" }, { stepId: "aN6znRYHG" })
.branch({ .branch({
@ -244,7 +244,7 @@ describe("Branching automations", () => {
}) })
it("evaluate multiple conditions with interpolated text", async () => { it("evaluate multiple conditions with interpolated text", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.appAction({ fields: { test_trigger: true } }) .appAction({ fields: { test_trigger: true } })
.serverLog({ text: "Starting automation" }, { stepId: "aN6znRYHG" }) .serverLog({ text: "Starting automation" }, { stepId: "aN6znRYHG" })
.branch({ .branch({

View File

@ -29,7 +29,7 @@ describe("Automation Scenarios", () => {
it("should trigger an automation which then creates a row", async () => { it("should trigger an automation which then creates a row", async () => {
const table = await config.api.table.save(basicTable()) const table = await config.api.table.save(basicTable())
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.rowUpdated( .rowUpdated(
{ tableId: table._id! }, { tableId: table._id! },
{ {
@ -65,7 +65,7 @@ describe("Automation Scenarios", () => {
} }
await config.api.row.save(table._id!, row) await config.api.row.save(table._id!, row)
await config.api.row.save(table._id!, row) await config.api.row.save(table._id!, row)
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.queryRows({ .queryRows({
tableId: table._id!, tableId: table._id!,
}) })
@ -83,7 +83,7 @@ describe("Automation Scenarios", () => {
} }
await config.api.row.save(table._id!, row) await config.api.row.save(table._id!, row)
await config.api.row.save(table._id!, row) await config.api.row.save(table._id!, row)
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.queryRows({ .queryRows({
tableId: table._id!, tableId: table._id!,
}) })
@ -124,7 +124,7 @@ describe("Automation Scenarios", () => {
}, },
}) })
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.createRow( .createRow(
{ {
row: { row: {
@ -192,7 +192,7 @@ describe("Automation Scenarios", () => {
} }
await config.api.row.save(table._id!, row) await config.api.row.save(table._id!, row)
await config.api.row.save(table._id!, row) await config.api.row.save(table._id!, row)
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.queryRows( .queryRows(
{ {
tableId: table._id!, tableId: table._id!,
@ -241,7 +241,7 @@ describe("Automation Scenarios", () => {
}) })
it("should stop an automation if the condition is not met", async () => { it("should stop an automation if the condition is not met", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.createRow({ .createRow({
row: { row: {
name: "Equal Test", name: "Equal Test",
@ -266,7 +266,7 @@ describe("Automation Scenarios", () => {
}) })
it("should continue the automation if the condition is met", async () => { it("should continue the automation if the condition is met", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.createRow({ .createRow({
row: { row: {
name: "Not Equal Test", name: "Not Equal Test",
@ -332,7 +332,7 @@ describe("Automation Scenarios", () => {
it.each(testCases)( it.each(testCases)(
"should pass the filter when condition is $condition", "should pass the filter when condition is $condition",
async ({ condition, value, rowValue, expectPass }) => { async ({ condition, value, rowValue, expectPass }) => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.createRow({ .createRow({
row: { row: {
name: `${condition} Test`, name: `${condition} Test`,
@ -366,7 +366,7 @@ describe("Automation Scenarios", () => {
it("Check user is passed through from row trigger", async () => { it("Check user is passed through from row trigger", async () => {
const table = await config.api.table.save(basicTable()) const table = await config.api.table.save(basicTable())
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.rowUpdated( .rowUpdated(
{ tableId: table._id! }, { tableId: table._id! },
{ {
@ -381,7 +381,7 @@ describe("Automation Scenarios", () => {
}) })
it("Check user is passed through from app trigger", async () => { it("Check user is passed through from app trigger", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.serverLog({ text: "{{ [user].[email] }}" }) .serverLog({ text: "{{ [user].[email] }}" })
.run() .run()
@ -452,7 +452,7 @@ if (descriptions.length) {
queryVerb: "read", queryVerb: "read",
}) })
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.appAction({ .appAction({
fields: {}, fields: {},
}) })

View File

@ -24,7 +24,7 @@ describe("Execute Bash Automations", () => {
}) })
it("should use trigger data in bash command and pass output to subsequent steps", async () => { it("should use trigger data in bash command and pass output to subsequent steps", async () => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.appAction({ fields: { command: "hello world" } }) .appAction({ fields: { command: "hello world" } })
.bash( .bash(
{ code: "echo '{{ trigger.fields.command }}'" }, { code: "echo '{{ trigger.fields.command }}'" },
@ -43,7 +43,7 @@ describe("Execute Bash Automations", () => {
}) })
it("should chain multiple bash commands using previous outputs", async () => { it("should chain multiple bash commands using previous outputs", async () => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.appAction({ fields: { filename: "testfile.txt" } }) .appAction({ fields: { filename: "testfile.txt" } })
.bash( .bash(
{ code: "echo 'initial content' > {{ trigger.fields.filename }}" }, { code: "echo 'initial content' > {{ trigger.fields.filename }}" },
@ -64,7 +64,7 @@ describe("Execute Bash Automations", () => {
}) })
it("should integrate bash output with row operations", async () => { it("should integrate bash output with row operations", async () => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.queryRows( .queryRows(
{ {
tableId: table._id!, tableId: table._id!,
@ -93,7 +93,7 @@ describe("Execute Bash Automations", () => {
}) })
it("should handle bash output in conditional logic", async () => { it("should handle bash output in conditional logic", async () => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.appAction({ fields: { threshold: "5" } }) .appAction({ fields: { threshold: "5" } })
.bash( .bash(
{ code: "echo $(( {{ trigger.fields.threshold }} + 5 ))" }, { code: "echo $(( {{ trigger.fields.threshold }} + 5 ))" },
@ -120,7 +120,7 @@ describe("Execute Bash Automations", () => {
}) })
it("should handle null values gracefully", async () => { it("should handle null values gracefully", async () => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.bash( .bash(
// @ts-expect-error - testing null input // @ts-expect-error - testing null input
{ code: null }, { code: null },

View File

@ -40,7 +40,7 @@ describe("test the create row action", () => {
}) })
it("should be able to run the action", async () => { it("should be able to run the action", async () => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.appAction({ fields: { status: "new" } }) .appAction({ fields: { status: "new" } })
.serverLog({ text: "Starting create row flow" }, { stepName: "StartLog" }) .serverLog({ text: "Starting create row flow" }, { stepName: "StartLog" })
.createRow({ row }, { stepName: "CreateRow" }) .createRow({ row }, { stepName: "CreateRow" })
@ -66,7 +66,7 @@ describe("test the create row action", () => {
}) })
it("should return an error (not throw) when bad info provided", async () => { it("should return an error (not throw) when bad info provided", async () => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.appAction({ fields: { status: "error" } }) .appAction({ fields: { status: "error" } })
.serverLog({ text: "Starting error test flow" }, { stepName: "StartLog" }) .serverLog({ text: "Starting error test flow" }, { stepName: "StartLog" })
.createRow( .createRow(
@ -84,7 +84,7 @@ describe("test the create row action", () => {
}) })
it("should check invalid inputs return an error", async () => { it("should check invalid inputs return an error", async () => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.appAction({ fields: { status: "invalid" } }) .appAction({ fields: { status: "invalid" } })
.serverLog({ text: "Testing invalid input" }, { stepName: "StartLog" }) .serverLog({ text: "Testing invalid input" }, { stepName: "StartLog" })
.createRow({ row: {} }, { stepName: "CreateRow" }) .createRow({ row: {} }, { stepName: "CreateRow" })
@ -122,7 +122,7 @@ describe("test the create row action", () => {
] ]
attachmentRow.file_attachment = attachmentObject attachmentRow.file_attachment = attachmentObject
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.appAction({ fields: { type: "attachment" } }) .appAction({ fields: { type: "attachment" } })
.serverLog( .serverLog(
{ text: "Processing attachment upload" }, { text: "Processing attachment upload" },
@ -173,7 +173,7 @@ describe("test the create row action", () => {
} }
attachmentRow.single_file_attachment = attachmentObject attachmentRow.single_file_attachment = attachmentObject
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.appAction({ fields: { type: "single-attachment" } }) .appAction({ fields: { type: "single-attachment" } })
.serverLog( .serverLog(
{ text: "Processing single attachment" }, { text: "Processing single attachment" },
@ -244,7 +244,7 @@ describe("test the create row action", () => {
} }
attachmentRow.single_file_attachment = attachmentObject attachmentRow.single_file_attachment = attachmentObject
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.appAction({ fields: { type: "invalid-attachment" } }) .appAction({ fields: { type: "invalid-attachment" } })
.serverLog( .serverLog(
{ text: "Testing invalid attachment keys" }, { text: "Testing invalid attachment keys" },

View File

@ -27,7 +27,7 @@ describe("cron automations", () => {
}) })
it("should initialise the automation timestamp", async () => { it("should initialise the automation timestamp", async () => {
await createAutomationBuilder({ config }).cron({ cron: "* * * * *" }).save() await createAutomationBuilder(config).cron({ cron: "* * * * *" }).save()
tk.travel(Date.now() + oneMinuteInMs) tk.travel(Date.now() + oneMinuteInMs)
await config.publish() await config.publish()

View File

@ -16,7 +16,7 @@ describe("test the delay logic", () => {
const time = 100 const time = 100
const before = performance.now() const before = performance.now()
await createAutomationBuilder({ config }).delay({ time }).run() await createAutomationBuilder(config).delay({ time }).run()
const now = performance.now() const now = performance.now()

View File

@ -20,7 +20,7 @@ describe("test the delete row action", () => {
}) })
it("should be able to run the delete row action", async () => { it("should be able to run the delete row action", async () => {
await createAutomationBuilder({ config }) await createAutomationBuilder(config)
.deleteRow({ .deleteRow({
tableId: table._id!, tableId: table._id!,
id: row._id!, id: row._id!,
@ -34,7 +34,7 @@ describe("test the delete row action", () => {
}) })
it("should check invalid inputs return an error", async () => { it("should check invalid inputs return an error", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.deleteRow({ tableId: "", id: "", revision: "" }) .deleteRow({ tableId: "", id: "", revision: "" })
.run() .run()
@ -42,7 +42,7 @@ describe("test the delete row action", () => {
}) })
it("should return an error when table doesn't exist", async () => { it("should return an error when table doesn't exist", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.deleteRow({ .deleteRow({
tableId: "invalid", tableId: "invalid",
id: "invalid", id: "invalid",

View File

@ -19,7 +19,7 @@ describe("test the outgoing webhook action", () => {
it("should be able to run the action", async () => { it("should be able to run the action", async () => {
nock("http://www.example.com/").post("/").reply(200, { foo: "bar" }) nock("http://www.example.com/").post("/").reply(200, { foo: "bar" })
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.discord({ .discord({
url: "http://www.example.com", url: "http://www.example.com",
username: "joe_bloggs", username: "joe_bloggs",

View File

@ -20,7 +20,7 @@ describe("Execute Script Automations", () => {
}) })
it("should execute a basic script and return the result", async () => { it("should execute a basic script and return the result", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.executeScript({ code: "return 2 + 2" }) .executeScript({ code: "return 2 + 2" })
.run() .run()
@ -28,7 +28,7 @@ describe("Execute Script Automations", () => {
}) })
it("should access bindings from previous steps", async () => { it("should access bindings from previous steps", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.appAction({ fields: { data: [1, 2, 3] } }) .appAction({ fields: { data: [1, 2, 3] } })
.executeScript( .executeScript(
{ {
@ -42,7 +42,7 @@ describe("Execute Script Automations", () => {
}) })
it("should handle script execution errors gracefully", async () => { it("should handle script execution errors gracefully", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.executeScript({ code: "return nonexistentVariable.map(x => x)" }) .executeScript({ code: "return nonexistentVariable.map(x => x)" })
.run() .run()
@ -53,7 +53,7 @@ describe("Execute Script Automations", () => {
}) })
it("should handle conditional logic in scripts", async () => { it("should handle conditional logic in scripts", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.appAction({ fields: { value: 10 } }) .appAction({ fields: { value: 10 } })
.executeScript({ .executeScript({
code: ` code: `
@ -70,7 +70,8 @@ describe("Execute Script Automations", () => {
}) })
it("should use multiple steps and validate script execution", async () => { it("should use multiple steps and validate script execution", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.appAction({ fields: {} })
.serverLog( .serverLog(
{ text: "Starting multi-step automation" }, { text: "Starting multi-step automation" },
{ stepId: "start-log-step" } { stepId: "start-log-step" }

View File

@ -42,7 +42,7 @@ describe("test the filter logic", () => {
[new Date().toISOString(), ">", new Date(-10000).toISOString()], [new Date().toISOString(), ">", new Date(-10000).toISOString()],
] ]
it.each(pass)("should pass %p %p %p", async (field, condition, value) => { it.each(pass)("should pass %p %p %p", async (field, condition, value) => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.filter({ field, condition: stringToFilterCondition(condition), value }) .filter({ field, condition: stringToFilterCondition(condition), value })
.run() .run()
@ -59,7 +59,7 @@ describe("test the filter logic", () => {
[{}, "==", {}], [{}, "==", {}],
] ]
it.each(fail)("should fail %p %p %p", async (field, condition, value) => { it.each(fail)("should fail %p %p %p", async (field, condition, value) => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.filter({ field, condition: stringToFilterCondition(condition), value }) .filter({ field, condition: stringToFilterCondition(condition), value })
.run() .run()

View File

@ -72,7 +72,7 @@ describe("Attempt to run a basic loop automation", () => {
}) })
it("should run an automation with a trigger, loop, and create row step", async () => { it("should run an automation with a trigger, loop, and create row step", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.rowSaved( .rowSaved(
{ tableId: table._id! }, { tableId: table._id! },
{ {
@ -115,7 +115,7 @@ describe("Attempt to run a basic loop automation", () => {
}) })
it("should run an automation where a loop step is between two normal steps to ensure context correctness", async () => { it("should run an automation where a loop step is between two normal steps to ensure context correctness", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.rowSaved( .rowSaved(
{ tableId: table._id! }, { tableId: table._id! },
{ {
@ -151,7 +151,7 @@ describe("Attempt to run a basic loop automation", () => {
}) })
it("if an incorrect type is passed to the loop it should return an error", async () => { it("if an incorrect type is passed to the loop it should return an error", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.loop({ .loop({
option: LoopStepType.ARRAY, option: LoopStepType.ARRAY,
binding: "1, 2, 3", binding: "1, 2, 3",
@ -166,7 +166,7 @@ describe("Attempt to run a basic loop automation", () => {
}) })
it("ensure the loop stops if the failure condition is reached", async () => { it("ensure the loop stops if the failure condition is reached", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.loop({ .loop({
option: LoopStepType.ARRAY, option: LoopStepType.ARRAY,
binding: ["test", "test2", "test3"], binding: ["test", "test2", "test3"],
@ -184,7 +184,7 @@ describe("Attempt to run a basic loop automation", () => {
}) })
it("ensure the loop stops if the max iterations are reached", async () => { it("ensure the loop stops if the max iterations are reached", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.loop({ .loop({
option: LoopStepType.ARRAY, option: LoopStepType.ARRAY,
binding: ["test", "test2", "test3"], binding: ["test", "test2", "test3"],
@ -198,7 +198,7 @@ describe("Attempt to run a basic loop automation", () => {
}) })
it("should run an automation with loop and max iterations to ensure context correctness further down the tree", async () => { it("should run an automation with loop and max iterations to ensure context correctness further down the tree", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.loop({ .loop({
option: LoopStepType.ARRAY, option: LoopStepType.ARRAY,
binding: ["test", "test2", "test3"], binding: ["test", "test2", "test3"],
@ -212,7 +212,7 @@ describe("Attempt to run a basic loop automation", () => {
}) })
it("should run an automation where a loop is successfully run twice", async () => { it("should run an automation where a loop is successfully run twice", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.rowSaved( .rowSaved(
{ tableId: table._id! }, { tableId: table._id! },
{ {
@ -274,7 +274,7 @@ describe("Attempt to run a basic loop automation", () => {
}) })
it("should run an automation where a loop is used twice to ensure context correctness further down the tree", async () => { it("should run an automation where a loop is used twice to ensure context correctness further down the tree", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.loop({ .loop({
option: LoopStepType.ARRAY, option: LoopStepType.ARRAY,
binding: [1, 2, 3], binding: [1, 2, 3],
@ -295,7 +295,7 @@ describe("Attempt to run a basic loop automation", () => {
}) })
it("should use automation names to loop with", async () => { it("should use automation names to loop with", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.loop( .loop(
{ {
option: LoopStepType.ARRAY, option: LoopStepType.ARRAY,
@ -346,7 +346,7 @@ describe("Attempt to run a basic loop automation", () => {
await config.api.row.bulkImport(table._id!, { rows }) await config.api.row.bulkImport(table._id!, { rows })
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.queryRows({ .queryRows({
tableId: table._id!, tableId: table._id!,
}) })
@ -425,7 +425,7 @@ describe("Attempt to run a basic loop automation", () => {
await config.api.row.bulkImport(table._id!, { rows }) await config.api.row.bulkImport(table._id!, { rows })
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.queryRows( .queryRows(
{ {
tableId: table._id!, tableId: table._id!,
@ -507,7 +507,7 @@ describe("Attempt to run a basic loop automation", () => {
await config.api.row.bulkImport(table._id!, { rows }) await config.api.row.bulkImport(table._id!, { rows })
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.queryRows({ .queryRows({
tableId: table._id!, tableId: table._id!,
}) })

View File

@ -19,7 +19,7 @@ describe("test the outgoing webhook action", () => {
it("should be able to run the action", async () => { it("should be able to run the action", async () => {
nock("http://www.example.com/").post("/").reply(200, { foo: "bar" }) nock("http://www.example.com/").post("/").reply(200, { foo: "bar" })
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.make({ .make({
url: "http://www.example.com", url: "http://www.example.com",
body: null, body: null,
@ -45,7 +45,7 @@ describe("test the outgoing webhook action", () => {
.post("/", payload) .post("/", payload)
.reply(200, { foo: "bar" }) .reply(200, { foo: "bar" })
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.make({ .make({
body: { value: JSON.stringify(payload) }, body: { value: JSON.stringify(payload) },
url: "http://www.example.com", url: "http://www.example.com",
@ -57,7 +57,7 @@ describe("test the outgoing webhook action", () => {
}) })
it("should return a 400 if the JSON payload string is malformed", async () => { it("should return a 400 if the JSON payload string is malformed", async () => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.make({ .make({
body: { value: "{ invalid json }" }, body: { value: "{ invalid json }" },
url: "http://www.example.com", url: "http://www.example.com",

View File

@ -20,7 +20,7 @@ describe("test the outgoing webhook action", () => {
it("should be able to run the action and default to 'get'", async () => { it("should be able to run the action and default to 'get'", async () => {
nock("http://www.example.com/").get("/").reply(200, { foo: "bar" }) nock("http://www.example.com/").get("/").reply(200, { foo: "bar" })
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.n8n({ .n8n({
url: "http://www.example.com", url: "http://www.example.com",
body: { test: "IGNORE_ME" }, body: { test: "IGNORE_ME" },
@ -38,7 +38,7 @@ describe("test the outgoing webhook action", () => {
.post("/", { name: "Adam", age: 9 }) .post("/", { name: "Adam", age: 9 })
.reply(200) .reply(200)
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.n8n({ .n8n({
url: "http://www.example.com", url: "http://www.example.com",
body: { value: JSON.stringify({ name: "Adam", age: 9 }) }, body: { value: JSON.stringify({ name: "Adam", age: 9 }) },
@ -51,7 +51,7 @@ describe("test the outgoing webhook action", () => {
}) })
it("should return a 400 if the JSON payload string is malformed", async () => { it("should return a 400 if the JSON payload string is malformed", async () => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.n8n({ .n8n({
url: "http://www.example.com", url: "http://www.example.com",
body: { value: "{ value1 1 }" }, body: { value: "{ value1 1 }" },
@ -70,7 +70,7 @@ describe("test the outgoing webhook action", () => {
.head("/", body => body === "") .head("/", body => body === "")
.reply(200) .reply(200)
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.n8n({ .n8n({
url: "http://www.example.com", url: "http://www.example.com",
method: HttpMethod.HEAD, method: HttpMethod.HEAD,

View File

@ -57,7 +57,7 @@ describe("test the openai action", () => {
// means it goes through the "legacy" path which requires you to set your // means it goes through the "legacy" path which requires you to set your
// own API key. We don't count this against your quota. // own API key. We don't count this against your quota.
const result = await expectAIUsage(0, () => const result = await expectAIUsage(0, () =>
createAutomationBuilder({ config }) createAutomationBuilder(config)
.openai({ prompt: "Hello, world", model: Model.GPT_4O_MINI }) .openai({ prompt: "Hello, world", model: Model.GPT_4O_MINI })
.run() .run()
) )
@ -68,7 +68,7 @@ describe("test the openai action", () => {
it("should present the correct error message when a prompt is not provided", async () => { it("should present the correct error message when a prompt is not provided", async () => {
const result = await expectAIUsage(0, () => const result = await expectAIUsage(0, () =>
createAutomationBuilder({ config }) createAutomationBuilder(config)
.openai({ prompt: "", model: Model.GPT_4O_MINI }) .openai({ prompt: "", model: Model.GPT_4O_MINI })
.run() .run()
) )
@ -83,7 +83,7 @@ describe("test the openai action", () => {
mockChatGPTError() mockChatGPTError()
const result = await expectAIUsage(0, () => const result = await expectAIUsage(0, () =>
createAutomationBuilder({ config }) createAutomationBuilder(config)
.openai({ prompt: "Hello, world", model: Model.GPT_4O_MINI }) .openai({ prompt: "Hello, world", model: Model.GPT_4O_MINI })
.run() .run()
) )
@ -105,7 +105,7 @@ describe("test the openai action", () => {
// calculation we use to approximate cost. This uses Budibase's OpenAI API // calculation we use to approximate cost. This uses Budibase's OpenAI API
// key, so we charge users for it. // key, so we charge users for it.
const result = await expectAIUsage(14, () => const result = await expectAIUsage(14, () =>
createAutomationBuilder({ config }) createAutomationBuilder(config)
.openai({ model: Model.GPT_4O_MINI, prompt: "Hello, world" }) .openai({ model: Model.GPT_4O_MINI, prompt: "Hello, world" })
.run() .run()
) )

View File

@ -23,7 +23,7 @@ describe("test the outgoing webhook action", () => {
.post("/", { a: 1 }) .post("/", { a: 1 })
.reply(200, { foo: "bar" }) .reply(200, { foo: "bar" })
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.outgoingWebhook({ .outgoingWebhook({
requestMethod: RequestType.POST, requestMethod: RequestType.POST,
url: "http://www.example.com", url: "http://www.example.com",
@ -38,7 +38,7 @@ describe("test the outgoing webhook action", () => {
}) })
it("should return an error if something goes wrong in fetch", async () => { it("should return an error if something goes wrong in fetch", async () => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.outgoingWebhook({ .outgoingWebhook({
requestMethod: RequestType.GET, requestMethod: RequestType.GET,
url: "www.invalid.com", url: "www.invalid.com",

View File

@ -28,10 +28,7 @@ describe("Test a query step automation", () => {
}) })
it("should be able to run the query step", async () => { it("should be able to run the query step", async () => {
const result = await createAutomationBuilder({ const result = await createAutomationBuilder(config)
name: "Basic Query Test",
config,
})
.queryRows( .queryRows(
{ {
tableId: table._id!, tableId: table._id!,
@ -55,10 +52,7 @@ describe("Test a query step automation", () => {
}) })
it("Returns all rows when onEmptyFilter has no value and no filters are passed", async () => { it("Returns all rows when onEmptyFilter has no value and no filters are passed", async () => {
const result = await createAutomationBuilder({ const result = await createAutomationBuilder(config)
name: "Empty Filter Test",
config,
})
.queryRows( .queryRows(
{ {
tableId: table._id!, tableId: table._id!,
@ -78,10 +72,7 @@ describe("Test a query step automation", () => {
}) })
it("Returns no rows when onEmptyFilter is RETURN_NONE and theres no filters", async () => { it("Returns no rows when onEmptyFilter is RETURN_NONE and theres no filters", async () => {
const result = await createAutomationBuilder({ const result = await createAutomationBuilder(config)
name: "Return None Test",
config,
})
.queryRows( .queryRows(
{ {
tableId: table._id!, tableId: table._id!,
@ -102,10 +93,7 @@ describe("Test a query step automation", () => {
}) })
it("Returns no rows when onEmptyFilters RETURN_NONE and a filter is passed with a null value", async () => { it("Returns no rows when onEmptyFilters RETURN_NONE and a filter is passed with a null value", async () => {
const result = await createAutomationBuilder({ const result = await createAutomationBuilder(config)
name: "Null Filter Test",
config,
})
.queryRows( .queryRows(
{ {
tableId: table._id!, tableId: table._id!,
@ -130,10 +118,7 @@ describe("Test a query step automation", () => {
}) })
it("Returns rows when onEmptyFilter is RETURN_ALL and no filter is passed", async () => { it("Returns rows when onEmptyFilter is RETURN_ALL and no filter is passed", async () => {
const result = await createAutomationBuilder({ const result = await createAutomationBuilder(config)
name: "Return All Test",
config,
})
.queryRows( .queryRows(
{ {
tableId: table._id!, tableId: table._id!,
@ -160,10 +145,7 @@ describe("Test a query step automation", () => {
await config.api.row.save(tableWithSpaces._id!, { await config.api.row.save(tableWithSpaces._id!, {
name: NAME, name: NAME,
}) })
const result = await createAutomationBuilder({ const result = await createAutomationBuilder(config)
name: "Return All Test",
config,
})
.queryRows( .queryRows(
{ {
tableId: tableWithSpaces._id!, tableId: tableWithSpaces._id!,

View File

@ -13,7 +13,7 @@ describe("test the server log action", () => {
}) })
it("should be able to log the text", async () => { it("should be able to log the text", async () => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.serverLog({ text: "Hello World" }) .serverLog({ text: "Hello World" })
.run() .run()
expect(result.steps[0].outputs.message).toEqual( expect(result.steps[0].outputs.message).toEqual(

View File

@ -17,11 +17,11 @@ describe("Test triggering an automation from another automation", () => {
}) })
it("should trigger an other server log automation", async () => { it("should trigger an other server log automation", async () => {
const automation = await createAutomationBuilder({ config }) const automation = await createAutomationBuilder(config)
.serverLog({ text: "Hello World" }) .serverLog({ text: "Hello World" })
.save() .save()
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.triggerAutomationRun({ .triggerAutomationRun({
automation: { automation: {
automationId: automation._id!, automationId: automation._id!,
@ -34,7 +34,7 @@ describe("Test triggering an automation from another automation", () => {
}) })
it("should fail gracefully if the automation id is incorrect", async () => { it("should fail gracefully if the automation id is incorrect", async () => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.triggerAutomationRun({ .triggerAutomationRun({
automation: { automation: {
// @ts-expect-error - incorrect on purpose // @ts-expect-error - incorrect on purpose

View File

@ -30,7 +30,7 @@ describe("test the update row action", () => {
}) })
it("should be able to run the update row action", async () => { it("should be able to run the update row action", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.updateRow({ .updateRow({
rowId: row._id!, rowId: row._id!,
row: { row: {
@ -52,7 +52,7 @@ describe("test the update row action", () => {
}) })
it("should check invalid inputs return an error", async () => { it("should check invalid inputs return an error", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.updateRow({ meta: {}, row: {}, rowId: "" }) .updateRow({ meta: {}, row: {}, rowId: "" })
.run() .run()
@ -60,7 +60,7 @@ describe("test the update row action", () => {
}) })
it("should return an error when table doesn't exist", async () => { it("should return an error when table doesn't exist", async () => {
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.updateRow({ .updateRow({
row: { _id: "invalid" }, row: { _id: "invalid" },
rowId: "invalid", rowId: "invalid",
@ -103,7 +103,7 @@ describe("test the update row action", () => {
user2: [{ _id: user2._id }], user2: [{ _id: user2._id }],
}) })
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.updateRow({ .updateRow({
rowId: row._id!, rowId: row._id!,
row: { row: {
@ -156,7 +156,7 @@ describe("test the update row action", () => {
user2: [{ _id: user2._id }], user2: [{ _id: user2._id }],
}) })
const results = await createAutomationBuilder({ config }) const results = await createAutomationBuilder(config)
.updateRow({ .updateRow({
rowId: row._id!, rowId: row._id!,
row: { row: {

View File

@ -20,7 +20,7 @@ describe("test the outgoing webhook action", () => {
it("should be able to run the action", async () => { it("should be able to run the action", async () => {
nock("http://www.example.com/").post("/").reply(200, { foo: "bar" }) nock("http://www.example.com/").post("/").reply(200, { foo: "bar" })
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.zapier({ url: "http://www.example.com", body: null }) .zapier({ url: "http://www.example.com", body: null })
.run() .run()
@ -43,7 +43,7 @@ describe("test the outgoing webhook action", () => {
.post("/", { ...payload, platform: "budibase" }) .post("/", { ...payload, platform: "budibase" })
.reply(200, { foo: "bar" }) .reply(200, { foo: "bar" })
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.zapier({ .zapier({
url: "http://www.example.com", url: "http://www.example.com",
body: { value: JSON.stringify(payload) }, body: { value: JSON.stringify(payload) },
@ -55,7 +55,7 @@ describe("test the outgoing webhook action", () => {
}) })
it("should return a 400 if the JSON payload string is malformed", async () => { it("should return a 400 if the JSON payload string is malformed", async () => {
const result = await createAutomationBuilder({ config }) const result = await createAutomationBuilder(config)
.zapier({ .zapier({
url: "http://www.example.com", url: "http://www.example.com",
body: { value: "{ invalid json }" }, body: { value: "{ invalid json }" },

View File

@ -24,7 +24,7 @@ describe("cron trigger", () => {
}) })
}) })
await createAutomationBuilder({ config }) await createAutomationBuilder(config)
.cron({ cron: "* * * * *" }) .cron({ cron: "* * * * *" })
.serverLog({ .serverLog({
text: "Hello, world!", text: "Hello, world!",
@ -44,7 +44,7 @@ describe("cron trigger", () => {
}) })
it("should fail if the cron expression is invalid", async () => { it("should fail if the cron expression is invalid", async () => {
await createAutomationBuilder({ config }) await createAutomationBuilder(config)
.cron({ cron: "* * * * * *" }) .cron({ cron: "* * * * * *" })
.serverLog({ .serverLog({
text: "Hello, world!", text: "Hello, world!",

View File

@ -11,7 +11,7 @@ describe("Branching automations", () => {
let webhook: Webhook let webhook: Webhook
async function createWebhookAutomation() { async function createWebhookAutomation() {
const automation = await createAutomationBuilder({ config }) const automation = await createAutomationBuilder(config)
.webhook({ fields: { parameter: "string" } }) .webhook({ fields: { parameter: "string" } })
.createRow({ .createRow({
row: { tableId: table._id!, name: "{{ trigger.parameter }}" }, row: { tableId: table._id!, name: "{{ trigger.parameter }}" },

View File

@ -135,14 +135,12 @@ class AutomationBuilder extends BaseStepBuilder {
private triggerOutputs: TriggerOutputs private triggerOutputs: TriggerOutputs
private triggerSet = false private triggerSet = false
constructor( constructor(config?: TestConfiguration) {
options: { name?: string; appId?: string; config?: TestConfiguration } = {}
) {
super() super()
this.config = options.config || setup.getConfig() this.config = config || setup.getConfig()
this.triggerOutputs = { fields: {} } this.triggerOutputs = { fields: {} }
this.automationConfig = { this.automationConfig = {
name: options.name || `Test Automation ${uuidv4()}`, name: `Test Automation ${uuidv4()}`,
definition: { definition: {
steps: [], steps: [],
trigger: { trigger: {
@ -154,10 +152,15 @@ class AutomationBuilder extends BaseStepBuilder {
stepNames: {}, stepNames: {},
}, },
type: "automation", type: "automation",
appId: options.appId ?? this.config.getAppId(), appId: this.config.getAppId(),
} }
} }
name(n: string): this {
this.automationConfig.name = n
return this
}
protected triggerInputOutput< protected triggerInputOutput<
TStep extends AutomationTriggerStepId, TStep extends AutomationTriggerStepId,
TInput = AutomationTriggerInputs<TStep>, TInput = AutomationTriggerInputs<TStep>,
@ -195,10 +198,13 @@ class AutomationBuilder extends BaseStepBuilder {
} }
} }
// The input and output for appAction is identical, and we only ever seem to
// set the output, so we're ignoring the input for now.
appAction = this.triggerOutputOnly(AutomationTriggerStepId.APP)
rowSaved = this.triggerInputOutput(AutomationTriggerStepId.ROW_SAVED) rowSaved = this.triggerInputOutput(AutomationTriggerStepId.ROW_SAVED)
rowUpdated = this.triggerInputOutput(AutomationTriggerStepId.ROW_UPDATED) rowUpdated = this.triggerInputOutput(AutomationTriggerStepId.ROW_UPDATED)
rowDeleted = this.triggerInputOutput(AutomationTriggerStepId.ROW_DELETED) rowDeleted = this.triggerInputOutput(AutomationTriggerStepId.ROW_DELETED)
appAction = this.triggerOutputOnly(AutomationTriggerStepId.APP)
webhook = this.triggerInputOutput(AutomationTriggerStepId.WEBHOOK) webhook = this.triggerInputOutput(AutomationTriggerStepId.WEBHOOK)
cron = this.triggerInputOutput(AutomationTriggerStepId.CRON) cron = this.triggerInputOutput(AutomationTriggerStepId.CRON)
@ -214,9 +220,6 @@ class AutomationBuilder extends BaseStepBuilder {
} }
async save() { async save() {
if (!Object.keys(this.automationConfig.definition.trigger).length) {
throw new Error("Please add a trigger to this automation test")
}
this.automationConfig.definition.steps = this.steps this.automationConfig.definition.steps = this.steps
const { automation } = await this.config.api.automation.post(this.build()) const { automation } = await this.config.api.automation.post(this.build())
return automation return automation
@ -241,10 +244,6 @@ class AutomationBuilder extends BaseStepBuilder {
} }
} }
export function createAutomationBuilder(options?: { export function createAutomationBuilder(config?: TestConfiguration) {
name?: string return new AutomationBuilder(config)
appId?: string
config?: TestConfiguration
}) {
return new AutomationBuilder(options)
} }