Create tests for the row saved trigger.
This commit is contained in:
parent
18b296a850
commit
af188e1c1a
|
@ -199,6 +199,12 @@ class InMemoryQueue implements Partial<Queue> {
|
||||||
return this as unknown as Queue
|
return this as unknown as Queue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
off(event: string, callback: (...args: any[]) => void): Queue {
|
||||||
|
// @ts-expect-error - this callback can be one of many types
|
||||||
|
this._emitter.off(event, callback)
|
||||||
|
return this as unknown as Queue
|
||||||
|
}
|
||||||
|
|
||||||
async count() {
|
async count() {
|
||||||
return this._messages.length
|
return this._messages.length
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,7 +182,7 @@ if (descriptions.length) {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
await config.api.application.publish(config.getAppId())
|
await config.api.application.publish()
|
||||||
const prodQuery = await config.api.query.getProd(query._id!)
|
const prodQuery = await config.api.query.getProd(query._id!)
|
||||||
|
|
||||||
expect(prodQuery._id).toEqual(query._id)
|
expect(prodQuery._id).toEqual(query._id)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { createAutomationBuilder } from "../utilities/AutomationTestBuilder"
|
import { createAutomationBuilder } from "../utilities/AutomationTestBuilder"
|
||||||
import TestConfiguration from "../../../tests/utilities/TestConfiguration"
|
import TestConfiguration from "../../../tests/utilities/TestConfiguration"
|
||||||
import { getQueue } from "../.."
|
import { captureAutomationRuns } from "../utilities"
|
||||||
import { Job } from "bull"
|
|
||||||
|
|
||||||
describe("cron trigger", () => {
|
describe("cron trigger", () => {
|
||||||
const config = new TestConfiguration()
|
const config = new TestConfiguration()
|
||||||
|
@ -15,15 +14,6 @@ describe("cron trigger", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should queue a Bull cron job", async () => {
|
it("should queue a Bull cron job", async () => {
|
||||||
const queue = getQueue()
|
|
||||||
expect(await queue.getCompletedCount()).toEqual(0)
|
|
||||||
|
|
||||||
const jobPromise = new Promise<Job>(resolve => {
|
|
||||||
queue.on("completed", async job => {
|
|
||||||
resolve(job)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
await createAutomationBuilder(config)
|
await createAutomationBuilder(config)
|
||||||
.onCron({ cron: "* * * * *" })
|
.onCron({ cron: "* * * * *" })
|
||||||
.serverLog({
|
.serverLog({
|
||||||
|
@ -31,12 +21,12 @@ describe("cron trigger", () => {
|
||||||
})
|
})
|
||||||
.save()
|
.save()
|
||||||
|
|
||||||
await config.api.application.publish(config.getAppId())
|
const jobs = await captureAutomationRuns(() =>
|
||||||
|
config.api.application.publish()
|
||||||
|
)
|
||||||
|
expect(jobs).toHaveLength(1)
|
||||||
|
|
||||||
expect(await queue.getCompletedCount()).toEqual(1)
|
const repeat = jobs[0].opts?.repeat
|
||||||
|
|
||||||
const job = await jobPromise
|
|
||||||
const repeat = job.opts?.repeat
|
|
||||||
if (!repeat || !("cron" in repeat)) {
|
if (!repeat || !("cron" in repeat)) {
|
||||||
throw new Error("Expected cron repeat")
|
throw new Error("Expected cron repeat")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { createAutomationBuilder } from "../utilities/AutomationTestBuilder"
|
||||||
|
import TestConfiguration from "../../../tests/utilities/TestConfiguration"
|
||||||
|
import { Table } from "@budibase/types"
|
||||||
|
import { basicTable } from "../../../tests/utilities/structures"
|
||||||
|
import { captureAutomationRuns } from "../utilities"
|
||||||
|
|
||||||
|
describe("row saved trigger", () => {
|
||||||
|
const config = new TestConfiguration()
|
||||||
|
let table: Table
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await config.init()
|
||||||
|
table = await config.api.table.save(basicTable())
|
||||||
|
await createAutomationBuilder(config)
|
||||||
|
.onRowSaved({ tableId: table._id! })
|
||||||
|
.serverLog({ text: "Row created!" })
|
||||||
|
.save()
|
||||||
|
|
||||||
|
await config.api.application.publish()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
config.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should queue a Bull job when a row is created", async () => {
|
||||||
|
const jobs = await captureAutomationRuns(() =>
|
||||||
|
config.withProdApp(() => config.api.row.save(table._id!, { name: "foo" }))
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(jobs).toHaveLength(1)
|
||||||
|
expect(jobs[0].data.event).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
tableId: table._id!,
|
||||||
|
row: expect.objectContaining({ name: "foo" }),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should not fire for rows created in other tables", async () => {
|
||||||
|
const otherTable = await config.api.table.save(basicTable())
|
||||||
|
await config.api.application.publish()
|
||||||
|
|
||||||
|
const jobs = await captureAutomationRuns(() =>
|
||||||
|
config.withProdApp(() =>
|
||||||
|
config.api.row.save(otherTable._id!, { name: "foo" })
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(jobs).toBeEmpty()
|
||||||
|
})
|
||||||
|
})
|
|
@ -3,8 +3,15 @@ import { context } from "@budibase/backend-core"
|
||||||
import { BUILTIN_ACTION_DEFINITIONS, getAction } from "../../actions"
|
import { BUILTIN_ACTION_DEFINITIONS, getAction } from "../../actions"
|
||||||
import emitter from "../../../events/index"
|
import emitter from "../../../events/index"
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
import { AutomationActionStepId, Datasource } from "@budibase/types"
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationData,
|
||||||
|
Datasource,
|
||||||
|
} from "@budibase/types"
|
||||||
import { Knex } from "knex"
|
import { Knex } from "knex"
|
||||||
|
import { getQueue } from "../.."
|
||||||
|
import { Job } from "bull"
|
||||||
|
import { helpers } from "@budibase/shared-core"
|
||||||
|
|
||||||
let config: TestConfiguration
|
let config: TestConfiguration
|
||||||
|
|
||||||
|
@ -63,6 +70,44 @@ export async function runStep(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capture all automation runs that occur during the execution of a function.
|
||||||
|
* This function will wait for all messages to be processed before returning.
|
||||||
|
*/
|
||||||
|
export async function captureAutomationRuns(
|
||||||
|
f: () => Promise<unknown>
|
||||||
|
): Promise<Job<AutomationData>[]> {
|
||||||
|
const runs: Job<AutomationData>[] = []
|
||||||
|
const queue = getQueue()
|
||||||
|
let messagesReceived = 0
|
||||||
|
|
||||||
|
const completedListener = async (job: Job<AutomationData>) => {
|
||||||
|
runs.push(job)
|
||||||
|
messagesReceived--
|
||||||
|
}
|
||||||
|
const messageListener = async () => {
|
||||||
|
messagesReceived++
|
||||||
|
}
|
||||||
|
queue.on("message", messageListener)
|
||||||
|
queue.on("completed", completedListener)
|
||||||
|
try {
|
||||||
|
await f()
|
||||||
|
// Queue messages tend to be send asynchronously in API handlers, so there's
|
||||||
|
// no guarantee that awaiting this function will have queued anything yet.
|
||||||
|
// We wait here to make sure we're queued _after_ any existing async work.
|
||||||
|
await helpers.wait(100)
|
||||||
|
} finally {
|
||||||
|
// eslint-disable-next-line no-unmodified-loop-condition
|
||||||
|
while (messagesReceived > 0) {
|
||||||
|
await helpers.wait(50)
|
||||||
|
}
|
||||||
|
queue.off("completed", completedListener)
|
||||||
|
queue.off("message", messageListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
return runs
|
||||||
|
}
|
||||||
|
|
||||||
export async function saveTestQuery(
|
export async function saveTestQuery(
|
||||||
config: TestConfiguration,
|
config: TestConfiguration,
|
||||||
client: Knex,
|
client: Knex,
|
||||||
|
|
|
@ -34,9 +34,12 @@ export class ApplicationAPI extends TestAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
publish = async (
|
publish = async (
|
||||||
appId: string,
|
appId?: string,
|
||||||
expectations?: Expectations
|
expectations?: Expectations
|
||||||
): Promise<PublishResponse> => {
|
): Promise<PublishResponse> => {
|
||||||
|
if (!appId) {
|
||||||
|
appId = this.config.getAppId()
|
||||||
|
}
|
||||||
return await this._post<PublishResponse>(
|
return await this._post<PublishResponse>(
|
||||||
`/api/applications/${appId}/publish`,
|
`/api/applications/${appId}/publish`,
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue