Adding some basic test cases for the metadata API, testing that automation tests do store history.
This commit is contained in:
parent
06d17827b6
commit
fce3a6bbe7
|
@ -3,9 +3,10 @@ const actions = require("../../automations/actions")
|
|||
const logic = require("../../automations/logic")
|
||||
const triggers = require("../../automations/triggers")
|
||||
const { getAutomationParams, generateAutomationID } = require("../../db/utils")
|
||||
const { saveEntityMetadata } = require("../../utilities")
|
||||
const { MetadataTypes } = require("../../constants")
|
||||
const { checkForWebhooks } = require("../../automations/utils")
|
||||
const {
|
||||
checkForWebhooks,
|
||||
updateTestHistory,
|
||||
} = require("../../automations/utils")
|
||||
|
||||
/*************************
|
||||
* *
|
||||
|
@ -171,11 +172,9 @@ exports.test = async function (ctx) {
|
|||
{ getResponses: true }
|
||||
)
|
||||
// save a test history run
|
||||
await saveEntityMetadata(
|
||||
ctx.appId,
|
||||
MetadataTypes.AUTOMATION_TEST_HISTORY,
|
||||
automation._id,
|
||||
ctx.request.body
|
||||
)
|
||||
await updateTestHistory(ctx.appId, automation, {
|
||||
...ctx.request.body,
|
||||
occurredAt: new Date().toISOString(),
|
||||
})
|
||||
ctx.body = response
|
||||
}
|
||||
|
|
|
@ -14,7 +14,12 @@ exports.saveMetadata = async ctx => {
|
|||
if (type === MetadataTypes.AUTOMATION_TEST_HISTORY) {
|
||||
ctx.throw(400, "Cannot save automation history type")
|
||||
}
|
||||
await saveEntityMetadata(ctx.appId, type, entityId, ctx.request.body)
|
||||
ctx.body = await saveEntityMetadata(
|
||||
ctx.appId,
|
||||
type,
|
||||
entityId,
|
||||
ctx.request.body
|
||||
)
|
||||
}
|
||||
|
||||
exports.deleteMetadata = async ctx => {
|
||||
|
@ -34,7 +39,7 @@ exports.deleteMetadata = async ctx => {
|
|||
await db.remove(id, rev)
|
||||
}
|
||||
ctx.body = {
|
||||
message: "Metadata deleted successfully.",
|
||||
message: "Metadata deleted successfully",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,5 +47,13 @@ exports.getMetadata = async ctx => {
|
|||
const { type, entityId } = ctx.params
|
||||
const db = new CouchDB(ctx.appId)
|
||||
const id = generateMetadataID(type, entityId)
|
||||
try {
|
||||
ctx.body = await db.get(id)
|
||||
} catch (err) {
|
||||
if (err.status === 404) {
|
||||
ctx.body = {}
|
||||
} else {
|
||||
ctx.throw(err.status, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ const datasourceRoutes = require("./datasource")
|
|||
const queryRoutes = require("./query")
|
||||
const hostingRoutes = require("./hosting")
|
||||
const backupRoutes = require("./backup")
|
||||
const metadataRoutes = require("./metadata")
|
||||
const devRoutes = require("./dev")
|
||||
|
||||
exports.mainRoutes = [
|
||||
|
@ -46,6 +47,7 @@ exports.mainRoutes = [
|
|||
queryRoutes,
|
||||
hostingRoutes,
|
||||
backupRoutes,
|
||||
metadataRoutes,
|
||||
devRoutes,
|
||||
// these need to be handled last as they still use /api/:tableId
|
||||
// this could be breaking as koa may recognise other routes as this
|
||||
|
|
|
@ -4,27 +4,33 @@ const {
|
|||
middleware: appInfoMiddleware,
|
||||
AppType,
|
||||
} = require("../../middleware/appInfo")
|
||||
const authorized = require("../../middleware/authorized")
|
||||
const { BUILDER } = require("@budibase/auth/permissions")
|
||||
|
||||
const router = Router()
|
||||
|
||||
router
|
||||
.post(
|
||||
"/api/metadata/:type/:entityId",
|
||||
authorized(BUILDER),
|
||||
appInfoMiddleware({ appType: AppType.DEV }),
|
||||
controller.saveMetadata
|
||||
)
|
||||
.delete(
|
||||
"/api/metadata/:type/:entityId",
|
||||
authorized(BUILDER),
|
||||
appInfoMiddleware({ appType: AppType.DEV }),
|
||||
controller.deleteMetadata
|
||||
)
|
||||
.get(
|
||||
"/api/metadata/type",
|
||||
authorized(BUILDER),
|
||||
appInfoMiddleware({ appType: AppType.DEV }),
|
||||
controller.getTypes
|
||||
)
|
||||
.get(
|
||||
"/api/metadata/:type/:entityId",
|
||||
authorized(BUILDER),
|
||||
appInfoMiddleware({ appType: AppType.DEV }),
|
||||
controller.getMetadata
|
||||
)
|
||||
|
|
|
@ -2,6 +2,7 @@ const {
|
|||
checkBuilderEndpoint,
|
||||
getAllTableRows,
|
||||
clearAllAutomations,
|
||||
triggerAutomation,
|
||||
} = require("./utilities/TestFunctions")
|
||||
const setup = require("./utilities")
|
||||
const { basicAutomation } = setup.structures
|
||||
|
@ -23,15 +24,6 @@ describe("/automations", () => {
|
|||
await config.init()
|
||||
})
|
||||
|
||||
const triggerWorkflow = async automation => {
|
||||
return await request
|
||||
.post(`/api/automations/${automation._id}/trigger`)
|
||||
.send({ name: "Test", description: "TEST" })
|
||||
.set(config.defaultHeaders())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
}
|
||||
|
||||
describe("get definitions", () => {
|
||||
it("returns a list of definitions for actions", async () => {
|
||||
const res = await request
|
||||
|
@ -168,7 +160,7 @@ describe("/automations", () => {
|
|||
automation.definition.steps[0].inputs.row.tableId = table._id
|
||||
automation = await config.createAutomation(automation)
|
||||
await setup.delay(500)
|
||||
const res = await triggerWorkflow(automation)
|
||||
const res = await triggerAutomation(config, automation)
|
||||
// this looks a bit mad but we don't actually have a way to wait for a response from the automation to
|
||||
// know that it has finished all of its actions - this is currently the best way
|
||||
// also when this runs in CI it is very temper-mental so for now trying to make run stable by repeating until it works
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
const { testAutomation } = require("./utilities/TestFunctions")
|
||||
const setup = require("./utilities")
|
||||
const { MetadataTypes } = require("../../../constants")
|
||||
|
||||
describe("/metadata", () => {
|
||||
let request = setup.getRequest()
|
||||
let config = setup.getConfig()
|
||||
let automation
|
||||
|
||||
afterAll(setup.afterAll)
|
||||
|
||||
beforeEach(async () => {
|
||||
await config.init()
|
||||
automation = await config.createAutomation()
|
||||
})
|
||||
|
||||
async function createMetadata(data, type = MetadataTypes.AUTOMATION_TEST_INPUT) {
|
||||
const res = await request
|
||||
.post(`/api/metadata/${type}/${automation._id}`)
|
||||
.send(data)
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
expect(res.body._rev).toBeDefined()
|
||||
}
|
||||
|
||||
async function getMetadata(type) {
|
||||
const res = await request
|
||||
.get(`/api/metadata/${type}/${automation._id}`)
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
return res.body
|
||||
}
|
||||
|
||||
describe("save", () => {
|
||||
it("should be able to save some metadata", async () => {
|
||||
await createMetadata({ test: "a" })
|
||||
const testInput = await getMetadata(MetadataTypes.AUTOMATION_TEST_INPUT)
|
||||
expect(testInput.test).toBe("a")
|
||||
})
|
||||
|
||||
it("should save history metadata on automation run", async () => {
|
||||
// this should have created some history
|
||||
await testAutomation(config, automation)
|
||||
const metadata = await getMetadata(MetadataTypes.AUTOMATION_TEST_HISTORY)
|
||||
expect(metadata).toBeDefined()
|
||||
expect(metadata.history.length).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe("destroy", () => {
|
||||
it("should be able to delete some test inputs", async () => {
|
||||
const res = await request
|
||||
.delete(`/api/metadata/${MetadataTypes.AUTOMATION_TEST_INPUT}/${automation._id}`)
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
expect(res.body.message).toBeDefined()
|
||||
const metadata = await getMetadata(MetadataTypes.AUTOMATION_TEST_INPUT)
|
||||
expect(metadata.test).toBeUndefined()
|
||||
})
|
||||
})
|
||||
})
|
|
@ -101,3 +101,21 @@ exports.checkPermissionsEndpoint = async ({
|
|||
exports.getDB = config => {
|
||||
return new CouchDB(config.getAppId())
|
||||
}
|
||||
|
||||
exports.triggerAutomation = async (config, automation) => {
|
||||
return await config.request
|
||||
.post(`/api/automations/${automation._id}/trigger`)
|
||||
.send({ name: "Test", description: "TEST" })
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
}
|
||||
|
||||
exports.testAutomation = async (config, automation) => {
|
||||
return await config.request
|
||||
.post(`/api/automations/${automation._id}/test`)
|
||||
.send({ name: "Test", description: "TEST" })
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ const webhooks = require("../api/controllers/webhook")
|
|||
const CouchDB = require("../db")
|
||||
const { queue } = require("./bullboard")
|
||||
const newid = require("../db/newid")
|
||||
const { updateEntityMetadata } = require("../utilities")
|
||||
const { MetadataTypes } = require("../constants")
|
||||
|
||||
const WH_STEP_ID = definitions.WEBHOOK.stepId
|
||||
const CRON_STEP_ID = definitions.CRON.stepId
|
||||
|
@ -63,6 +65,24 @@ exports.processEvent = async job => {
|
|||
}
|
||||
}
|
||||
|
||||
exports.updateTestHistory = async (appId, automation, history) => {
|
||||
return updateEntityMetadata(
|
||||
appId,
|
||||
MetadataTypes.AUTOMATION_TEST_HISTORY,
|
||||
automation._id,
|
||||
metadata => {
|
||||
if (metadata && Array.isArray(metadata.history)) {
|
||||
metadata.history.push(history)
|
||||
} else {
|
||||
metadata = {
|
||||
history: [history],
|
||||
}
|
||||
}
|
||||
return metadata
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// end the repetition and the job itself
|
||||
exports.disableAllCrons = async appId => {
|
||||
const promises = []
|
||||
|
|
|
@ -58,16 +58,19 @@ exports.attachmentsRelativeURL = attachmentKey => {
|
|||
)
|
||||
}
|
||||
|
||||
exports.saveEntityMetadata = async (appId, type, entityId, metadata) => {
|
||||
exports.updateEntityMetadata = async (appId, type, entityId, updateFn) => {
|
||||
const db = new CouchDB(appId)
|
||||
const id = generateMetadataID(type, entityId)
|
||||
// read it to see if it exists, we'll overwrite it no matter what
|
||||
let rev
|
||||
let rev,
|
||||
metadata = {}
|
||||
try {
|
||||
const oldMetadata = await db.get(id)
|
||||
rev = oldMetadata._rev
|
||||
metadata = updateFn(oldMetadata)
|
||||
} catch (err) {
|
||||
rev = null
|
||||
metadata = updateFn({})
|
||||
}
|
||||
metadata._id = id
|
||||
if (rev) {
|
||||
|
@ -80,3 +83,9 @@ exports.saveEntityMetadata = async (appId, type, entityId, metadata) => {
|
|||
_rev: response.rev,
|
||||
}
|
||||
}
|
||||
|
||||
exports.saveEntityMetadata = async (appId, type, entityId, metadata) => {
|
||||
return exports.updateEntityMetadata(appId, type, entityId, () => {
|
||||
return metadata
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue