Merge branch 'master' into fix/feature-flag-checks

This commit is contained in:
Michael Drury 2024-08-15 17:11:38 +01:00 committed by GitHub
commit 483bb585c3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 235 additions and 74 deletions

View File

@ -0,0 +1,51 @@
import {
AutomationActionStepId,
AutomationCustomIOType,
AutomationIOType,
AutomationStepDefinition,
AutomationStepType,
} from "@budibase/types"
export const definition: AutomationStepDefinition = {
name: "Branch",
icon: "Branch3",
tagline: "Branch from this step",
description: "Branching",
stepId: AutomationActionStepId.BRANCH,
internal: true,
features: {},
inputs: {},
schema: {
inputs: {
properties: {
branches: {
properties: {
name: {
type: AutomationIOType.STRING,
},
condition: {
customType: AutomationCustomIOType.FILTERS,
},
},
},
children: {
type: AutomationIOType.ARRAY,
},
},
required: ["conditions"],
},
outputs: {
properties: {
branchName: {
type: AutomationIOType.STRING,
},
result: {
type: AutomationIOType.BOOLEAN,
description: "Whether the condition was met",
},
},
required: ["output"],
},
},
type: AutomationStepType.LOGIC,
}

View File

@ -7,7 +7,7 @@ import {
ServerLogStepOutputs,
FieldType,
} from "@budibase/types"
import { createAutomationBuilder } from "../utilities/AutomationBuilder"
import { createAutomationBuilder } from "../utilities/AutomationTestBuilder"
import { DatabaseName } from "../../../integrations/tests/utils"
describe("Automation Scenarios", () => {
@ -23,6 +23,43 @@ describe("Automation Scenarios", () => {
afterAll(setup.afterAll)
// eslint-disable-next-line jest/no-commented-out-tests
// describe("Branching automations", () => {
// eslint-disable-next-line jest/no-commented-out-tests
// it("should run an automation with a trigger, loop, and create row step", async () => {
// const builder = createAutomationBuilder({
// name: "Test Trigger with Loop and Create Row",
// })
// builder
// .serverLog({ text: "Starting automation" })
// .branch({
// topLevelBranch1: {
// steps: stepBuilder =>
// stepBuilder.serverLog({ text: "Branch 1" }).branch({
// branch1: {
// steps: stepBuilder =>
// stepBuilder.serverLog({ text: "Branch 1.1" }),
// condition: { notEmpty: { column: 10 } },
// },
// branch2: {
// steps: stepBuilder =>
// stepBuilder.serverLog({ text: "Branch 1.2" }),
// condition: { fuzzy: { column: "sadsd" } },
// },
// }),
// condition: { equal: { column: 10 } },
// },
// topLevelBranch2: {
// steps: stepBuilder => stepBuilder.serverLog({ text: "Branch 2" }),
// condition: { equal: { column: 20 } },
// },
// })
// .run()
// })
// })
describe("Loop automations", () => {
it("should run an automation with a trigger, loop, and create row step", async () => {
const builder = createAutomationBuilder({

View File

@ -30,10 +30,13 @@ import {
AutomationStepInputs,
AutomationTriggerInputs,
ServerLogStepInputs,
BranchStepInputs,
SearchFilters,
Branch,
} from "@budibase/types"
import {} from "../../steps/loop"
import TestConfiguration from "../../../tests/utilities/TestConfiguration"
import * as setup from "../utilities"
import { definition } from "../../../automations/steps/branch"
type TriggerOutputs =
| RowCreatedTriggerOutputs
@ -43,69 +46,56 @@ type TriggerOutputs =
| CronTriggerOutputs
| undefined
class AutomationBuilder {
private automationConfig: Automation = {
name: "",
definition: {
steps: [],
trigger: {} as AutomationTrigger,
},
type: "automation",
appId: setup.getConfig().getAppId(),
}
private config: TestConfiguration = setup.getConfig()
private triggerOutputs: TriggerOutputs
private triggerSet: boolean = false
type StepBuilderFunction = (stepBuilder: StepBuilder) => void
constructor(options: { name?: string } = {}) {
this.automationConfig.name = options.name || `Test Automation ${uuidv4()}`
type BranchConfig = {
[key: string]: {
steps: StepBuilderFunction
condition: SearchFilters
}
}
// TRIGGERS
rowSaved(inputs: RowCreatedTriggerInputs, outputs: RowCreatedTriggerOutputs) {
this.triggerOutputs = outputs
return this.trigger(
TRIGGER_DEFINITIONS.ROW_SAVED,
AutomationTriggerStepId.ROW_SAVED,
inputs,
outputs
)
class BaseStepBuilder {
protected steps: AutomationStep[] = []
protected step<TStep extends AutomationActionStepId>(
stepId: TStep,
stepSchema: Omit<AutomationStep, "id" | "stepId" | "inputs">,
inputs: AutomationStepInputs<TStep>
): this {
this.steps.push({
...stepSchema,
inputs: inputs as any,
id: uuidv4(),
stepId,
})
return this
}
rowUpdated(
inputs: RowUpdatedTriggerInputs,
outputs: RowUpdatedTriggerOutputs
) {
this.triggerOutputs = outputs
return this.trigger(
TRIGGER_DEFINITIONS.ROW_UPDATED,
AutomationTriggerStepId.ROW_UPDATED,
inputs,
outputs
)
protected addBranchStep(branchConfig: BranchConfig): void {
const branchStepInputs: BranchStepInputs = {
branches: [] as Branch[],
children: {},
}
rowDeleted(
inputs: RowDeletedTriggerInputs,
outputs: RowDeletedTriggerOutputs
) {
this.triggerOutputs = outputs
return this.trigger(
TRIGGER_DEFINITIONS.ROW_DELETED,
AutomationTriggerStepId.ROW_DELETED,
inputs,
outputs
)
}
Object.entries(branchConfig).forEach(([key, branch]) => {
const stepBuilder = new StepBuilder()
branch.steps(stepBuilder)
appAction(outputs: AppActionTriggerOutputs, inputs?: AppActionTriggerInputs) {
this.triggerOutputs = outputs
return this.trigger(
TRIGGER_DEFINITIONS.APP,
AutomationTriggerStepId.APP,
inputs,
outputs
)
branchStepInputs.branches.push({
name: key,
condition: branch.condition,
})
branchStepInputs.children![key] = stepBuilder.build()
})
const branchStep: AutomationStep = {
...definition,
id: uuidv4(),
stepId: AutomationActionStepId.BRANCH,
inputs: branchStepInputs,
}
this.steps.push(branchStep)
}
// STEPS
@ -171,6 +161,84 @@ class AutomationBuilder {
input
)
}
}
class StepBuilder extends BaseStepBuilder {
build(): AutomationStep[] {
return this.steps
}
branch(branchConfig: BranchConfig): this {
this.addBranchStep(branchConfig)
return this
}
}
class AutomationBuilder extends BaseStepBuilder {
private automationConfig: Automation
private config: TestConfiguration
private triggerOutputs: any
private triggerSet: boolean = false
constructor(options: { name?: string } = {}) {
super()
this.automationConfig = {
name: options.name || `Test Automation ${uuidv4()}`,
definition: {
steps: [],
trigger: {} as AutomationTrigger,
},
type: "automation",
appId: setup.getConfig().getAppId(),
}
this.config = setup.getConfig()
}
// TRIGGERS
rowSaved(inputs: RowCreatedTriggerInputs, outputs: RowCreatedTriggerOutputs) {
this.triggerOutputs = outputs
return this.trigger(
TRIGGER_DEFINITIONS.ROW_SAVED,
AutomationTriggerStepId.ROW_SAVED,
inputs,
outputs
)
}
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
)
}
private trigger<TStep extends AutomationTriggerStepId>(
triggerSchema: AutomationTriggerDefinition,
@ -181,7 +249,6 @@ class AutomationBuilder {
if (this.triggerSet) {
throw new Error("Only one trigger can be set for an automation.")
}
this.automationConfig.definition.trigger = {
...triggerSchema,
stepId,
@ -194,21 +261,20 @@ class AutomationBuilder {
return this
}
private step<TStep extends AutomationActionStepId>(
stepId: TStep,
stepSchema: Omit<AutomationStep, "id" | "stepId" | "inputs">,
inputs: AutomationStepInputs<TStep>
): this {
this.automationConfig.definition.steps.push({
...stepSchema,
inputs: inputs as any,
id: uuidv4(),
stepId,
})
return this
branch(branchConfig: BranchConfig): {
run: () => Promise<AutomationResults>
} {
this.addBranchStep(branchConfig)
return {
run: () => this.run(),
}
}
async run() {
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.createAutomation(this.automationConfig)
const results = await testAutomation(
this.config,
@ -218,7 +284,9 @@ class AutomationBuilder {
return this.processResults(results)
}
private processResults(results: { body: AutomationResults }) {
private processResults(results: {
body: AutomationResults
}): AutomationResults {
results.body.steps.shift()
return {
trigger: results.body.trigger,

View File

@ -111,10 +111,15 @@ export type LoopStepOutputs = {
}
export type BranchStepInputs = {
conditions: SearchFilters
branches: Branch[]
children?: Record<string, AutomationStep[]>
}
export type Branch = {
name: string
condition: SearchFilters
}
export type MakeIntegrationInputs = {
url: string
body: any