Merge remote-tracking branch 'origin/master' into automation-branching-ux-updates

This commit is contained in:
Dean 2024-11-27 10:18:04 +00:00
commit 66b60d36d9
3 changed files with 303 additions and 117 deletions

View File

@ -1,6 +1,7 @@
import * as setup from "./utilities"
import { basicTableWithAttachmentField } from "../../tests/utilities/structures"
import { objectStore } from "@budibase/backend-core"
import { createAutomationBuilder } from "./utilities/AutomationTestBuilder"
async function uploadTestFile(filename: string) {
let bucket = "testbucket"
@ -13,6 +14,7 @@ async function uploadTestFile(filename: string) {
return presignedUrl
}
describe("test the create row action", () => {
let table: any
let row: any
@ -31,30 +33,78 @@ describe("test the create row action", () => {
afterAll(setup.afterAll)
it("should be able to run the action", async () => {
const res = await setup.runStep(config, setup.actions.CREATE_ROW.stepId, {
row,
const result = await createAutomationBuilder({
name: "Test Create Row Flow",
appId: config.getAppId(),
config,
})
expect(res.id).toBeDefined()
expect(res.revision).toBeDefined()
expect(res.success).toEqual(true)
const gottenRow = await config.api.row.get(table._id, res.id)
.appAction({ fields: { status: "new" } })
.serverLog({ text: "Starting create row flow" }, { stepName: "StartLog" })
.createRow({ row }, { stepName: "CreateRow" })
.serverLog(
{ text: "Row created with ID: {{ stepsByName.CreateRow.row._id }}" },
{ stepName: "CreationLog" }
)
.run()
expect(result.steps[1].outputs.success).toBeDefined()
expect(result.steps[1].outputs.id).toBeDefined()
expect(result.steps[1].outputs.revision).toBeDefined()
const gottenRow = await config.api.row.get(
table._id,
result.steps[1].outputs.id
)
expect(gottenRow.name).toEqual("test")
expect(gottenRow.description).toEqual("test")
expect(result.steps[2].outputs.message).toContain(
"Row created with ID: " + result.steps[1].outputs.id
)
})
it("should return an error (not throw) when bad info provided", async () => {
const res = await setup.runStep(config, setup.actions.CREATE_ROW.stepId, {
row: {
tableId: "invalid",
invalid: "invalid",
},
const result = await createAutomationBuilder({
name: "Test Create Row Error Flow",
appId: config.getAppId(),
config,
})
expect(res.success).toEqual(false)
.appAction({ fields: { status: "error" } })
.serverLog({ text: "Starting error test flow" }, { stepName: "StartLog" })
.createRow(
{
row: {
tableId: "invalid",
invalid: "invalid",
},
},
{ stepName: "CreateRow" }
)
.run()
expect(result.steps[1].outputs.success).toEqual(false)
})
it("should check invalid inputs return an error", async () => {
const res = await setup.runStep(config, setup.actions.CREATE_ROW.stepId, {})
expect(res.success).toEqual(false)
const result = await createAutomationBuilder({
name: "Test Create Row Invalid Flow",
appId: config.getAppId(),
config,
})
.appAction({ fields: { status: "invalid" } })
.serverLog({ text: "Testing invalid input" }, { stepName: "StartLog" })
.createRow({ row: {} }, { stepName: "CreateRow" })
.filter({
field: "{{ stepsByName.CreateRow.success }}",
condition: "equal",
value: true,
})
.serverLog(
{ text: "This log should not appear" },
{ stepName: "SkippedLog" }
)
.run()
expect(result.steps[1].outputs.success).toEqual(false)
expect(result.steps.length).toBeLessThan(4)
})
it("should check that an attachment field is sent to storage and parsed", async () => {
@ -76,13 +126,33 @@ describe("test the create row action", () => {
]
attachmentRow.file_attachment = attachmentObject
const res = await setup.runStep(config, setup.actions.CREATE_ROW.stepId, {
row: attachmentRow,
const result = await createAutomationBuilder({
name: "Test Create Row Attachment Flow",
appId: config.getAppId(),
config,
})
.appAction({ fields: { type: "attachment" } })
.serverLog(
{ text: "Processing attachment upload" },
{ stepName: "StartLog" }
)
.createRow({ row: attachmentRow }, { stepName: "CreateRow" })
.filter({
field: "{{ stepsByName.CreateRow.success }}",
condition: "equal",
value: true,
})
.serverLog(
{
text: "Attachment uploaded with key: {{ stepsByName.CreateRow.row.file_attachment.0.key }}",
},
{ stepName: "UploadLog" }
)
.run()
expect(res.success).toEqual(true)
expect(res.row.file_attachment[0]).toHaveProperty("key")
let s3Key = res.row.file_attachment[0].key
expect(result.steps[1].outputs.success).toEqual(true)
expect(result.steps[1].outputs.row.file_attachment[0]).toHaveProperty("key")
let s3Key = result.steps[1].outputs.row.file_attachment[0].key
const client = objectStore.ObjectStore(objectStore.ObjectStoreBuckets.APPS)
@ -111,13 +181,53 @@ describe("test the create row action", () => {
}
attachmentRow.single_file_attachment = attachmentObject
const res = await setup.runStep(config, setup.actions.CREATE_ROW.stepId, {
row: attachmentRow,
const result = await createAutomationBuilder({
name: "Test Create Row Single Attachment Flow",
appId: config.getAppId(),
config,
})
.appAction({ fields: { type: "single-attachment" } })
.serverLog(
{ text: "Processing single attachment" },
{ stepName: "StartLog" }
)
.createRow({ row: attachmentRow }, { stepName: "CreateRow" })
.branch({
success: {
steps: stepBuilder =>
stepBuilder
.serverLog(
{ text: "Single attachment processed" },
{ stepName: "ProcessLog" }
)
.serverLog(
{
text: "File key: {{ stepsByName.CreateRow.row.single_file_attachment.key }}",
},
{ stepName: "KeyLog" }
),
condition: {
equal: { "{{ stepsByName.CreateRow.success }}": true },
},
},
error: {
steps: stepBuilder =>
stepBuilder.serverLog(
{ text: "Failed to process attachment" },
{ stepName: "ErrorLog" }
),
condition: {
equal: { "{{ stepsByName.CreateRow.success }}": false },
},
},
})
.run()
expect(res.success).toEqual(true)
expect(res.row.single_file_attachment).toHaveProperty("key")
let s3Key = res.row.single_file_attachment.key
expect(result.steps[1].outputs.success).toEqual(true)
expect(result.steps[1].outputs.row.single_file_attachment).toHaveProperty(
"key"
)
let s3Key = result.steps[1].outputs.row.single_file_attachment.key
const client = objectStore.ObjectStore(objectStore.ObjectStoreBuckets.APPS)
@ -146,13 +256,50 @@ describe("test the create row action", () => {
}
attachmentRow.single_file_attachment = attachmentObject
const res = await setup.runStep(config, setup.actions.CREATE_ROW.stepId, {
row: attachmentRow,
const result = await createAutomationBuilder({
name: "Test Create Row Invalid Attachment Flow",
appId: config.getAppId(),
config,
})
.appAction({ fields: { type: "invalid-attachment" } })
.serverLog(
{ text: "Testing invalid attachment keys" },
{ stepName: "StartLog" }
)
.createRow({ row: attachmentRow }, { stepName: "CreateRow" })
.branch({
success: {
steps: stepBuilder =>
stepBuilder.serverLog(
{ text: "Unexpected success" },
{ stepName: "UnexpectedLog" }
),
condition: {
equal: { "{{ stepsByName.CreateRow.success }}": true },
},
},
error: {
steps: stepBuilder =>
stepBuilder
.serverLog(
{ text: "Expected error occurred" },
{ stepName: "ErrorLog" }
)
.serverLog(
{ text: "Error: {{ stepsByName.CreateRow.response }}" },
{ stepName: "ErrorDetailsLog" }
),
condition: {
equal: { "{{ stepsByName.CreateRow.success }}": false },
},
},
})
.run()
expect(res.success).toEqual(false)
expect(res.response).toEqual(
expect(result.steps[1].outputs.success).toEqual(false)
expect(result.steps[1].outputs.response).toEqual(
'Error: Attachments must have both "url" and "filename" keys. You have provided: wrongKey, anotherWrongKey'
)
expect(result.steps[2].outputs.status).toEqual("No branch condition met")
})
})

View File

@ -1,52 +1,65 @@
import { createAutomationBuilder } from "./utilities/AutomationTestBuilder"
import * as setup from "./utilities"
describe("test the delete row action", () => {
let table: any
let row: any
let inputs: any
let config = setup.getConfig()
let table: any,
row: any,
config = setup.getConfig()
beforeEach(async () => {
beforeAll(async () => {
await config.init()
table = await config.createTable()
row = await config.createRow()
inputs = {
tableId: table._id,
id: row._id,
revision: row._rev,
}
})
afterAll(setup.afterAll)
it("should be able to run the action", async () => {
const res = await setup.runStep(
config,
setup.actions.DELETE_ROW.stepId,
inputs
)
expect(res.success).toEqual(true)
expect(res.response).toBeDefined()
expect(res.row._id).toEqual(row._id)
})
it("should be able to run the delete row action", async () => {
const builder = createAutomationBuilder({
name: "Delete Row Automation",
})
it("check usage quota attempts", async () => {
await setup.runInProd(async () => {
await setup.runStep(config, setup.actions.DELETE_ROW.stepId, inputs)
await builder
.appAction({ fields: {} })
.deleteRow({
tableId: table._id,
id: row._id,
revision: row._rev,
})
.run()
await config.api.row.get(table._id, row._id, {
status: 404,
})
})
it("should check invalid inputs return an error", async () => {
const res = await setup.runStep(config, setup.actions.DELETE_ROW.stepId, {})
expect(res.success).toEqual(false)
const builder = createAutomationBuilder({
name: "Invalid Inputs Automation",
})
const results = await builder
.appAction({ fields: {} })
.deleteRow({ tableId: "", id: "", revision: "" })
.run()
expect(results.steps[0].outputs.success).toEqual(false)
})
it("should return an error when table doesn't exist", async () => {
const res = await setup.runStep(config, setup.actions.DELETE_ROW.stepId, {
tableId: "invalid",
id: "invalid",
revision: "invalid",
const builder = createAutomationBuilder({
name: "Nonexistent Table Automation",
})
expect(res.success).toEqual(false)
const results = await builder
.appAction({ fields: {} })
.deleteRow({
tableId: "invalid",
id: "invalid",
revision: "invalid",
})
.run()
expect(results.steps[0].outputs.success).toEqual(false)
})
})

View File

@ -8,58 +8,83 @@ import {
Table,
TableSourceType,
} from "@budibase/types"
import { createAutomationBuilder } from "./utilities/AutomationTestBuilder"
import * as setup from "./utilities"
import * as uuid from "uuid"
describe("test the update row action", () => {
let table: Table, row: Row, inputs: any
let config = setup.getConfig()
let table: Table,
row: Row,
config = setup.getConfig()
beforeAll(async () => {
await config.init()
table = await config.createTable()
row = await config.createRow()
inputs = {
rowId: row._id,
row: {
...row,
name: "Updated name",
// put a falsy option in to be removed
description: "",
},
}
})
afterAll(setup.afterAll)
it("should be able to run the action", async () => {
const res = await setup.runStep(
config,
setup.actions.UPDATE_ROW.stepId,
inputs
it("should be able to run the update row action", async () => {
const builder = createAutomationBuilder({
name: "Update Row Automation",
})
const results = await builder
.appAction({ fields: {} })
.updateRow({
rowId: row._id!,
row: {
...row,
name: "Updated name",
description: "",
},
meta: {},
})
.run()
expect(results.steps[0].outputs.success).toEqual(true)
const updatedRow = await config.api.row.get(
table._id!,
results.steps[0].outputs.id
)
expect(res.success).toEqual(true)
const updatedRow = await config.api.row.get(table._id!, res.id)
expect(updatedRow.name).toEqual("Updated name")
expect(updatedRow.description).not.toEqual("")
})
it("should check invalid inputs return an error", async () => {
const res = await setup.runStep(config, setup.actions.UPDATE_ROW.stepId, {})
expect(res.success).toEqual(false)
const builder = createAutomationBuilder({
name: "Invalid Inputs Automation",
})
const results = await builder
.appAction({ fields: {} })
.updateRow({ meta: {}, row: {}, rowId: "" })
.run()
expect(results.steps[0].outputs.success).toEqual(false)
})
it("should return an error when table doesn't exist", async () => {
const res = await setup.runStep(config, setup.actions.UPDATE_ROW.stepId, {
row: { _id: "invalid" },
rowId: "invalid",
const builder = createAutomationBuilder({
name: "Nonexistent Table Automation",
})
expect(res.success).toEqual(false)
const results = await builder
.appAction({ fields: {} })
.updateRow({
row: { _id: "invalid" },
rowId: "invalid",
meta: {},
})
.run()
expect(results.steps[0].outputs.success).toEqual(false)
})
it("should not overwrite links if those links are not set", async () => {
let linkField: FieldSchema = {
const linkField: FieldSchema = {
type: FieldType.LINK,
name: "",
fieldName: "",
@ -71,7 +96,7 @@ describe("test the update row action", () => {
tableId: InternalTable.USER_METADATA,
}
let table = await config.api.table.save({
const table = await config.api.table.save({
name: uuid.v4(),
type: "table",
sourceType: TableSourceType.INTERNAL,
@ -82,23 +107,22 @@ describe("test the update row action", () => {
},
})
let user1 = await config.createUser()
let user2 = await config.createUser()
const user1 = await config.createUser()
const user2 = await config.createUser()
let row = await config.api.row.save(table._id!, {
const row = await config.api.row.save(table._id!, {
user1: [{ _id: user1._id }],
user2: [{ _id: user2._id }],
})
let getResp = await config.api.row.get(table._id!, row._id!)
expect(getResp.user1[0]._id).toEqual(user1._id)
expect(getResp.user2[0]._id).toEqual(user2._id)
const builder = createAutomationBuilder({
name: "Link Preservation Automation",
})
let stepResp = await setup.runStep(
config,
setup.actions.UPDATE_ROW.stepId,
{
rowId: row._id,
const results = await builder
.appAction({ fields: {} })
.updateRow({
rowId: row._id!,
row: {
_id: row._id,
_rev: row._rev,
@ -106,17 +130,19 @@ describe("test the update row action", () => {
user1: [user2._id],
user2: "",
},
}
)
expect(stepResp.success).toEqual(true)
meta: {},
})
.run()
getResp = await config.api.row.get(table._id!, row._id!)
expect(results.steps[0].outputs.success).toEqual(true)
const getResp = await config.api.row.get(table._id!, row._id!)
expect(getResp.user1[0]._id).toEqual(user2._id)
expect(getResp.user2[0]._id).toEqual(user2._id)
})
it("should overwrite links if those links are not set and we ask it do", async () => {
let linkField: FieldSchema = {
it("should overwrite links if those links are not set and we ask it to", async () => {
const linkField: FieldSchema = {
type: FieldType.LINK,
name: "",
fieldName: "",
@ -128,7 +154,7 @@ describe("test the update row action", () => {
tableId: InternalTable.USER_METADATA,
}
let table = await config.api.table.save({
const table = await config.api.table.save({
name: uuid.v4(),
type: "table",
sourceType: TableSourceType.INTERNAL,
@ -139,23 +165,22 @@ describe("test the update row action", () => {
},
})
let user1 = await config.createUser()
let user2 = await config.createUser()
const user1 = await config.createUser()
const user2 = await config.createUser()
let row = await config.api.row.save(table._id!, {
const row = await config.api.row.save(table._id!, {
user1: [{ _id: user1._id }],
user2: [{ _id: user2._id }],
})
let getResp = await config.api.row.get(table._id!, row._id!)
expect(getResp.user1[0]._id).toEqual(user1._id)
expect(getResp.user2[0]._id).toEqual(user2._id)
const builder = createAutomationBuilder({
name: "Link Overwrite Automation",
})
let stepResp = await setup.runStep(
config,
setup.actions.UPDATE_ROW.stepId,
{
rowId: row._id,
const results = await builder
.appAction({ fields: {} })
.updateRow({
rowId: row._id!,
row: {
_id: row._id,
_rev: row._rev,
@ -170,11 +195,12 @@ describe("test the update row action", () => {
},
},
},
}
)
expect(stepResp.success).toEqual(true)
})
.run()
getResp = await config.api.row.get(table._id!, row._id!)
expect(results.steps[0].outputs.success).toEqual(true)
const getResp = await config.api.row.get(table._id!, row._id!)
expect(getResp.user1[0]._id).toEqual(user2._id)
expect(getResp.user2).toBeUndefined()
})