update automation test builder to support ...building

This commit is contained in:
Peter Clement 2024-09-04 16:37:33 +01:00
parent d80123bbcb
commit 2135dbca67
4 changed files with 84 additions and 174 deletions

View File

@ -15,6 +15,7 @@ import { Automation, FieldType, Table } from "@budibase/types"
import { mocks } from "@budibase/backend-core/tests" import { mocks } from "@budibase/backend-core/tests"
import { FilterConditions } from "../../../automations/steps/filter" import { FilterConditions } from "../../../automations/steps/filter"
import { removeDeprecated } from "../../../automations/utils" import { removeDeprecated } from "../../../automations/utils"
import { createAutomationBuilder } from "../../../automations/tests/utilities/AutomationTestBuilder"
const MAX_RETRIES = 4 const MAX_RETRIES = 4
let { let {
@ -25,8 +26,6 @@ let {
collectAutomation, collectAutomation,
filterAutomation, filterAutomation,
updateRowAutomationWithFilters, updateRowAutomationWithFilters,
branchAutomationIncorrectPosition,
branchAutomation,
} = setup.structures } = setup.structures
describe("/automations", () => { describe("/automations", () => {
@ -124,23 +123,22 @@ 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 = branchAutomationIncorrectPosition() const automation = createAutomationBuilder({
name: "String Equality Branching",
await config.api.automation.post(automation, { appId: config.getAppId(),
status: 400,
body: {
message:
'Invalid body - "definition.steps[0].inputs.branches" must contain at least 1 items',
},
}) })
}) .appAction({ fields: { status: "active" } })
.branch({
it("Should check validation on an automation that has a branch step with no children", async () => { activeBranch: {
const automation = branchAutomationIncorrectPosition() steps: stepBuilder =>
automation.definition.steps[0].inputs.branches = [ stepBuilder.serverLog({ text: "Active user" }),
{ name: "test", condition: { equal: { "steps.1.success": "true" } } }, condition: {
] equal: { "trigger.fields.status": "active" },
automation.definition.steps[0].inputs.children = {} },
},
})
.serverLog({ text: "Inactive user" })
.build()
await config.api.automation.post(automation, { await config.api.automation.post(automation, {
status: 400, status: 400,
@ -151,41 +149,73 @@ describe("/automations", () => {
}) })
}) })
it("Should check validation on a branch step with empty conditions", async () => { it("Should check validation on an automation that has a branch step with no children", async () => {
const automation = branchAutomation() const automation = createAutomationBuilder({
name: "String Equality Branching",
automation.definition.steps[1].inputs.branches = [ appId: config.getAppId(),
{ name: "test", condition: {} }, })
] .appAction({ fields: { status: "active" } })
automation.definition.steps[1].inputs.children = {} .branch({})
.serverLog({ text: "Inactive user" })
.build()
await config.api.automation.post(automation, { await config.api.automation.post(automation, {
status: 400, status: 400,
body: { body: {
message: message:
'Invalid body - "definition.steps[1].inputs.branches[0].condition" must have at least 1 key', 'Invalid body - "definition.steps[0].inputs.branches" must contain at least 1 items',
},
})
})
it("Should check validation on a branch step with empty conditions", async () => {
const automation = createAutomationBuilder({
name: "String Equality Branching",
appId: config.getAppId(),
})
.appAction({ fields: { status: "active" } })
.branch({
activeBranch: {
steps: stepBuilder =>
stepBuilder.serverLog({ text: "Active user" }),
condition: {},
},
})
.build()
await config.api.automation.post(automation, {
status: 400,
body: {
message:
'Invalid body - "definition.steps[0].inputs.branches[0].condition" must have at least 1 key',
}, },
}) })
}) })
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 = branchAutomation() const automation = createAutomationBuilder({
name: "String Equality Branching",
automation.definition.steps[1].inputs.branches = [ appId: config.getAppId(),
{ })
name: "test", .appAction({ fields: { status: "active" } })
condition: { .branch({
INCORRECT: { "steps.1.success": true }, activeBranch: {
steps: stepBuilder =>
stepBuilder.serverLog({ text: "Active user" }),
condition: {
//@ts-ignore
INCORRECT: { "trigger.fields.status": "active" },
},
}, },
}, })
] .serverLog({ text: "Inactive user" })
automation.definition.steps[1].inputs.children = {} .build()
await config.api.automation.post(automation, { await config.api.automation.post(automation, {
status: 400, status: 400,
body: { body: {
message: message:
'Invalid body - "definition.steps[1].inputs.branches[0].condition.INCORRECT" is not allowed', 'Invalid body - "definition.steps[0].inputs.branches[0].condition.INCORRECT" is not allowed',
}, },
}) })
}) })

View File

