Merge branch 'master' into ai-configs-design-updates
This commit is contained in:
commit
3b32eb89cb
|
@ -5,6 +5,7 @@ import {
|
||||||
LoopStepType,
|
LoopStepType,
|
||||||
CreateRowStepOutputs,
|
CreateRowStepOutputs,
|
||||||
ServerLogStepOutputs,
|
ServerLogStepOutputs,
|
||||||
|
FieldType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { createAutomationBuilder } from "../utilities/AutomationTestBuilder"
|
import { createAutomationBuilder } from "../utilities/AutomationTestBuilder"
|
||||||
|
|
||||||
|
@ -269,4 +270,145 @@ describe("Loop automations", () => {
|
||||||
|
|
||||||
expect(results.steps[1].outputs.message).toContain("- 3")
|
expect(results.steps[1].outputs.message).toContain("- 3")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should run an automation with a loop and update row step", async () => {
|
||||||
|
const table = await config.createTable({
|
||||||
|
name: "TestTable",
|
||||||
|
type: "table",
|
||||||
|
schema: {
|
||||||
|
name: {
|
||||||
|
name: "name",
|
||||||
|
type: FieldType.STRING,
|
||||||
|
constraints: {
|
||||||
|
presence: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
name: "value",
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
constraints: {
|
||||||
|
presence: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const rows = [
|
||||||
|
{ name: "Row 1", value: 1, tableId: table._id },
|
||||||
|
{ name: "Row 2", value: 2, tableId: table._id },
|
||||||
|
{ name: "Row 3", value: 3, tableId: table._id },
|
||||||
|
]
|
||||||
|
|
||||||
|
await config.api.row.bulkImport(table._id!, { rows })
|
||||||
|
|
||||||
|
const builder = createAutomationBuilder({
|
||||||
|
name: "Test Loop and Update Row",
|
||||||
|
})
|
||||||
|
|
||||||
|
const results = await builder
|
||||||
|
.appAction({ fields: {} })
|
||||||
|
.queryRows({
|
||||||
|
tableId: table._id!,
|
||||||
|
})
|
||||||
|
.loop({
|
||||||
|
option: LoopStepType.ARRAY,
|
||||||
|
binding: "{{ steps.1.rows }}",
|
||||||
|
})
|
||||||
|
.updateRow({
|
||||||
|
rowId: "{{ loop.currentItem._id }}",
|
||||||
|
row: {
|
||||||
|
name: "Updated {{ loop.currentItem.name }}",
|
||||||
|
value: "{{ loop.currentItem.value }}",
|
||||||
|
tableId: table._id,
|
||||||
|
},
|
||||||
|
meta: {},
|
||||||
|
})
|
||||||
|
.queryRows({
|
||||||
|
tableId: table._id!,
|
||||||
|
})
|
||||||
|
.run()
|
||||||
|
|
||||||
|
const expectedRows = [
|
||||||
|
{ name: "Updated Row 1", value: 1 },
|
||||||
|
{ name: "Updated Row 2", value: 2 },
|
||||||
|
{ name: "Updated Row 3", value: 3 },
|
||||||
|
]
|
||||||
|
|
||||||
|
expect(results.steps[1].outputs.items).toEqual(
|
||||||
|
expect.arrayContaining(
|
||||||
|
expectedRows.map(row =>
|
||||||
|
expect.objectContaining({
|
||||||
|
success: true,
|
||||||
|
row: expect.objectContaining(row),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(results.steps[2].outputs.rows).toEqual(
|
||||||
|
expect.arrayContaining(
|
||||||
|
expectedRows.map(row => expect.objectContaining(row))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(results.steps[1].outputs.items).toHaveLength(expectedRows.length)
|
||||||
|
expect(results.steps[2].outputs.rows).toHaveLength(expectedRows.length)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should run an automation with a loop and delete row step", async () => {
|
||||||
|
const table = await config.createTable({
|
||||||
|
name: "TestTable",
|
||||||
|
type: "table",
|
||||||
|
schema: {
|
||||||
|
name: {
|
||||||
|
name: "name",
|
||||||
|
type: FieldType.STRING,
|
||||||
|
constraints: {
|
||||||
|
presence: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
name: "value",
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
constraints: {
|
||||||
|
presence: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const rows = [
|
||||||
|
{ name: "Row 1", value: 1, tableId: table._id },
|
||||||
|
{ name: "Row 2", value: 2, tableId: table._id },
|
||||||
|
{ name: "Row 3", value: 3, tableId: table._id },
|
||||||
|
]
|
||||||
|
|
||||||
|
await config.api.row.bulkImport(table._id!, { rows })
|
||||||
|
|
||||||
|
const builder = createAutomationBuilder({
|
||||||
|
name: "Test Loop and Delete Row",
|
||||||
|
})
|
||||||
|
|
||||||
|
const results = await builder
|
||||||
|
.appAction({ fields: {} })
|
||||||
|
.queryRows({
|
||||||
|
tableId: table._id!,
|
||||||
|
})
|
||||||
|
.loop({
|
||||||
|
option: LoopStepType.ARRAY,
|
||||||
|
binding: "{{ steps.1.rows }}",
|
||||||
|
})
|
||||||
|
.deleteRow({
|
||||||
|
tableId: table._id!,
|
||||||
|
id: "{{ loop.currentItem._id }}",
|
||||||
|
})
|
||||||
|
.queryRows({
|
||||||
|
tableId: table._id!,
|
||||||
|
})
|
||||||
|
.run()
|
||||||
|
|
||||||
|
expect(results.steps).toHaveLength(3)
|
||||||
|
|
||||||
|
expect(results.steps[2].outputs.rows).toHaveLength(0)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import * as automation from "../../index"
|
import * as automation from "../../index"
|
||||||
import * as setup from "../utilities"
|
import * as setup from "../utilities"
|
||||||
import { LoopStepType, FieldType } from "@budibase/types"
|
import { LoopStepType, FieldType, Table } from "@budibase/types"
|
||||||
import { createAutomationBuilder } from "../utilities/AutomationTestBuilder"
|
import { createAutomationBuilder } from "../utilities/AutomationTestBuilder"
|
||||||
import { DatabaseName } from "../../../integrations/tests/utils"
|
import { DatabaseName } from "../../../integrations/tests/utils"
|
||||||
|
import { FilterConditions } from "../../../automations/steps/filter"
|
||||||
|
|
||||||
describe("Automation Scenarios", () => {
|
describe("Automation Scenarios", () => {
|
||||||
let config = setup.getConfig()
|
let config = setup.getConfig()
|
||||||
|
@ -195,6 +196,91 @@ describe("Automation Scenarios", () => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should trigger an automation which creates and then updates a row", async () => {
|
||||||
|
const table = await config.createTable({
|
||||||
|
name: "TestTable",
|
||||||
|
type: "table",
|
||||||
|
schema: {
|
||||||
|
name: {
|
||||||
|
name: "name",
|
||||||
|
type: FieldType.STRING,
|
||||||
|
constraints: {
|
||||||
|
presence: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
name: "value",
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
constraints: {
|
||||||
|
presence: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const builder = createAutomationBuilder({
|
||||||
|
name: "Test Create and Update Row",
|
||||||
|
})
|
||||||
|
|
||||||
|
const results = await builder
|
||||||
|
.appAction({ fields: {} })
|
||||||
|
.createRow(
|
||||||
|
{
|
||||||
|
row: {
|
||||||
|
name: "Initial Row",
|
||||||
|
value: 1,
|
||||||
|
tableId: table._id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ stepName: "CreateRowStep" }
|
||||||
|
)
|
||||||
|
.updateRow(
|
||||||
|
{
|
||||||
|
rowId: "{{ steps.CreateRowStep.row._id }}",
|
||||||
|
row: {
|
||||||
|
name: "Updated Row",
|
||||||
|
value: 2,
|
||||||
|
tableId: table._id,
|
||||||
|
},
|
||||||
|
meta: {},
|
||||||
|
},
|
||||||
|
{ stepName: "UpdateRowStep" }
|
||||||
|
)
|
||||||
|
.queryRows(
|
||||||
|
{
|
||||||
|
tableId: table._id!,
|
||||||
|
},
|
||||||
|
{ stepName: "QueryRowsStep" }
|
||||||
|
)
|
||||||
|
.run()
|
||||||
|
|
||||||
|
expect(results.steps).toHaveLength(3)
|
||||||
|
|
||||||
|
expect(results.steps[0].outputs).toMatchObject({
|
||||||
|
success: true,
|
||||||
|
row: {
|
||||||
|
name: "Initial Row",
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(results.steps[1].outputs).toMatchObject({
|
||||||
|
success: true,
|
||||||
|
row: {
|
||||||
|
name: "Updated Row",
|
||||||
|
value: 2,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const expectedRows = [{ name: "Updated Row", value: 2 }]
|
||||||
|
|
||||||
|
expect(results.steps[2].outputs.rows).toEqual(
|
||||||
|
expect.arrayContaining(
|
||||||
|
expectedRows.map(row => expect.objectContaining(row))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("Name Based Automations", () => {
|
describe("Name Based Automations", () => {
|
||||||
|
@ -233,4 +319,167 @@ describe("Automation Scenarios", () => {
|
||||||
expect(results.steps[2].outputs.rows).toHaveLength(1)
|
expect(results.steps[2].outputs.rows).toHaveLength(1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
describe("Automations with filter", () => {
|
||||||
|
let table: Table
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
table = await config.createTable({
|
||||||
|
name: "TestTable",
|
||||||
|
type: "table",
|
||||||
|
schema: {
|
||||||
|
name: {
|
||||||
|
name: "name",
|
||||||
|
type: FieldType.STRING,
|
||||||
|
constraints: {
|
||||||
|
presence: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
name: "value",
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
constraints: {
|
||||||
|
presence: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should stop an automation if the condition is not met", async () => {
|
||||||
|
const builder = createAutomationBuilder({
|
||||||
|
name: "Test Equal",
|
||||||
|
})
|
||||||
|
|
||||||
|
const results = await builder
|
||||||
|
.appAction({ fields: {} })
|
||||||
|
.createRow({
|
||||||
|
row: {
|
||||||
|
name: "Equal Test",
|
||||||
|
value: 10,
|
||||||
|
tableId: table._id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.queryRows({
|
||||||
|
tableId: table._id!,
|
||||||
|
})
|
||||||
|
.filter({
|
||||||
|
field: "{{ steps.2.rows.0.value }}",
|
||||||
|
condition: FilterConditions.EQUAL,
|
||||||
|
value: 20,
|
||||||
|
})
|
||||||
|
.serverLog({ text: "Equal condition met" })
|
||||||
|
.run()
|
||||||
|
|
||||||
|
expect(results.steps[2].outputs.success).toBeTrue()
|
||||||
|
expect(results.steps[2].outputs.result).toBeFalse()
|
||||||
|
expect(results.steps[3]).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should continue the automation if the condition is met", async () => {
|
||||||
|
const builder = createAutomationBuilder({
|
||||||
|
name: "Test Not Equal",
|
||||||
|
})
|
||||||
|
|
||||||
|
const results = await builder
|
||||||
|
.appAction({ fields: {} })
|
||||||
|
.createRow({
|
||||||
|
row: {
|
||||||
|
name: "Not Equal Test",
|
||||||
|
value: 10,
|
||||||
|
tableId: table._id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.queryRows({
|
||||||
|
tableId: table._id!,
|
||||||
|
})
|
||||||
|
.filter({
|
||||||
|
field: "{{ steps.2.rows.0.value }}",
|
||||||
|
condition: FilterConditions.NOT_EQUAL,
|
||||||
|
value: 20,
|
||||||
|
})
|
||||||
|
.serverLog({ text: "Not Equal condition met" })
|
||||||
|
.run()
|
||||||
|
|
||||||
|
expect(results.steps[2].outputs.success).toBeTrue()
|
||||||
|
expect(results.steps[2].outputs.result).toBeTrue()
|
||||||
|
expect(results.steps[3].outputs.success).toBeTrue()
|
||||||
|
})
|
||||||
|
|
||||||
|
const testCases = [
|
||||||
|
{
|
||||||
|
condition: FilterConditions.EQUAL,
|
||||||
|
value: 10,
|
||||||
|
rowValue: 10,
|
||||||
|
expectPass: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
condition: FilterConditions.NOT_EQUAL,
|
||||||
|
value: 10,
|
||||||
|
rowValue: 20,
|
||||||
|
expectPass: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
condition: FilterConditions.GREATER_THAN,
|
||||||
|
value: 10,
|
||||||
|
rowValue: 15,
|
||||||
|
expectPass: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
condition: FilterConditions.LESS_THAN,
|
||||||
|
value: 10,
|
||||||
|
rowValue: 5,
|
||||||
|
expectPass: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
condition: FilterConditions.GREATER_THAN,
|
||||||
|
value: 10,
|
||||||
|
rowValue: 5,
|
||||||
|
expectPass: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
condition: FilterConditions.LESS_THAN,
|
||||||
|
value: 10,
|
||||||
|
rowValue: 15,
|
||||||
|
expectPass: false,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
it.each(testCases)(
|
||||||
|
"should pass the filter when condition is $condition",
|
||||||
|
async ({ condition, value, rowValue, expectPass }) => {
|
||||||
|
const builder = createAutomationBuilder({
|
||||||
|
name: `Test ${condition}`,
|
||||||
|
})
|
||||||
|
|
||||||
|
const results = await builder
|
||||||
|
.appAction({ fields: {} })
|
||||||
|
.createRow({
|
||||||
|
row: {
|
||||||
|
name: `${condition} Test`,
|
||||||
|
value: rowValue,
|
||||||
|
tableId: table._id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.queryRows({
|
||||||
|
tableId: table._id!,
|
||||||
|
})
|
||||||
|
.filter({
|
||||||
|
field: "{{ steps.2.rows.0.value }}",
|
||||||
|
condition,
|
||||||
|
value,
|
||||||
|
})
|
||||||
|
.serverLog({
|
||||||
|
text: `${condition} condition ${expectPass ? "passed" : "failed"}`,
|
||||||
|
})
|
||||||
|
.run()
|
||||||
|
|
||||||
|
expect(results.steps[2].outputs.result).toBe(expectPass)
|
||||||
|
if (expectPass) {
|
||||||
|
expect(results.steps[3].outputs.success).toBeTrue()
|
||||||
|
} else {
|
||||||
|
expect(results.steps[3]).toBeUndefined()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -33,6 +33,7 @@ import {
|
||||||
BranchStepInputs,
|
BranchStepInputs,
|
||||||
SearchFilters,
|
SearchFilters,
|
||||||
Branch,
|
Branch,
|
||||||
|
FilterStepInputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import TestConfiguration from "../../../tests/utilities/TestConfiguration"
|
import TestConfiguration from "../../../tests/utilities/TestConfiguration"
|
||||||
import * as setup from "../utilities"
|
import * as setup from "../utilities"
|
||||||
|
@ -181,6 +182,14 @@ class BaseStepBuilder {
|
||||||
opts?.stepName
|
opts?.stepName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filter(input: FilterStepInputs): this {
|
||||||
|
return this.step(
|
||||||
|
AutomationActionStepId.FILTER,
|
||||||
|
BUILTIN_ACTION_DEFINITIONS.FILTER,
|
||||||
|
input
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class StepBuilder extends BaseStepBuilder {
|
class StepBuilder extends BaseStepBuilder {
|
||||||
build(): AutomationStep[] {
|
build(): AutomationStep[] {
|
||||||
|
|
Loading…
Reference in New Issue