Merge branch 'master' into execute-script-v2

This commit is contained in:
deanhannigan 2025-02-12 14:17:54 +00:00 committed by GitHub
commit 06d4948d42
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 47 additions and 80 deletions

View File

@ -1,6 +1,6 @@
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"version": "3.4.5",
"version": "3.4.6",
"npmClient": "yarn",
"concurrency": 20,
"command": {

View File

@ -93,7 +93,10 @@ const handleMouseDown = (e: MouseEvent) => {
// Handle iframe clicks by detecting a loss of focus on the main window
const handleBlur = () => {
if (document.activeElement?.tagName === "IFRAME") {
if (
document.activeElement &&
["IFRAME", "BODY"].includes(document.activeElement.tagName)
) {
handleClick(
new MouseEvent("click", { relatedTarget: document.activeElement })
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,15 +1,15 @@
<script>
import { Layout } from "@budibase/bbui"
import Bulgaria from "../../assets/bulgaria.png"
import Covanta from "../../assets/covanta.png"
import Reworld from "../../assets/reworld.png"
import Schnellecke from "../../assets/schnellecke.png"
const testimonials = [
{
text: "Budibase was the only solution that checked all the boxes for Covanta. Covanta expects to realize $3.2MM in savings due to the elimination of redundant data entry.",
text: "Budibase was the only solution that checked all the boxes for Reworld. Reworld expects to realize $3.2MM in savings due to the elimination of redundant data entry.",
name: "Charles Link",
role: "Senior Director, Data and Analytics",
image: Covanta,
image: Reworld,
imageSize: 105,
},
{

View File

@ -6,6 +6,7 @@ import {
} from "../../../integrations/tests/utils"
import { Knex } from "knex"
import { generator } from "@budibase/backend-core/tests"
import { createAutomationBuilder } from "../utilities/AutomationTestBuilder"
const descriptions = datasourceDescribe({
exclude: [DatabaseName.MONGODB, DatabaseName.SQS],
@ -41,39 +42,34 @@ if (descriptions.length) {
})
it("should be able to execute a query", async () => {
let res = await setup.runStep(
config,
setup.actions.EXECUTE_QUERY.stepId,
{
query: { queryId: query._id },
}
)
expect(res.response).toEqual([{ a: "string", b: 1 }])
expect(res.success).toEqual(true)
const { steps } = await createAutomationBuilder(config)
.onAppAction()
.executeQuery({ query: { queryId: query._id! } })
.test({ fields: {} })
expect(steps[0].outputs.response).toEqual([{ a: "string", b: 1 }])
expect(steps[0].outputs.success).toEqual(true)
})
it("should handle a null query value", async () => {
let res = await setup.runStep(
config,
setup.actions.EXECUTE_QUERY.stepId,
{
query: null,
}
)
expect(res.response.message).toEqual("Invalid inputs")
expect(res.success).toEqual(false)
const { steps } = await createAutomationBuilder(config)
.onAppAction()
// @ts-expect-error - intentionally passing null
.executeQuery({ query: { queryId: null } })
.test({ fields: {} })
expect(steps[0].outputs.response).toStartWith("Error:")
expect(steps[0].outputs.success).toEqual(false)
})
it("should handle an error executing a query", async () => {
let res = await setup.runStep(
config,
setup.actions.EXECUTE_QUERY.stepId,
{
query: { queryId: "wrong_id" },
}
)
expect(res.response).toBeDefined()
expect(res.success).toEqual(false)
const { steps } = await createAutomationBuilder(config)
.onAppAction()
.executeQuery({ query: { queryId: "wrong_id" } })
.test({ fields: {} })
expect(steps[0].outputs.response).toStartWith("Error:")
expect(steps[0].outputs.success).toEqual(false)
})
}
)

View File

@ -19,7 +19,7 @@ function generateResponse(to: string, from: string) {
}
}
import * as setup from "../utilities"
import { createAutomationBuilder } from "../utilities/AutomationTestBuilder"
describe("test the outgoing webhook action", () => {
const config = new TestConfiguration()
@ -60,13 +60,14 @@ describe("test the outgoing webhook action", () => {
...invite,
}
let resp = generateResponse(inputs.to, inputs.from)
const res = await setup.runStep(
config,
setup.actions.SEND_EMAIL_SMTP.stepId,
inputs
)
expect(res.response).toEqual(resp)
expect(res.success).toEqual(true)
const { steps } = await createAutomationBuilder(config)
.onAppAction()
.sendSmtpEmail(inputs)
.test({ fields: {} })
expect(steps[0].outputs.response).toEqual(resp)
expect(steps[0].outputs.success).toEqual(true)
expect(workerRequests.sendSmtpEmail).toHaveBeenCalledTimes(1)
expect(workerRequests.sendSmtpEmail).toHaveBeenCalledWith({
to: "user1@example.com",
@ -75,7 +76,11 @@ describe("test the outgoing webhook action", () => {
contents: "testing",
cc: "cc",
bcc: "bcc",
invite,
invite: {
...invite,
startTime: invite.startTime.toISOString(),
endTime: invite.endTime.toISOString(),
},
automation: true,
attachments: [
{ url: "attachment1", filename: "attachment1.txt" },

View File

@ -1,14 +1,7 @@
import TestConfiguration from "../../../tests/utilities/TestConfiguration"
import { context } from "@budibase/backend-core"
import { BUILTIN_ACTION_DEFINITIONS, getAction } from "../../actions"
import emitter from "../../../events/index"
import { BUILTIN_ACTION_DEFINITIONS } from "../../actions"
import env from "../../../environment"
import {
Automation,
AutomationActionStepId,
AutomationData,
Datasource,
} from "@budibase/types"
import { Automation, AutomationData, Datasource } from "@budibase/types"
import { Knex } from "knex"
import { getQueue } from "../.."
import { Job } from "bull"
@ -41,36 +34,6 @@ export async function runInProd(fn: any) {
}
}
export async function runStep(
config: TestConfiguration,
stepId: string,
inputs: any,
stepContext?: any
) {
async function run() {
let step = await getAction(stepId as AutomationActionStepId)
expect(step).toBeDefined()
if (!step) {
throw new Error("No step found")
}
return step({
context: stepContext || {},
inputs,
appId: config ? config.getAppId() : "",
// don't really need an API key, mocked out usage quota, not being tested here
apiKey,
emitter,
})
}
if (config.appId) {
return context.doInContext(config?.appId, async () => {
return run()
})
} else {
return run()
}
}
/**
* Capture all automation runs that occur during the execution of a function.
* This function will wait for all messages to be processed before returning.