@ -291,7 +291,9 @@ function generateStepSchema(allowStepTypes: string[]) {
type: Joi.string() type: Joi.string()
.required() .required()
.valid(...allowStepTypes), .valid(...allowStepTypes),
}).unknown(true) })
.unknown(true)
.id("step")
} }
const validateStepsArray = ( const validateStepsArray = (

View File

@ -179,7 +179,7 @@ class AutomationBuilder extends BaseStepBuilder {
private triggerOutputs: any private triggerOutputs: any
private triggerSet: boolean = false private triggerSet: boolean = false
constructor(options: { name?: string } = {}) { constructor(options: { name?: string; appId?: string } = {}) {
super() super()
this.automationConfig = { this.automationConfig = {
name: options.name || `Test Automation ${uuidv4()}`, name: options.name || `Test Automation ${uuidv4()}`,
@ -188,7 +188,7 @@ class AutomationBuilder extends BaseStepBuilder {
trigger: {} as AutomationTrigger, trigger: {} as AutomationTrigger,
}, },
type: "automation", type: "automation",
appId: setup.getConfig().getAppId(), appId: options.appId ?? setup.getConfig().getAppId(),
} }
this.config = setup.getConfig() this.config = setup.getConfig()
} }
@ -261,13 +261,14 @@ class AutomationBuilder extends BaseStepBuilder {
return this return this
} }
branch(branchConfig: BranchConfig): { branch(branchConfig: BranchConfig): this {
run: () => Promise<AutomationResults>
} {
this.addBranchStep(branchConfig) this.addBranchStep(branchConfig)
return { return this
run: () => this.run(), }
}
build(): Automation {
this.automationConfig.definition.steps = this.steps
return this.automationConfig
} }
async run() { async run() {
@ -275,7 +276,7 @@ class AutomationBuilder extends BaseStepBuilder {
throw new Error("Please add a trigger to this automation test") 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.createAutomation(this.automationConfig) const automation = await this.config.createAutomation(this.build())
const results = await testAutomation( const results = await testAutomation(
this.config, this.config,
automation, automation,
@ -295,6 +296,9 @@ class AutomationBuilder extends BaseStepBuilder {
} }
} }
export function createAutomationBuilder(options?: { name?: string }) { export function createAutomationBuilder(options?: {
name?: string
appId?: string
}) {
return new AutomationBuilder(options) return new AutomationBuilder(options)
} }

View File

@ -292,132 +292,6 @@ export function serverLogAutomation(appId?: string): Automation {
} }
} }
export function branchAutomationIncorrectPosition(appId?: string): Automation {
return {
name: "My Automation",
screenId: "kasdkfldsafkl",
live: true,
uiTree: {},
definition: {
trigger: {
stepId: AutomationTriggerStepId.APP,
name: "test",
tagline: "test",
icon: "test",
description: "test",
type: AutomationStepType.TRIGGER,
id: "test",
inputs: { fields: {} },
schema: {
inputs: {
properties: {},
},
outputs: {
properties: {},
},
},
},
steps: [
{
stepId: AutomationActionStepId.BRANCH,
name: "Branch",
tagline: "Console log a value in the backend",
icon: "Monitoring",
description: "Logs the given text to the server (using console.log)",
inputs: {
branches: [],
},
schema: { inputs: { properties: {} }, outputs: { properties: {} } },
id: "y8lkZbeSe",
type: AutomationStepType.LOGIC,
},
{
stepId: AutomationActionStepId.SERVER_LOG,
name: "Backend log",
tagline: "Console log a value in the backend",
icon: "Monitoring",
description: "Logs the given text to the server (using console.log)",
internal: true,
features: {
LOOPING: true,
},
inputs: {
text: "log statement",
},
schema: BUILTIN_ACTION_DEFINITIONS.SERVER_LOG.schema,
id: "y8lkZbeSe",
type: AutomationStepType.ACTION,
},
],
},
type: "automation",
appId: appId!,
}
}
export function branchAutomation(appId?: string): Automation {
return {
name: "My Automation",
screenId: "kasdkfldsafkl",
live: true,
uiTree: {},
definition: {
trigger: {
stepId: AutomationTriggerStepId.APP,
name: "test",
tagline: "test",
icon: "test",
description: "test",
type: AutomationStepType.TRIGGER,
id: "test",
inputs: { fields: {} },
schema: {
inputs: {
properties: {},
},
outputs: {
properties: {},
},
},
},
steps: [
{
stepId: AutomationActionStepId.SERVER_LOG,
name: "Backend log",
tagline: "Console log a value in the backend",
icon: "Monitoring",
description: "Logs the given text to the server (using console.log)",
internal: true,
features: {
LOOPING: true,
},
inputs: {
text: "log statement",
},
schema: BUILTIN_ACTION_DEFINITIONS.SERVER_LOG.schema,
id: "y8lkZbeSe",
type: AutomationStepType.ACTION,
},
{
stepId: AutomationActionStepId.BRANCH,
name: "Branch",
tagline: "Console log a value in the backend",
icon: "Monitoring",
description: "Logs the given text to the server (using console.log)",
inputs: {
branches: [],
},
schema: { inputs: { properties: {} }, outputs: { properties: {} } },
id: "y8lkZbeSe",
type: AutomationStepType.LOGIC,
},
],
},
type: "automation",
appId: appId!,
}
}
export function loopAutomation( export function loopAutomation(
tableId: string, tableId: string,
loopOpts?: LoopInput loopOpts?: LoopInput