Improve some typing around automation testing.

This commit is contained in:
Sam Rose 2025-01-20 18:08:14 +00:00
parent 5afab49e18
commit 31fc2e45c9
No known key found for this signature in database
5 changed files with 86 additions and 31 deletions

View File

@ -1,5 +1,4 @@
import { v4 as uuidv4 } from "uuid" import { v4 as uuidv4 } from "uuid"
import { testAutomation } from "../../../api/routes/tests/utilities/TestFunctions"
import { BUILTIN_ACTION_DEFINITIONS } from "../../actions" import { BUILTIN_ACTION_DEFINITIONS } from "../../actions"
import { TRIGGER_DEFINITIONS } from "../../triggers" import { TRIGGER_DEFINITIONS } from "../../triggers"
import { import {
@ -7,7 +6,6 @@ import {
AppActionTriggerOutputs, AppActionTriggerOutputs,
Automation, Automation,
AutomationActionStepId, AutomationActionStepId,
AutomationResults,
AutomationStep, AutomationStep,
AutomationStepInputs, AutomationStepInputs,
AutomationTrigger, AutomationTrigger,
@ -24,6 +22,7 @@ import {
ExecuteQueryStepInputs, ExecuteQueryStepInputs,
ExecuteScriptStepInputs, ExecuteScriptStepInputs,
FilterStepInputs, FilterStepInputs,
isDidNotTriggerResponse,
LoopStepInputs, LoopStepInputs,
OpenAIStepInputs, OpenAIStepInputs,
QueryRowsStepInputs, QueryRowsStepInputs,
@ -36,6 +35,7 @@ import {
SearchFilters, SearchFilters,
ServerLogStepInputs, ServerLogStepInputs,
SmtpEmailStepInputs, SmtpEmailStepInputs,
TestAutomationRequest,
UpdateRowStepInputs, UpdateRowStepInputs,
WebhookTriggerInputs, WebhookTriggerInputs,
WebhookTriggerOutputs, WebhookTriggerOutputs,
@ -279,7 +279,7 @@ class StepBuilder extends BaseStepBuilder {
class AutomationBuilder extends BaseStepBuilder { class AutomationBuilder extends BaseStepBuilder {
private automationConfig: Automation private automationConfig: Automation
private config: TestConfiguration private config: TestConfiguration
private triggerOutputs: any private triggerOutputs: TriggerOutputs
private triggerSet = false private triggerSet = false
constructor( constructor(
@ -398,21 +398,19 @@ class AutomationBuilder extends BaseStepBuilder {
async run() { async run() {
const automation = await this.save() const automation = await this.save()
const results = await testAutomation( const response = await this.config.api.automation.test(
this.config, automation._id!,
automation, this.triggerOutputs as TestAutomationRequest
this.triggerOutputs
) )
return this.processResults(results)
}
private processResults(results: { if (isDidNotTriggerResponse(response)) {
body: AutomationResults throw new Error(response.message)
}): AutomationResults { }
results.body.steps.shift()
response.steps.shift()
return { return {
trigger: results.body.trigger, trigger: response.trigger,
steps: results.body.steps, steps: response.steps,
} }
} }
} }

View File

@ -21,6 +21,7 @@ import {
AutomationRowEvent, AutomationRowEvent,
UserBindings, UserBindings,
AutomationResults, AutomationResults,
DidNotTriggerResponse,
} from "@budibase/types" } from "@budibase/types"
import { executeInThread } from "../threads/automation" import { executeInThread } from "../threads/automation"
import { dataFilters, sdk } from "@budibase/shared-core" import { dataFilters, sdk } from "@budibase/shared-core"
@ -33,14 +34,6 @@ const JOB_OPTS = {
import * as automationUtils from "../automations/automationUtils" import * as automationUtils from "../automations/automationUtils"
import { doesTableExist } from "../sdk/app/tables/getters" import { doesTableExist } from "../sdk/app/tables/getters"
type DidNotTriggerResponse = {
outputs: {
success: false
status: AutomationStatus.STOPPED
}
message: AutomationStoppedReason.TRIGGER_FILTER_NOT_MET
}
async function getAllAutomations() { async function getAllAutomations() {
const db = context.getAppDB() const db = context.getAppDB()
let automations = await db.allDocs<Automation>( let automations = await db.allDocs<Automation>(
@ -156,14 +149,26 @@ export function isAutomationResults(
) )
} }
interface AutomationTriggerParams {
fields: Record<string, any>
timeout?: number
appId?: string
user?: UserBindings
}
export async function externalTrigger( export async function externalTrigger(
automation: Automation, automation: Automation,
params: { params: AutomationTriggerParams,
fields: Record<string, any> options: { getResponses: true }
timeout?: number ): Promise<AutomationResults | DidNotTriggerResponse>
appId?: string export async function externalTrigger(
user?: UserBindings automation: Automation,
}, params: AutomationTriggerParams,
options?: { getResponses: false }
): Promise<AutomationJob | DidNotTriggerResponse>
export async function externalTrigger(
automation: Automation,
params: AutomationTriggerParams,
{ getResponses }: { getResponses?: boolean } = {} { getResponses }: { getResponses?: boolean } = {}
): Promise<AutomationResults | DidNotTriggerResponse | AutomationJob> { ): Promise<AutomationResults | DidNotTriggerResponse | AutomationJob> {
if (automation.disabled) { if (automation.disabled) {

View File

@ -1,4 +1,11 @@
import { Automation, FetchAutomationResponse } from "@budibase/types" import {
Automation,
FetchAutomationResponse,
TestAutomationRequest,
TestAutomationResponse,
TestAutomationStepRequest,
TestAutomationStepResponse,
} from "@budibase/types"
import { Expectations, TestAPI } from "./base" import { Expectations, TestAPI } from "./base"
export class AutomationAPI extends TestAPI { export class AutomationAPI extends TestAPI {
@ -33,4 +40,33 @@ export class AutomationAPI extends TestAPI {
}) })
return result return result
} }
test = async (
id: string,
body: TestAutomationRequest,
expectations?: Expectations
): Promise<TestAutomationResponse> => {
return await this._post<TestAutomationResponse>(
`/api/automations/${id}/test`,
{
body,
expectations,
}
)
}
testStep = async (
id: string,
stepId: string,
body: TestAutomationStepRequest,
expectations?: Expectations
): Promise<TestAutomationStepResponse> => {
return await this._post<TestAutomationStepResponse>(
`/api/automations/${id}/steps/${stepId}/test`,
{
body,
expectations,
}
)
}
} }

View File

@ -2,10 +2,12 @@ import {
Automation, Automation,
AutomationActionStepId, AutomationActionStepId,
AutomationLogPage, AutomationLogPage,
AutomationResults,
AutomationStatus, AutomationStatus,
AutomationStepDefinition, AutomationStepDefinition,
AutomationTriggerDefinition, AutomationTriggerDefinition,
AutomationTriggerStepId, AutomationTriggerStepId,
DidNotTriggerResponse,
Row, Row,
} from "../../../documents" } from "../../../documents"
import { DocumentDestroyResponse } from "@budibase/nano" import { DocumentDestroyResponse } from "@budibase/nano"
@ -74,7 +76,13 @@ export interface TestAutomationRequest {
fields: Record<string, any> fields: Record<string, any>
row?: Row row?: Row
} }
export interface TestAutomationResponse {} export type TestAutomationResponse = AutomationResults | DidNotTriggerResponse
export function isDidNotTriggerResponse(
response: TestAutomationResponse
): response is DidNotTriggerResponse {
return !!("message" in response && response.message)
}
export interface TestAutomationStepRequest { export interface TestAutomationStepRequest {
inputs: Record<string, any> inputs: Record<string, any>

View File

@ -205,6 +205,14 @@ export interface AutomationResults {
}[] }[]
} }
export interface DidNotTriggerResponse {
outputs: {
success: false
status: AutomationStatus.STOPPED
}
message: AutomationStoppedReason.TRIGGER_FILTER_NOT_MET
}
export interface AutomationLog extends AutomationResults, Document { export interface AutomationLog extends AutomationResults, Document {
automationName: string automationName: string
_rev?: string _rev?: string