Adding some basic test cases for the metadata API, testing that automation tests do store history.

This commit is contained in:
mike12345567 2021-09-10 13:52:41 +01:00
parent da9d78d1fb
commit 84cdec5907
9 changed files with 147 additions and 24 deletions

View File

@ -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
}

View File

@ -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)
}
}
}

View File

@ -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

View File

@ -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
)

View File

@ -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

View File

@ -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()
})
})
})

View File

@ -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)
}

View File

@ -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 = []

View File

@ -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
})
}