Merge pull request #15494 from Budibase/automation-tests-4
Refactor automation builder.
This commit is contained in:
commit
d72b40c857
|
@ -107,10 +107,7 @@ describe("/automations", () => {
|
|||
})
|
||||
|
||||
it("Should ensure you can't have a branch as not a last step", async () => {
|
||||
const automation = createAutomationBuilder({
|
||||
name: "String Equality Branching",
|
||||
appId: config.getAppId(),
|
||||
})
|
||||
const automation = createAutomationBuilder(config)
|
||||
.appAction({ fields: { status: "active" } })
|
||||
.branch({
|
||||
activeBranch: {
|
||||
|
@ -134,10 +131,7 @@ describe("/automations", () => {
|
|||
})
|
||||
|
||||
it("Should check validation on an automation that has a branch step with no children", async () => {
|
||||
const automation = createAutomationBuilder({
|
||||
name: "String Equality Branching",
|
||||
appId: config.getAppId(),
|
||||
})
|
||||
const automation = createAutomationBuilder(config)
|
||||
.appAction({ fields: { status: "active" } })
|
||||
.branch({})
|
||||
.serverLog({ text: "Inactive user" })
|
||||
|
@ -153,10 +147,7 @@ describe("/automations", () => {
|
|||
})
|
||||
|
||||
it("Should check validation on a branch step with empty conditions", async () => {
|
||||
const automation = createAutomationBuilder({
|
||||
name: "String Equality Branching",
|
||||
appId: config.getAppId(),
|
||||
})
|
||||
const automation = createAutomationBuilder(config)
|
||||
.appAction({ fields: { status: "active" } })
|
||||
.branch({
|
||||
activeBranch: {
|
||||
|
@ -177,10 +168,7 @@ describe("/automations", () => {
|
|||
})
|
||||
|
||||
it("Should check validation on an branch that has a condition that is not valid", async () => {
|
||||
const automation = createAutomationBuilder({
|
||||
name: "String Equality Branching",
|
||||
appId: config.getAppId(),
|
||||
})
|
||||
const automation = createAutomationBuilder(config)
|
||||
.appAction({ fields: { status: "active" } })
|
||||
.branch({
|
||||
activeBranch: {
|
||||
|
@ -252,12 +240,7 @@ describe("/automations", () => {
|
|||
})
|
||||
|
||||
it("should be able to access platformUrl, logoUrl and company in the automation", async () => {
|
||||
const result = await createAutomationBuilder({
|
||||
name: "Test Automation",
|
||||
appId: config.getAppId(),
|
||||
config,
|
||||
})
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.serverLog({
|
||||
text: "{{ settings.url }}",
|
||||
})
|
||||
|
|
|
@ -24,8 +24,7 @@ describe("Branching automations", () => {
|
|||
const branch2LogId = "33333333-3333-3333-3333-333333333333"
|
||||
const branch2Id = "44444444-4444-4444-4444-444444444444"
|
||||
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.serverLog(
|
||||
{ text: "Starting automation" },
|
||||
{ stepName: "FirstLog", stepId: firstLogId }
|
||||
|
@ -83,7 +82,7 @@ describe("Branching automations", () => {
|
|||
})
|
||||
|
||||
it("should execute correct branch based on string equality", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.appAction({ fields: { status: "active" } })
|
||||
.branch({
|
||||
activeBranch: {
|
||||
|
@ -108,7 +107,7 @@ describe("Branching automations", () => {
|
|||
})
|
||||
|
||||
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" } })
|
||||
.branch({
|
||||
activeAdminBranch: {
|
||||
|
@ -136,7 +135,7 @@ describe("Branching automations", () => {
|
|||
})
|
||||
|
||||
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" } })
|
||||
.branch({
|
||||
specialBranch: {
|
||||
|
@ -168,7 +167,7 @@ describe("Branching automations", () => {
|
|||
})
|
||||
|
||||
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" } })
|
||||
.createRow({ row: { name: "Test", tableId: table._id } })
|
||||
.branch({
|
||||
|
@ -204,7 +203,7 @@ describe("Branching automations", () => {
|
|||
})
|
||||
|
||||
it("evaluate multiple conditions", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.appAction({ fields: { test_trigger: true } })
|
||||
.serverLog({ text: "Starting automation" }, { stepId: "aN6znRYHG" })
|
||||
.branch({
|
||||
|
@ -245,7 +244,7 @@ describe("Branching automations", () => {
|
|||
})
|
||||
|
||||
it("evaluate multiple conditions with interpolated text", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.appAction({ fields: { test_trigger: true } })
|
||||
.serverLog({ text: "Starting automation" }, { stepId: "aN6znRYHG" })
|
||||
.branch({
|
||||
|
|
|
@ -29,7 +29,7 @@ describe("Automation Scenarios", () => {
|
|||
it("should trigger an automation which then creates a row", async () => {
|
||||
const table = await config.api.table.save(basicTable())
|
||||
|
||||
const results = await createAutomationBuilder({ config })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.rowUpdated(
|
||||
{ tableId: table._id! },
|
||||
{
|
||||
|
@ -65,8 +65,7 @@ describe("Automation Scenarios", () => {
|
|||
}
|
||||
await config.api.row.save(table._id!, row)
|
||||
await config.api.row.save(table._id!, row)
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.queryRows({
|
||||
tableId: table._id!,
|
||||
})
|
||||
|
@ -84,8 +83,7 @@ describe("Automation Scenarios", () => {
|
|||
}
|
||||
await config.api.row.save(table._id!, row)
|
||||
await config.api.row.save(table._id!, row)
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.queryRows({
|
||||
tableId: table._id!,
|
||||
})
|
||||
|
@ -126,8 +124,7 @@ describe("Automation Scenarios", () => {
|
|||
},
|
||||
})
|
||||
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.createRow(
|
||||
{
|
||||
row: {
|
||||
|
@ -195,8 +192,7 @@ describe("Automation Scenarios", () => {
|
|||
}
|
||||
await config.api.row.save(table._id!, row)
|
||||
await config.api.row.save(table._id!, row)
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.queryRows(
|
||||
{
|
||||
tableId: table._id!,
|
||||
|
@ -245,8 +241,7 @@ describe("Automation Scenarios", () => {
|
|||
})
|
||||
|
||||
it("should stop an automation if the condition is not met", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.createRow({
|
||||
row: {
|
||||
name: "Equal Test",
|
||||
|
@ -271,8 +266,7 @@ describe("Automation Scenarios", () => {
|
|||
})
|
||||
|
||||
it("should continue the automation if the condition is met", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.createRow({
|
||||
row: {
|
||||
name: "Not Equal Test",
|
||||
|
@ -338,8 +332,7 @@ describe("Automation Scenarios", () => {
|
|||
it.each(testCases)(
|
||||
"should pass the filter when condition is $condition",
|
||||
async ({ condition, value, rowValue, expectPass }) => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.createRow({
|
||||
row: {
|
||||
name: `${condition} Test`,
|
||||
|
@ -373,7 +366,7 @@ describe("Automation Scenarios", () => {
|
|||
it("Check user is passed through from row trigger", async () => {
|
||||
const table = await config.api.table.save(basicTable())
|
||||
|
||||
const results = await createAutomationBuilder({ config })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.rowUpdated(
|
||||
{ tableId: table._id! },
|
||||
{
|
||||
|
@ -388,8 +381,7 @@ describe("Automation Scenarios", () => {
|
|||
})
|
||||
|
||||
it("Check user is passed through from app trigger", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.serverLog({ text: "{{ [user].[email] }}" })
|
||||
.run()
|
||||
|
||||
|
@ -460,7 +452,7 @@ if (descriptions.length) {
|
|||
queryVerb: "read",
|
||||
})
|
||||
|
||||
const results = await createAutomationBuilder({ config })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.appAction({
|
||||
fields: {},
|
||||
})
|
||||
|
|
|
@ -24,7 +24,7 @@ describe("Execute Bash Automations", () => {
|
|||
})
|
||||
|
||||
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" } })
|
||||
.bash(
|
||||
{ code: "echo '{{ trigger.fields.command }}'" },
|
||||
|
@ -43,7 +43,7 @@ describe("Execute Bash Automations", () => {
|
|||
})
|
||||
|
||||
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" } })
|
||||
.bash(
|
||||
{ code: "echo 'initial content' > {{ trigger.fields.filename }}" },
|
||||
|
@ -64,8 +64,7 @@ describe("Execute Bash Automations", () => {
|
|||
})
|
||||
|
||||
it("should integrate bash output with row operations", async () => {
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.queryRows(
|
||||
{
|
||||
tableId: table._id!,
|
||||
|
@ -94,7 +93,7 @@ describe("Execute Bash Automations", () => {
|
|||
})
|
||||
|
||||
it("should handle bash output in conditional logic", async () => {
|
||||
const result = await createAutomationBuilder({ config })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.appAction({ fields: { threshold: "5" } })
|
||||
.bash(
|
||||
{ code: "echo $(( {{ trigger.fields.threshold }} + 5 ))" },
|
||||
|
@ -121,8 +120,7 @@ describe("Execute Bash Automations", () => {
|
|||
})
|
||||
|
||||
it("should handle null values gracefully", async () => {
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.bash(
|
||||
// @ts-expect-error - testing null input
|
||||
{ code: null },
|
||||
|
|
|
@ -40,7 +40,7 @@ describe("test the create row action", () => {
|
|||
})
|
||||
|
||||
it("should be able to run the action", async () => {
|
||||
const result = await createAutomationBuilder({ config })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.appAction({ fields: { status: "new" } })
|
||||
.serverLog({ text: "Starting create row flow" }, { stepName: "StartLog" })
|
||||
.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 () => {
|
||||
const result = await createAutomationBuilder({ config })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.appAction({ fields: { status: "error" } })
|
||||
.serverLog({ text: "Starting error test flow" }, { stepName: "StartLog" })
|
||||
.createRow(
|
||||
|
@ -84,7 +84,7 @@ describe("test the create row action", () => {
|
|||
})
|
||||
|
||||
it("should check invalid inputs return an error", async () => {
|
||||
const result = await createAutomationBuilder({ config })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.appAction({ fields: { status: "invalid" } })
|
||||
.serverLog({ text: "Testing invalid input" }, { stepName: "StartLog" })
|
||||
.createRow({ row: {} }, { stepName: "CreateRow" })
|
||||
|
@ -122,7 +122,7 @@ describe("test the create row action", () => {
|
|||
]
|
||||
|
||||
attachmentRow.file_attachment = attachmentObject
|
||||
const result = await createAutomationBuilder({ config })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.appAction({ fields: { type: "attachment" } })
|
||||
.serverLog(
|
||||
{ text: "Processing attachment upload" },
|
||||
|
@ -173,7 +173,7 @@ describe("test the create row action", () => {
|
|||
}
|
||||
|
||||
attachmentRow.single_file_attachment = attachmentObject
|
||||
const result = await createAutomationBuilder({ config })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.appAction({ fields: { type: "single-attachment" } })
|
||||
.serverLog(
|
||||
{ text: "Processing single attachment" },
|
||||
|
@ -244,7 +244,7 @@ describe("test the create row action", () => {
|
|||
}
|
||||
|
||||
attachmentRow.single_file_attachment = attachmentObject
|
||||
const result = await createAutomationBuilder({ config })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.appAction({ fields: { type: "invalid-attachment" } })
|
||||
.serverLog(
|
||||
{ text: "Testing invalid attachment keys" },
|
||||
|
|
|
@ -27,7 +27,7 @@ describe("cron automations", () => {
|
|||
})
|
||||
|
||||
it("should initialise the automation timestamp", async () => {
|
||||
await createAutomationBuilder({ config }).cron({ cron: "* * * * *" }).save()
|
||||
await createAutomationBuilder(config).cron({ cron: "* * * * *" }).save()
|
||||
|
||||
tk.travel(Date.now() + oneMinuteInMs)
|
||||
await config.publish()
|
||||
|
|
|
@ -16,10 +16,7 @@ describe("test the delay logic", () => {
|
|||
const time = 100
|
||||
const before = performance.now()
|
||||
|
||||
await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
.delay({ time })
|
||||
.run()
|
||||
await createAutomationBuilder(config).delay({ time }).run()
|
||||
|
||||
const now = performance.now()
|
||||
|
||||
|
|
|
@ -20,8 +20,7 @@ describe("test the delete row action", () => {
|
|||
})
|
||||
|
||||
it("should be able to run the delete row action", async () => {
|
||||
await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
await createAutomationBuilder(config)
|
||||
.deleteRow({
|
||||
tableId: table._id!,
|
||||
id: row._id!,
|
||||
|
@ -35,8 +34,7 @@ describe("test the delete row action", () => {
|
|||
})
|
||||
|
||||
it("should check invalid inputs return an error", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.deleteRow({ tableId: "", id: "", revision: "" })
|
||||
.run()
|
||||
|
||||
|
@ -44,8 +42,7 @@ describe("test the delete row action", () => {
|
|||
})
|
||||
|
||||
it("should return an error when table doesn't exist", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.deleteRow({
|
||||
tableId: "invalid",
|
||||
id: "invalid",
|
||||
|
|
|
@ -19,8 +19,7 @@ describe("test the outgoing webhook action", () => {
|
|||
|
||||
it("should be able to run the action", async () => {
|
||||
nock("http://www.example.com/").post("/").reply(200, { foo: "bar" })
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.discord({
|
||||
url: "http://www.example.com",
|
||||
username: "joe_bloggs",
|
||||
|
|
|
@ -20,8 +20,7 @@ describe("Execute Script Automations", () => {
|
|||
})
|
||||
|
||||
it("should execute a basic script and return the result", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.executeScript({ code: "return 2 + 2" })
|
||||
.run()
|
||||
|
||||
|
@ -29,7 +28,7 @@ describe("Execute Script Automations", () => {
|
|||
})
|
||||
|
||||
it("should access bindings from previous steps", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.appAction({ fields: { data: [1, 2, 3] } })
|
||||
.executeScript(
|
||||
{
|
||||
|
@ -43,8 +42,7 @@ describe("Execute Script Automations", () => {
|
|||
})
|
||||
|
||||
it("should handle script execution errors gracefully", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.executeScript({ code: "return nonexistentVariable.map(x => x)" })
|
||||
.run()
|
||||
|
||||
|
@ -55,7 +53,7 @@ describe("Execute Script Automations", () => {
|
|||
})
|
||||
|
||||
it("should handle conditional logic in scripts", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.appAction({ fields: { value: 10 } })
|
||||
.executeScript({
|
||||
code: `
|
||||
|
@ -72,7 +70,7 @@ describe("Execute Script Automations", () => {
|
|||
})
|
||||
|
||||
it("should use multiple steps and validate script execution", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.appAction({ fields: {} })
|
||||
.serverLog(
|
||||
{ text: "Starting multi-step automation" },
|
||||
|
|
|
@ -42,8 +42,7 @@ describe("test the filter logic", () => {
|
|||
[new Date().toISOString(), ">", new Date(-10000).toISOString()],
|
||||
]
|
||||
it.each(pass)("should pass %p %p %p", async (field, condition, value) => {
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.filter({ field, condition: stringToFilterCondition(condition), value })
|
||||
.run()
|
||||
|
||||
|
@ -60,8 +59,7 @@ describe("test the filter logic", () => {
|
|||
[{}, "==", {}],
|
||||
]
|
||||
it.each(fail)("should fail %p %p %p", async (field, condition, value) => {
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.filter({ field, condition: stringToFilterCondition(condition), value })
|
||||
.run()
|
||||
|
||||
|
|
|
@ -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 () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.rowSaved(
|
||||
{ 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 () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.rowSaved(
|
||||
{ tableId: table._id! },
|
||||
{
|
||||
|
@ -151,8 +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 () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.loop({
|
||||
option: LoopStepType.ARRAY,
|
||||
binding: "1, 2, 3",
|
||||
|
@ -167,8 +166,7 @@ describe("Attempt to run a basic loop automation", () => {
|
|||
})
|
||||
|
||||
it("ensure the loop stops if the failure condition is reached", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.loop({
|
||||
option: LoopStepType.ARRAY,
|
||||
binding: ["test", "test2", "test3"],
|
||||
|
@ -186,8 +184,7 @@ describe("Attempt to run a basic loop automation", () => {
|
|||
})
|
||||
|
||||
it("ensure the loop stops if the max iterations are reached", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.loop({
|
||||
option: LoopStepType.ARRAY,
|
||||
binding: ["test", "test2", "test3"],
|
||||
|
@ -201,8 +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 () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.loop({
|
||||
option: LoopStepType.ARRAY,
|
||||
binding: ["test", "test2", "test3"],
|
||||
|
@ -216,7 +212,7 @@ describe("Attempt to run a basic loop automation", () => {
|
|||
})
|
||||
|
||||
it("should run an automation where a loop is successfully run twice", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.rowSaved(
|
||||
{ tableId: table._id! },
|
||||
{
|
||||
|
@ -278,8 +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 () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.loop({
|
||||
option: LoopStepType.ARRAY,
|
||||
binding: [1, 2, 3],
|
||||
|
@ -300,8 +295,7 @@ describe("Attempt to run a basic loop automation", () => {
|
|||
})
|
||||
|
||||
it("should use automation names to loop with", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.loop(
|
||||
{
|
||||
option: LoopStepType.ARRAY,
|
||||
|
@ -352,8 +346,7 @@ describe("Attempt to run a basic loop automation", () => {
|
|||
|
||||
await config.api.row.bulkImport(table._id!, { rows })
|
||||
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.queryRows({
|
||||
tableId: table._id!,
|
||||
})
|
||||
|
@ -432,8 +425,7 @@ describe("Attempt to run a basic loop automation", () => {
|
|||
|
||||
await config.api.row.bulkImport(table._id!, { rows })
|
||||
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.queryRows(
|
||||
{
|
||||
tableId: table._id!,
|
||||
|
@ -515,8 +507,7 @@ describe("Attempt to run a basic loop automation", () => {
|
|||
|
||||
await config.api.row.bulkImport(table._id!, { rows })
|
||||
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.queryRows({
|
||||
tableId: table._id!,
|
||||
})
|
||||
|
|
|
@ -19,8 +19,7 @@ describe("test the outgoing webhook action", () => {
|
|||
|
||||
it("should be able to run the action", async () => {
|
||||
nock("http://www.example.com/").post("/").reply(200, { foo: "bar" })
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.make({
|
||||
url: "http://www.example.com",
|
||||
body: null,
|
||||
|
@ -46,8 +45,7 @@ describe("test the outgoing webhook action", () => {
|
|||
.post("/", payload)
|
||||
.reply(200, { foo: "bar" })
|
||||
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.make({
|
||||
body: { value: JSON.stringify(payload) },
|
||||
url: "http://www.example.com",
|
||||
|
@ -59,8 +57,7 @@ describe("test the outgoing webhook action", () => {
|
|||
})
|
||||
|
||||
it("should return a 400 if the JSON payload string is malformed", async () => {
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.make({
|
||||
body: { value: "{ invalid json }" },
|
||||
url: "http://www.example.com",
|
||||
|
|
|
@ -20,8 +20,7 @@ describe("test the outgoing webhook action", () => {
|
|||
|
||||
it("should be able to run the action and default to 'get'", async () => {
|
||||
nock("http://www.example.com/").get("/").reply(200, { foo: "bar" })
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.n8n({
|
||||
url: "http://www.example.com",
|
||||
body: { test: "IGNORE_ME" },
|
||||
|
@ -39,8 +38,7 @@ describe("test the outgoing webhook action", () => {
|
|||
.post("/", { name: "Adam", age: 9 })
|
||||
.reply(200)
|
||||
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.n8n({
|
||||
url: "http://www.example.com",
|
||||
body: { value: JSON.stringify({ name: "Adam", age: 9 }) },
|
||||
|
@ -53,8 +51,7 @@ describe("test the outgoing webhook action", () => {
|
|||
})
|
||||
|
||||
it("should return a 400 if the JSON payload string is malformed", async () => {
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.n8n({
|
||||
url: "http://www.example.com",
|
||||
body: { value: "{ value1 1 }" },
|
||||
|
@ -73,8 +70,7 @@ describe("test the outgoing webhook action", () => {
|
|||
.head("/", body => body === "")
|
||||
.reply(200)
|
||||
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.n8n({
|
||||
url: "http://www.example.com",
|
||||
method: HttpMethod.HEAD,
|
||||
|
|
|
@ -57,8 +57,7 @@ describe("test the openai action", () => {
|
|||
// means it goes through the "legacy" path which requires you to set your
|
||||
// own API key. We don't count this against your quota.
|
||||
const result = await expectAIUsage(0, () =>
|
||||
createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
createAutomationBuilder(config)
|
||||
.openai({ prompt: "Hello, world", model: Model.GPT_4O_MINI })
|
||||
.run()
|
||||
)
|
||||
|
@ -69,8 +68,7 @@ describe("test the openai action", () => {
|
|||
|
||||
it("should present the correct error message when a prompt is not provided", async () => {
|
||||
const result = await expectAIUsage(0, () =>
|
||||
createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
createAutomationBuilder(config)
|
||||
.openai({ prompt: "", model: Model.GPT_4O_MINI })
|
||||
.run()
|
||||
)
|
||||
|
@ -85,8 +83,7 @@ describe("test the openai action", () => {
|
|||
mockChatGPTError()
|
||||
|
||||
const result = await expectAIUsage(0, () =>
|
||||
createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
createAutomationBuilder(config)
|
||||
.openai({ prompt: "Hello, world", model: Model.GPT_4O_MINI })
|
||||
.run()
|
||||
)
|
||||
|
@ -108,8 +105,7 @@ describe("test the openai action", () => {
|
|||
// calculation we use to approximate cost. This uses Budibase's OpenAI API
|
||||
// key, so we charge users for it.
|
||||
const result = await expectAIUsage(14, () =>
|
||||
createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
createAutomationBuilder(config)
|
||||
.openai({ model: Model.GPT_4O_MINI, prompt: "Hello, world" })
|
||||
.run()
|
||||
)
|
||||
|
|
|
@ -23,8 +23,7 @@ describe("test the outgoing webhook action", () => {
|
|||
.post("/", { a: 1 })
|
||||
.reply(200, { foo: "bar" })
|
||||
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.outgoingWebhook({
|
||||
requestMethod: RequestType.POST,
|
||||
url: "http://www.example.com",
|
||||
|
@ -39,8 +38,7 @@ describe("test the outgoing webhook action", () => {
|
|||
})
|
||||
|
||||
it("should return an error if something goes wrong in fetch", async () => {
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.outgoingWebhook({
|
||||
requestMethod: RequestType.GET,
|
||||
url: "www.invalid.com",
|
||||
|
|
|
@ -28,11 +28,7 @@ describe("Test a query step automation", () => {
|
|||
})
|
||||
|
||||
it("should be able to run the query step", async () => {
|
||||
const result = await createAutomationBuilder({
|
||||
name: "Basic Query Test",
|
||||
config,
|
||||
})
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.queryRows(
|
||||
{
|
||||
tableId: table._id!,
|
||||
|
@ -56,11 +52,7 @@ describe("Test a query step automation", () => {
|
|||
})
|
||||
|
||||
it("Returns all rows when onEmptyFilter has no value and no filters are passed", async () => {
|
||||
const result = await createAutomationBuilder({
|
||||
name: "Empty Filter Test",
|
||||
config,
|
||||
})
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.queryRows(
|
||||
{
|
||||
tableId: table._id!,
|
||||
|
@ -80,11 +72,7 @@ describe("Test a query step automation", () => {
|
|||
})
|
||||
|
||||
it("Returns no rows when onEmptyFilter is RETURN_NONE and theres no filters", async () => {
|
||||
const result = await createAutomationBuilder({
|
||||
name: "Return None Test",
|
||||
config,
|
||||
})
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.queryRows(
|
||||
{
|
||||
tableId: table._id!,
|
||||
|
@ -105,11 +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 () => {
|
||||
const result = await createAutomationBuilder({
|
||||
name: "Null Filter Test",
|
||||
config,
|
||||
})
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.queryRows(
|
||||
{
|
||||
tableId: table._id!,
|
||||
|
@ -134,11 +118,7 @@ describe("Test a query step automation", () => {
|
|||
})
|
||||
|
||||
it("Returns rows when onEmptyFilter is RETURN_ALL and no filter is passed", async () => {
|
||||
const result = await createAutomationBuilder({
|
||||
name: "Return All Test",
|
||||
config,
|
||||
})
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.queryRows(
|
||||
{
|
||||
tableId: table._id!,
|
||||
|
@ -165,11 +145,7 @@ describe("Test a query step automation", () => {
|
|||
await config.api.row.save(tableWithSpaces._id!, {
|
||||
name: NAME,
|
||||
})
|
||||
const result = await createAutomationBuilder({
|
||||
name: "Return All Test",
|
||||
config,
|
||||
})
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.queryRows(
|
||||
{
|
||||
tableId: tableWithSpaces._id!,
|
||||
|
|
|
@ -13,8 +13,7 @@ describe("test the server log action", () => {
|
|||
})
|
||||
|
||||
it("should be able to log the text", async () => {
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.serverLog({ text: "Hello World" })
|
||||
.run()
|
||||
expect(result.steps[0].outputs.message).toEqual(
|
||||
|
|
|
@ -17,13 +17,11 @@ describe("Test triggering an automation from another automation", () => {
|
|||
})
|
||||
|
||||
it("should trigger an other server log automation", async () => {
|
||||
const automation = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const automation = await createAutomationBuilder(config)
|
||||
.serverLog({ text: "Hello World" })
|
||||
.save()
|
||||
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.triggerAutomationRun({
|
||||
automation: {
|
||||
automationId: automation._id!,
|
||||
|
@ -36,8 +34,7 @@ describe("Test triggering an automation from another automation", () => {
|
|||
})
|
||||
|
||||
it("should fail gracefully if the automation id is incorrect", async () => {
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.triggerAutomationRun({
|
||||
automation: {
|
||||
// @ts-expect-error - incorrect on purpose
|
||||
|
|
|
@ -30,8 +30,7 @@ describe("test the update row action", () => {
|
|||
})
|
||||
|
||||
it("should be able to run the update row action", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.updateRow({
|
||||
rowId: row._id!,
|
||||
row: {
|
||||
|
@ -53,8 +52,7 @@ describe("test the update row action", () => {
|
|||
})
|
||||
|
||||
it("should check invalid inputs return an error", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.updateRow({ meta: {}, row: {}, rowId: "" })
|
||||
.run()
|
||||
|
||||
|
@ -62,8 +60,7 @@ describe("test the update row action", () => {
|
|||
})
|
||||
|
||||
it("should return an error when table doesn't exist", async () => {
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.updateRow({
|
||||
row: { _id: "invalid" },
|
||||
rowId: "invalid",
|
||||
|
@ -106,8 +103,7 @@ describe("test the update row action", () => {
|
|||
user2: [{ _id: user2._id }],
|
||||
})
|
||||
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.updateRow({
|
||||
rowId: row._id!,
|
||||
row: {
|
||||
|
@ -160,8 +156,7 @@ describe("test the update row action", () => {
|
|||
user2: [{ _id: user2._id }],
|
||||
})
|
||||
|
||||
const results = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const results = await createAutomationBuilder(config)
|
||||
.updateRow({
|
||||
rowId: row._id!,
|
||||
row: {
|
||||
|
|
|
@ -20,8 +20,7 @@ describe("test the outgoing webhook action", () => {
|
|||
it("should be able to run the action", async () => {
|
||||
nock("http://www.example.com/").post("/").reply(200, { foo: "bar" })
|
||||
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.zapier({ url: "http://www.example.com", body: null })
|
||||
.run()
|
||||
|
||||
|
@ -44,8 +43,7 @@ describe("test the outgoing webhook action", () => {
|
|||
.post("/", { ...payload, platform: "budibase" })
|
||||
.reply(200, { foo: "bar" })
|
||||
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.zapier({
|
||||
url: "http://www.example.com",
|
||||
body: { value: JSON.stringify(payload) },
|
||||
|
@ -57,8 +55,7 @@ describe("test the outgoing webhook action", () => {
|
|||
})
|
||||
|
||||
it("should return a 400 if the JSON payload string is malformed", async () => {
|
||||
const result = await createAutomationBuilder({ config })
|
||||
.appAction({ fields: {} })
|
||||
const result = await createAutomationBuilder(config)
|
||||
.zapier({
|
||||
url: "http://www.example.com",
|
||||
body: { value: "{ invalid json }" },
|
||||
|
|
|
@ -6,7 +6,7 @@ import { Job } from "bull"
|
|||
describe("cron trigger", () => {
|
||||
const config = new TestConfiguration()
|
||||
|
||||
beforeEach(async () => {
|
||||
beforeAll(async () => {
|
||||
await config.init()
|
||||
})
|
||||
|
||||
|
@ -24,7 +24,7 @@ describe("cron trigger", () => {
|
|||
})
|
||||
})
|
||||
|
||||
await createAutomationBuilder({ config })
|
||||
await createAutomationBuilder(config)
|
||||
.cron({ cron: "* * * * *" })
|
||||
.serverLog({
|
||||
text: "Hello, world!",
|
||||
|
@ -44,7 +44,7 @@ describe("cron trigger", () => {
|
|||
})
|
||||
|
||||
it("should fail if the cron expression is invalid", async () => {
|
||||
await createAutomationBuilder({ config })
|
||||
await createAutomationBuilder(config)
|
||||
.cron({ cron: "* * * * * *" })
|
||||
.serverLog({
|
||||
text: "Hello, world!",
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import * as automation from "../../index"
|
||||
import { Table, Webhook, WebhookActionType } from "@budibase/types"
|
||||
import { createAutomationBuilder } from "../utilities/AutomationTestBuilder"
|
||||
import { mocks } from "@budibase/backend-core/tests"
|
||||
|
@ -12,7 +11,7 @@ describe("Branching automations", () => {
|
|||
let webhook: Webhook
|
||||
|
||||
async function createWebhookAutomation() {
|
||||
const automation = await createAutomationBuilder({ config })
|
||||
const automation = await createAutomationBuilder(config)
|
||||
.webhook({ fields: { parameter: "string" } })
|
||||
.createRow({
|
||||
row: { tableId: table._id!, name: "{{ trigger.parameter }}" },
|
||||
|
@ -37,7 +36,6 @@ describe("Branching automations", () => {
|
|||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
await automation.init()
|
||||
await config.init()
|
||||
table = await config.createTable()
|
||||
})
|
||||
|
|
|
@ -2,51 +2,24 @@ import { v4 as uuidv4 } from "uuid"
|
|||
import { BUILTIN_ACTION_DEFINITIONS } from "../../actions"
|
||||
import { TRIGGER_DEFINITIONS } from "../../triggers"
|
||||
import {
|
||||
AppActionTriggerInputs,
|
||||
AppActionTriggerOutputs,
|
||||
Automation,
|
||||
AutomationActionStepId,
|
||||
AutomationStep,
|
||||
AutomationStepInputs,
|
||||
AutomationTrigger,
|
||||
AutomationTriggerDefinition,
|
||||
AutomationTriggerInputs,
|
||||
AutomationTriggerOutputs,
|
||||
AutomationTriggerStepId,
|
||||
BashStepInputs,
|
||||
Branch,
|
||||
BranchStepInputs,
|
||||
CollectStepInputs,
|
||||
CreateRowStepInputs,
|
||||
CronTriggerInputs,
|
||||
CronTriggerOutputs,
|
||||
DelayStepInputs,
|
||||
DeleteRowStepInputs,
|
||||
DiscordStepInputs,
|
||||
ExecuteQueryStepInputs,
|
||||
ExecuteScriptStepInputs,
|
||||
FilterStepInputs,
|
||||
isDidNotTriggerResponse,
|
||||
LoopStepInputs,
|
||||
MakeIntegrationInputs,
|
||||
n8nStepInputs,
|
||||
OpenAIStepInputs,
|
||||
OutgoingWebhookStepInputs,
|
||||
QueryRowsStepInputs,
|
||||
RowCreatedTriggerInputs,
|
||||
RowCreatedTriggerOutputs,
|
||||
RowDeletedTriggerInputs,
|
||||
RowDeletedTriggerOutputs,
|
||||
RowUpdatedTriggerInputs,
|
||||
RowUpdatedTriggerOutputs,
|
||||
SearchFilters,
|
||||
ServerLogStepInputs,
|
||||
SmtpEmailStepInputs,
|
||||
TestAutomationRequest,
|
||||
TriggerAutomationStepInputs,
|
||||
UpdateRowStepInputs,
|
||||
WebhookTriggerInputs,
|
||||
WebhookTriggerOutputs,
|
||||
ZapierStepInputs,
|
||||
} from "@budibase/types"
|
||||
import TestConfiguration from "../../../tests/utilities/TestConfiguration"
|
||||
import * as setup from "../utilities"
|
||||
|
@ -74,28 +47,53 @@ class BaseStepBuilder {
|
|||
protected steps: AutomationStep[] = []
|
||||
protected stepNames: { [key: string]: string } = {}
|
||||
|
||||
protected step<TStep extends AutomationActionStepId>(
|
||||
stepId: TStep,
|
||||
stepSchema: Omit<AutomationStep, "id" | "stepId" | "inputs">,
|
||||
protected createStepFn<TStep extends AutomationActionStepId>(stepId: TStep) {
|
||||
return (
|
||||
inputs: AutomationStepInputs<TStep>,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
) => {
|
||||
const schema = BUILTIN_ACTION_DEFINITIONS[stepId]
|
||||
const id = opts?.stepId || uuidv4()
|
||||
this.steps.push({
|
||||
...stepSchema,
|
||||
...schema,
|
||||
inputs: inputs as any,
|
||||
id,
|
||||
stepId,
|
||||
name: opts?.stepName || stepSchema.name,
|
||||
name: opts?.stepName || schema.name,
|
||||
})
|
||||
if (opts?.stepName) {
|
||||
this.stepNames[id] = opts.stepName
|
||||
}
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
createRow = this.createStepFn(AutomationActionStepId.CREATE_ROW)
|
||||
updateRow = this.createStepFn(AutomationActionStepId.UPDATE_ROW)
|
||||
deleteRow = this.createStepFn(AutomationActionStepId.DELETE_ROW)
|
||||
sendSmtpEmail = this.createStepFn(AutomationActionStepId.SEND_EMAIL_SMTP)
|
||||
executeQuery = this.createStepFn(AutomationActionStepId.EXECUTE_QUERY)
|
||||
queryRows = this.createStepFn(AutomationActionStepId.QUERY_ROWS)
|
||||
loop = this.createStepFn(AutomationActionStepId.LOOP)
|
||||
serverLog = this.createStepFn(AutomationActionStepId.SERVER_LOG)
|
||||
executeScript = this.createStepFn(AutomationActionStepId.EXECUTE_SCRIPT)
|
||||
filter = this.createStepFn(AutomationActionStepId.FILTER)
|
||||
bash = this.createStepFn(AutomationActionStepId.EXECUTE_BASH)
|
||||
openai = this.createStepFn(AutomationActionStepId.OPENAI)
|
||||
collect = this.createStepFn(AutomationActionStepId.COLLECT)
|
||||
zapier = this.createStepFn(AutomationActionStepId.zapier)
|
||||
triggerAutomationRun = this.createStepFn(
|
||||
AutomationActionStepId.TRIGGER_AUTOMATION_RUN
|
||||
)
|
||||
outgoingWebhook = this.createStepFn(AutomationActionStepId.OUTGOING_WEBHOOK)
|
||||
n8n = this.createStepFn(AutomationActionStepId.n8n)
|
||||
make = this.createStepFn(AutomationActionStepId.integromat)
|
||||
discord = this.createStepFn(AutomationActionStepId.discord)
|
||||
delay = this.createStepFn(AutomationActionStepId.DELAY)
|
||||
|
||||
protected addBranchStep(branchConfig: BranchConfig): void {
|
||||
const branchStepInputs: BranchStepInputs = {
|
||||
branches: [] as Branch[],
|
||||
branches: [],
|
||||
children: {},
|
||||
}
|
||||
|
||||
|
@ -118,243 +116,6 @@ class BaseStepBuilder {
|
|||
}
|
||||
this.steps.push(branchStep)
|
||||
}
|
||||
|
||||
// STEPS
|
||||
createRow(
|
||||
inputs: CreateRowStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.CREATE_ROW,
|
||||
BUILTIN_ACTION_DEFINITIONS.CREATE_ROW,
|
||||
inputs,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
updateRow(
|
||||
inputs: UpdateRowStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.UPDATE_ROW,
|
||||
BUILTIN_ACTION_DEFINITIONS.UPDATE_ROW,
|
||||
inputs,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
deleteRow(
|
||||
inputs: DeleteRowStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.DELETE_ROW,
|
||||
BUILTIN_ACTION_DEFINITIONS.DELETE_ROW,
|
||||
inputs,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
sendSmtpEmail(
|
||||
inputs: SmtpEmailStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.SEND_EMAIL_SMTP,
|
||||
BUILTIN_ACTION_DEFINITIONS.SEND_EMAIL_SMTP,
|
||||
inputs,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
executeQuery(
|
||||
inputs: ExecuteQueryStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.EXECUTE_QUERY,
|
||||
BUILTIN_ACTION_DEFINITIONS.EXECUTE_QUERY,
|
||||
inputs,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
queryRows(
|
||||
inputs: QueryRowsStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.QUERY_ROWS,
|
||||
BUILTIN_ACTION_DEFINITIONS.QUERY_ROWS,
|
||||
inputs,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
loop(
|
||||
inputs: LoopStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.LOOP,
|
||||
BUILTIN_ACTION_DEFINITIONS.LOOP,
|
||||
inputs,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
serverLog(
|
||||
input: ServerLogStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.SERVER_LOG,
|
||||
BUILTIN_ACTION_DEFINITIONS.SERVER_LOG,
|
||||
input,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
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,
|
||||
BUILTIN_ACTION_DEFINITIONS.FILTER,
|
||||
input
|
||||
)
|
||||
}
|
||||
|
||||
bash(
|
||||
input: BashStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.EXECUTE_BASH,
|
||||
BUILTIN_ACTION_DEFINITIONS.EXECUTE_BASH,
|
||||
input,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
openai(
|
||||
input: OpenAIStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.OPENAI,
|
||||
BUILTIN_ACTION_DEFINITIONS.OPENAI,
|
||||
input,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
collect(
|
||||
input: CollectStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.COLLECT,
|
||||
BUILTIN_ACTION_DEFINITIONS.COLLECT,
|
||||
input,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
zapier(
|
||||
input: ZapierStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.zapier,
|
||||
BUILTIN_ACTION_DEFINITIONS.zapier,
|
||||
input,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
triggerAutomationRun(
|
||||
input: TriggerAutomationStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.TRIGGER_AUTOMATION_RUN,
|
||||
BUILTIN_ACTION_DEFINITIONS.TRIGGER_AUTOMATION_RUN,
|
||||
input,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
outgoingWebhook(
|
||||
input: OutgoingWebhookStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.OUTGOING_WEBHOOK,
|
||||
BUILTIN_ACTION_DEFINITIONS.OUTGOING_WEBHOOK,
|
||||
input,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
n8n(
|
||||
input: n8nStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.n8n,
|
||||
BUILTIN_ACTION_DEFINITIONS.n8n,
|
||||
input,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
make(
|
||||
input: MakeIntegrationInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.integromat,
|
||||
BUILTIN_ACTION_DEFINITIONS.integromat,
|
||||
input,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
discord(
|
||||
input: DiscordStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.discord,
|
||||
BUILTIN_ACTION_DEFINITIONS.discord,
|
||||
input,
|
||||
opts
|
||||
)
|
||||
}
|
||||
|
||||
delay(
|
||||
input: DelayStepInputs,
|
||||
opts?: { stepName?: string; stepId?: string }
|
||||
): this {
|
||||
return this.step(
|
||||
AutomationActionStepId.DELAY,
|
||||
BUILTIN_ACTION_DEFINITIONS.DELAY,
|
||||
input,
|
||||
opts
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class StepBuilder extends BaseStepBuilder {
|
||||
|
@ -374,110 +135,78 @@ class AutomationBuilder extends BaseStepBuilder {
|
|||
private triggerOutputs: TriggerOutputs
|
||||
private triggerSet = false
|
||||
|
||||
constructor(
|
||||
options: { name?: string; appId?: string; config?: TestConfiguration } = {}
|
||||
) {
|
||||
constructor(config?: TestConfiguration) {
|
||||
super()
|
||||
this.config = options.config || setup.getConfig()
|
||||
this.config = config || setup.getConfig()
|
||||
this.triggerOutputs = { fields: {} }
|
||||
this.automationConfig = {
|
||||
name: options.name || `Test Automation ${uuidv4()}`,
|
||||
name: `Test Automation ${uuidv4()}`,
|
||||
definition: {
|
||||
steps: [],
|
||||
trigger: {} as AutomationTrigger,
|
||||
trigger: {
|
||||
...TRIGGER_DEFINITIONS[AutomationTriggerStepId.APP],
|
||||
stepId: AutomationTriggerStepId.APP,
|
||||
inputs: this.triggerOutputs,
|
||||
id: uuidv4(),
|
||||
},
|
||||
stepNames: {},
|
||||
},
|
||||
type: "automation",
|
||||
appId: options.appId ?? this.config.getAppId(),
|
||||
appId: this.config.getAppId(),
|
||||
}
|
||||
}
|
||||
|
||||
// TRIGGERS
|
||||
rowSaved(inputs: RowCreatedTriggerInputs, outputs: RowCreatedTriggerOutputs) {
|
||||
this.triggerOutputs = outputs
|
||||
return this.trigger(
|
||||
TRIGGER_DEFINITIONS.ROW_SAVED,
|
||||
AutomationTriggerStepId.ROW_SAVED,
|
||||
inputs,
|
||||
outputs
|
||||
)
|
||||
name(n: string): this {
|
||||
this.automationConfig.name = n
|
||||
return this
|
||||
}
|
||||
|
||||
rowUpdated(
|
||||
inputs: RowUpdatedTriggerInputs,
|
||||
outputs: RowUpdatedTriggerOutputs
|
||||
) {
|
||||
this.triggerOutputs = outputs
|
||||
return this.trigger(
|
||||
TRIGGER_DEFINITIONS.ROW_UPDATED,
|
||||
AutomationTriggerStepId.ROW_UPDATED,
|
||||
inputs,
|
||||
outputs
|
||||
)
|
||||
}
|
||||
|
||||
rowDeleted(
|
||||
inputs: RowDeletedTriggerInputs,
|
||||
outputs: RowDeletedTriggerOutputs
|
||||
) {
|
||||
this.triggerOutputs = outputs
|
||||
return this.trigger(
|
||||
TRIGGER_DEFINITIONS.ROW_DELETED,
|
||||
AutomationTriggerStepId.ROW_DELETED,
|
||||
inputs,
|
||||
outputs
|
||||
)
|
||||
}
|
||||
|
||||
appAction(outputs: AppActionTriggerOutputs, inputs?: AppActionTriggerInputs) {
|
||||
this.triggerOutputs = outputs
|
||||
return this.trigger(
|
||||
TRIGGER_DEFINITIONS.APP,
|
||||
AutomationTriggerStepId.APP,
|
||||
inputs,
|
||||
outputs
|
||||
)
|
||||
}
|
||||
|
||||
webhook(outputs: WebhookTriggerOutputs, inputs?: WebhookTriggerInputs) {
|
||||
this.triggerOutputs = outputs
|
||||
return this.trigger(
|
||||
TRIGGER_DEFINITIONS.WEBHOOK,
|
||||
AutomationTriggerStepId.WEBHOOK,
|
||||
inputs,
|
||||
outputs
|
||||
)
|
||||
}
|
||||
|
||||
cron(inputs: CronTriggerInputs, outputs?: CronTriggerOutputs) {
|
||||
this.triggerOutputs = outputs
|
||||
return this.trigger(
|
||||
TRIGGER_DEFINITIONS.CRON,
|
||||
AutomationTriggerStepId.CRON,
|
||||
inputs,
|
||||
outputs
|
||||
)
|
||||
}
|
||||
|
||||
private trigger<TStep extends AutomationTriggerStepId>(
|
||||
triggerSchema: AutomationTriggerDefinition,
|
||||
stepId: TStep,
|
||||
inputs?: AutomationTriggerInputs<TStep>,
|
||||
outputs?: TriggerOutputs
|
||||
): this {
|
||||
protected triggerInputOutput<
|
||||
TStep extends AutomationTriggerStepId,
|
||||
TInput = AutomationTriggerInputs<TStep>,
|
||||
TOutput = AutomationTriggerOutputs<TStep>
|
||||
>(stepId: TStep) {
|
||||
return (inputs: TInput, outputs?: TOutput) => {
|
||||
if (this.triggerSet) {
|
||||
throw new Error("Only one trigger can be set for an automation.")
|
||||
}
|
||||
this.triggerOutputs = outputs as TriggerOutputs | undefined
|
||||
this.automationConfig.definition.trigger = {
|
||||
...triggerSchema,
|
||||
...TRIGGER_DEFINITIONS[stepId],
|
||||
stepId,
|
||||
inputs: inputs || ({} as any),
|
||||
inputs,
|
||||
id: uuidv4(),
|
||||
}
|
||||
this.triggerOutputs = outputs
|
||||
} as AutomationTrigger
|
||||
this.triggerSet = true
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
protected triggerOutputOnly<
|
||||
TStep extends AutomationTriggerStepId,
|
||||
TOutput = AutomationTriggerOutputs<TStep>
|
||||
>(stepId: TStep) {
|
||||
return (outputs: TOutput) => {
|
||||
this.triggerOutputs = outputs as TriggerOutputs
|
||||
this.automationConfig.definition.trigger = {
|
||||
...TRIGGER_DEFINITIONS[stepId],
|
||||
stepId,
|
||||
id: uuidv4(),
|
||||
} as AutomationTrigger
|
||||
this.triggerSet = true
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
rowUpdated = this.triggerInputOutput(AutomationTriggerStepId.ROW_UPDATED)
|
||||
rowDeleted = this.triggerInputOutput(AutomationTriggerStepId.ROW_DELETED)
|
||||
webhook = this.triggerInputOutput(AutomationTriggerStepId.WEBHOOK)
|
||||
cron = this.triggerInputOutput(AutomationTriggerStepId.CRON)
|
||||
|
||||
branch(branchConfig: BranchConfig): this {
|
||||
this.addBranchStep(branchConfig)
|
||||
|
@ -491,9 +220,6 @@ class AutomationBuilder extends BaseStepBuilder {
|
|||
}
|
||||
|
||||
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
|
||||
const { automation } = await this.config.api.automation.post(this.build())
|
||||
return automation
|
||||
|
@ -518,10 +244,6 @@ class AutomationBuilder extends BaseStepBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
export function createAutomationBuilder(options?: {
|
||||
name?: string
|
||||
appId?: string
|
||||
config?: TestConfiguration
|
||||
}) {
|
||||
return new AutomationBuilder(options)
|
||||
export function createAutomationBuilder(config: TestConfiguration) {
|
||||
return new AutomationBuilder(config)
|
||||
}
|
||||
|
|
|
@ -52,6 +52,12 @@ import {
|
|||
RowDeletedTriggerInputs,
|
||||
BranchStepInputs,
|
||||
BaseAutomationOutputs,
|
||||
AppActionTriggerOutputs,
|
||||
CronTriggerOutputs,
|
||||
RowDeletedTriggerOutputs,
|
||||
RowCreatedTriggerOutputs,
|
||||
RowUpdatedTriggerOutputs,
|
||||
WebhookTriggerOutputs,
|
||||
} from "./StepInputsOutputs"
|
||||
|
||||
export type ActionImplementations<T extends Hosting> = {
|
||||
|
@ -341,6 +347,23 @@ export type AutomationTriggerInputs<T extends AutomationTriggerStepId> =
|
|||
? Record<string, any>
|
||||
: never
|
||||
|
||||
export type AutomationTriggerOutputs<T extends AutomationTriggerStepId> =
|
||||
T extends AutomationTriggerStepId.APP
|
||||
? AppActionTriggerOutputs
|
||||
: T extends AutomationTriggerStepId.CRON
|
||||
? CronTriggerOutputs
|
||||
: T extends AutomationTriggerStepId.ROW_ACTION
|
||||
? Record<string, any>
|
||||
: T extends AutomationTriggerStepId.ROW_DELETED
|
||||
? RowDeletedTriggerOutputs
|
||||
: T extends AutomationTriggerStepId.ROW_SAVED
|
||||
? RowCreatedTriggerOutputs
|
||||
: T extends AutomationTriggerStepId.ROW_UPDATED
|
||||
? RowUpdatedTriggerOutputs
|
||||
: T extends AutomationTriggerStepId.WEBHOOK
|
||||
? WebhookTriggerOutputs
|
||||
: never
|
||||
|
||||
export interface AutomationTriggerSchema<
|
||||
TTrigger extends AutomationTriggerStepId
|
||||
> extends AutomationStepSchemaBase {
|
||||
|
|
Loading…
Reference in New Issue