workflow CRUD complete
This commit is contained in:
parent
f069c3eb4b
commit
39c894c459
|
@ -24,7 +24,7 @@
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "jest routes --runInBand",
|
"test": "jest routes --runInBand",
|
||||||
"test:integration": "jest routes --runInBand",
|
"test:integration": "jest workflow --runInBand",
|
||||||
"test:watch": "jest -w",
|
"test:watch": "jest -w",
|
||||||
"initialise": "node ../cli/bin/budi init -b local -q",
|
"initialise": "node ../cli/bin/budi init -b local -q",
|
||||||
"budi": "node ../cli/bin/budi",
|
"budi": "node ../cli/bin/budi",
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
const CouchDB = require("../../db")
|
||||||
|
const Ajv = require("ajv")
|
||||||
|
const newid = require("../../db/newid")
|
||||||
|
|
||||||
|
const ajv = new Ajv()
|
||||||
|
|
||||||
|
exports.create = async function(ctx) {
|
||||||
|
const db = new CouchDB(ctx.params.instanceId)
|
||||||
|
const workflow = ctx.request.body
|
||||||
|
|
||||||
|
workflow._id = newid()
|
||||||
|
|
||||||
|
// TODO: Possibly validate the workflow against a schema
|
||||||
|
|
||||||
|
// // validation with ajv
|
||||||
|
// const model = await db.get(record.modelId)
|
||||||
|
// const validate = ajv.compile({
|
||||||
|
// properties: model.schema,
|
||||||
|
// })
|
||||||
|
// const valid = validate(record)
|
||||||
|
|
||||||
|
// if (!valid) {
|
||||||
|
// ctx.status = 400
|
||||||
|
// ctx.body = {
|
||||||
|
// status: 400,
|
||||||
|
// errors: validate.errors,
|
||||||
|
// }
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
workflow.type = "workflow"
|
||||||
|
const response = await db.post(workflow)
|
||||||
|
workflow._rev = response.rev
|
||||||
|
|
||||||
|
ctx.status = 200
|
||||||
|
ctx.body = {
|
||||||
|
message: "Workflow created successfully",
|
||||||
|
workflow: {
|
||||||
|
...workflow,
|
||||||
|
...response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.update = async function(ctx) {
|
||||||
|
const db = new CouchDB(ctx.params.instanceId)
|
||||||
|
ctx.body = await db.get(ctx.params.recordId)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.fetch = async function(ctx) {
|
||||||
|
const db = new CouchDB(ctx.params.instanceId)
|
||||||
|
const response = await db.query(`database/by_type`, {
|
||||||
|
type: "workflow",
|
||||||
|
include_docs: true,
|
||||||
|
})
|
||||||
|
ctx.body = response.rows.map(row => row.doc)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.find = async function(ctx) {
|
||||||
|
const db = new CouchDB(ctx.params.instanceId)
|
||||||
|
ctx.body = await db.get(ctx.params.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.destroy = async function(ctx) {
|
||||||
|
const db = new CouchDB(ctx.params.instanceId)
|
||||||
|
ctx.body = await db.remove(ctx.params.id, ctx.params.rev)
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ const {
|
||||||
viewRoutes,
|
viewRoutes,
|
||||||
staticRoutes,
|
staticRoutes,
|
||||||
componentRoutes,
|
componentRoutes,
|
||||||
|
workflowRoutes
|
||||||
} = require("./routes")
|
} = require("./routes")
|
||||||
|
|
||||||
const router = new Router()
|
const router = new Router()
|
||||||
|
@ -75,6 +76,9 @@ router.use(recordRoutes.allowedMethods())
|
||||||
|
|
||||||
router.use(instanceRoutes.routes())
|
router.use(instanceRoutes.routes())
|
||||||
router.use(instanceRoutes.allowedMethods())
|
router.use(instanceRoutes.allowedMethods())
|
||||||
|
|
||||||
|
router.use(workflowRoutes.routes())
|
||||||
|
router.use(workflowRoutes.allowedMethods())
|
||||||
// end auth routes
|
// end auth routes
|
||||||
|
|
||||||
router.use(pageRoutes.routes())
|
router.use(pageRoutes.routes())
|
||||||
|
|
|
@ -9,6 +9,7 @@ const modelRoutes = require("./model")
|
||||||
const viewRoutes = require("./view")
|
const viewRoutes = require("./view")
|
||||||
const staticRoutes = require("./static")
|
const staticRoutes = require("./static")
|
||||||
const componentRoutes = require("./component")
|
const componentRoutes = require("./component")
|
||||||
|
const workflowRoutes = require("./workflow");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
authRoutes,
|
authRoutes,
|
||||||
|
@ -22,4 +23,5 @@ module.exports = {
|
||||||
viewRoutes,
|
viewRoutes,
|
||||||
staticRoutes,
|
staticRoutes,
|
||||||
componentRoutes,
|
componentRoutes,
|
||||||
|
workflowRoutes
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,14 +76,9 @@ exports.createUser = async (
|
||||||
|
|
||||||
exports.insertDocument = async (databaseId, document) => {
|
exports.insertDocument = async (databaseId, document) => {
|
||||||
const { id, ...documentFields } = document
|
const { id, ...documentFields } = document
|
||||||
await new CouchDB(databaseId).put({ _id: id, ...documentFields })
|
return await new CouchDB(databaseId).put({ _id: id, ...documentFields })
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.createSchema = async (request, instanceId, schema) => {
|
exports.destroyDocument = async (databaseId, documentId) => {
|
||||||
for (let model of schema.models) {
|
return await new CouchDB(databaseId).destroy(documentId);
|
||||||
await request.post(`/api/${instanceId}/models`).send(model)
|
}
|
||||||
}
|
|
||||||
for (let view of schema.views) {
|
|
||||||
await request.post(`/api/${instanceId}/views`).send(view)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
const {
|
||||||
|
createClientDatabase,
|
||||||
|
createApplication,
|
||||||
|
createInstance,
|
||||||
|
defaultHeaders,
|
||||||
|
supertest,
|
||||||
|
insertDocument,
|
||||||
|
destroyDocument
|
||||||
|
} = require("./couchTestUtils")
|
||||||
|
|
||||||
|
const TEST_WORKFLOW = {
|
||||||
|
_id: "Test Workflow",
|
||||||
|
name: "My Workflow",
|
||||||
|
pageId: "123123123",
|
||||||
|
screenId: "kasdkfldsafkl",
|
||||||
|
live: true,
|
||||||
|
uiTree: {
|
||||||
|
|
||||||
|
},
|
||||||
|
definition: {
|
||||||
|
triggers: [
|
||||||
|
|
||||||
|
],
|
||||||
|
next: {
|
||||||
|
actionId: "abc123",
|
||||||
|
type: "SERVER",
|
||||||
|
conditions: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("/workflows", () => {
|
||||||
|
let request
|
||||||
|
let server
|
||||||
|
let app
|
||||||
|
let instance
|
||||||
|
let workflow
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
({ request, server } = await supertest())
|
||||||
|
await createClientDatabase(request)
|
||||||
|
app = await createApplication(request)
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
instance = await createInstance(request, app._id)
|
||||||
|
if (workflow) await destroyDocument(workflow.id);
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
server.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
const createWorkflow = async () => {
|
||||||
|
workflow = await insertDocument(instance._id, {
|
||||||
|
type: "workflow",
|
||||||
|
...TEST_WORKFLOW
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("create", () => {
|
||||||
|
it("returns a success message when the workflow is successfully created", async () => {
|
||||||
|
const res = await request
|
||||||
|
.post(`/api/${instance._id}/workflows`)
|
||||||
|
.set(defaultHeaders)
|
||||||
|
.send(TEST_WORKFLOW)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
expect(res.body.message).toEqual("Workflow created successfully");
|
||||||
|
expect(res.body.workflow.name).toEqual("My Workflow");
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("fetch", () => {
|
||||||
|
it("return all the workflows for an instance", async () => {
|
||||||
|
await createWorkflow();
|
||||||
|
const res = await request
|
||||||
|
.get(`/api/${instance._id}/workflows`)
|
||||||
|
.set(defaultHeaders)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
expect(res.body[0]).toEqual(expect.objectContaining(TEST_WORKFLOW));
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("find", () => {
|
||||||
|
it("returns a workflow when queried by ID", async () => {
|
||||||
|
await createWorkflow();
|
||||||
|
const res = await request
|
||||||
|
.get(`/api/${instance._id}/workflows/${workflow.id}`)
|
||||||
|
.set(defaultHeaders)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
expect(res.body).toEqual(expect.objectContaining(TEST_WORKFLOW));
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("destroy", () => {
|
||||||
|
it("deletes a workflow by its ID", async () => {
|
||||||
|
await createWorkflow();
|
||||||
|
const res = await request
|
||||||
|
.delete(`/api/${instance._id}/workflows/${workflow.id}/${workflow.rev}`)
|
||||||
|
.set(defaultHeaders)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
expect(res.body.id).toEqual(TEST_WORKFLOW._id);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
|
@ -0,0 +1,13 @@
|
||||||
|
const Router = require("@koa/router")
|
||||||
|
const controller = require("../controllers/workflow")
|
||||||
|
|
||||||
|
const router = Router()
|
||||||
|
|
||||||
|
router
|
||||||
|
.get("/api/:instanceId/workflows", controller.fetch)
|
||||||
|
.get("/api/:instanceId/workflows/:id", controller.find)
|
||||||
|
.post("/api/:instanceId/workflows", controller.create)
|
||||||
|
.put("/api/:instanceId/workflows/:id", controller.update)
|
||||||
|
.delete("/api/:instanceId/workflows/:id/:rev", controller.destroy)
|
||||||
|
|
||||||
|
module.exports = router
|
|
@ -0,0 +1,38 @@
|
||||||
|
const WORKFLOW_SCHEMA = {
|
||||||
|
properties: {
|
||||||
|
type: "workflow",
|
||||||
|
pageId: {
|
||||||
|
type: "string"
|
||||||
|
},
|
||||||
|
screenId: {
|
||||||
|
type: "string"
|
||||||
|
},
|
||||||
|
live: {
|
||||||
|
type: "boolean"
|
||||||
|
},
|
||||||
|
uiTree: {
|
||||||
|
type: "object"
|
||||||
|
},
|
||||||
|
definition: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
triggers: { type: "array" },
|
||||||
|
next: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
type: { type: "string" },
|
||||||
|
actionId: { type: "string" },
|
||||||
|
args: { type: "object" },
|
||||||
|
conditions: { type: "array" },
|
||||||
|
errorHandling: { type: "object" },
|
||||||
|
next: { type: "object" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
WORKFLOW_SCHEMA
|
||||||
|
};
|
Loading…
Reference in New Issue