Updating testcase to now trigger a proper workflow and check that it operates as expected.
This commit is contained in:
parent
8477ad8727
commit
be67eaf9c8
|
@ -182,6 +182,7 @@ exports.destroy = async function(ctx) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.body = await db.remove(ctx.params.recordId, ctx.params.revId)
|
ctx.body = await db.remove(ctx.params.recordId, ctx.params.revId)
|
||||||
|
ctx.status = 200
|
||||||
emitEvent(`record:delete`, ctx, record)
|
emitEvent(`record:delete`, ctx, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,13 @@ exports.createModel = async (request, appId, instanceId, model) => {
|
||||||
return res.body
|
return res.body
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.getAllFromModel = async (request, appId, instanceId, modelId) => {
|
||||||
|
const res = await request
|
||||||
|
.get(`/api/${modelId}/records`)
|
||||||
|
.set(exports.defaultHeaders(appId, instanceId))
|
||||||
|
return res.body
|
||||||
|
}
|
||||||
|
|
||||||
exports.createView = async (request, appId, instanceId, modelId, view) => {
|
exports.createView = async (request, appId, instanceId, modelId, view) => {
|
||||||
view = view || {
|
view = view || {
|
||||||
map: "function(doc) { emit(doc[doc.key], doc._id); } ",
|
map: "function(doc) { emit(doc[doc.key], doc._id); } ",
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
module.exports.delay = ms => new Promise(resolve => setTimeout(resolve, ms))
|
|
@ -3,6 +3,7 @@ const {
|
||||||
createApplication,
|
createApplication,
|
||||||
createInstance,
|
createInstance,
|
||||||
createModel,
|
createModel,
|
||||||
|
getAllFromModel,
|
||||||
defaultHeaders,
|
defaultHeaders,
|
||||||
supertest,
|
supertest,
|
||||||
insertDocument,
|
insertDocument,
|
||||||
|
@ -10,6 +11,8 @@ const {
|
||||||
builderEndpointShouldBlockNormalUsers
|
builderEndpointShouldBlockNormalUsers
|
||||||
} = require("./couchTestUtils")
|
} = require("./couchTestUtils")
|
||||||
|
|
||||||
|
const { delay } = require("./testUtils")
|
||||||
|
|
||||||
const TEST_WORKFLOW = {
|
const TEST_WORKFLOW = {
|
||||||
_id: "Test Workflow",
|
_id: "Test Workflow",
|
||||||
name: "My Workflow",
|
name: "My Workflow",
|
||||||
|
@ -37,7 +40,7 @@ describe("/workflows", () => {
|
||||||
let app
|
let app
|
||||||
let instance
|
let instance
|
||||||
let workflow
|
let workflow
|
||||||
let model
|
let workflowId
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
({ request, server } = await supertest())
|
({ request, server } = await supertest())
|
||||||
|
@ -48,7 +51,6 @@ describe("/workflows", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
if (workflow) await destroyDocument(workflow.id)
|
if (workflow) await destroyDocument(workflow.id)
|
||||||
instance = await createInstance(request, app._id)
|
instance = await createInstance(request, app._id)
|
||||||
model = await createModel(request, app._id, instance._id)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
@ -59,7 +61,7 @@ describe("/workflows", () => {
|
||||||
workflow = await insertDocument(instance._id, {
|
workflow = await insertDocument(instance._id, {
|
||||||
type: "workflow",
|
type: "workflow",
|
||||||
...TEST_WORKFLOW
|
...TEST_WORKFLOW
|
||||||
});
|
})
|
||||||
workflow = { ...workflow, ...TEST_WORKFLOW }
|
workflow = { ...workflow, ...TEST_WORKFLOW }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,21 +115,14 @@ describe("/workflows", () => {
|
||||||
describe("create", () => {
|
describe("create", () => {
|
||||||
it("should setup the workflow fully", () => {
|
it("should setup the workflow fully", () => {
|
||||||
let trigger = TRIGGER_DEFINITIONS["RECORD_SAVED"]
|
let trigger = TRIGGER_DEFINITIONS["RECORD_SAVED"]
|
||||||
trigger.inputs.modelId = model._id
|
|
||||||
trigger.id = "wadiawdo34"
|
trigger.id = "wadiawdo34"
|
||||||
let saveAction = ACTION_DEFINITIONS["SAVE_RECORD"]
|
let saveAction = ACTION_DEFINITIONS["SAVE_RECORD"]
|
||||||
saveAction.inputs.record = {
|
saveAction.inputs.record = {
|
||||||
modelId: model._id,
|
name: "{{trigger.name}}",
|
||||||
name: "Testing",
|
|
||||||
}
|
}
|
||||||
saveAction.id = "awde444wk"
|
saveAction.id = "awde444wk"
|
||||||
let deleteAction = ACTION_DEFINITIONS["DELETE_RECORD"]
|
|
||||||
deleteAction.inputs.id = "{{blocks[1].id}}"
|
|
||||||
deleteAction.inputs.revision = "{{blocks[1].revision}}"
|
|
||||||
deleteAction.id = "78MOt8nQO"
|
|
||||||
|
|
||||||
TEST_WORKFLOW.definition.steps.push(saveAction)
|
TEST_WORKFLOW.definition.steps.push(saveAction)
|
||||||
TEST_WORKFLOW.definition.steps.push(deleteAction)
|
|
||||||
TEST_WORKFLOW.definition.trigger = trigger
|
TEST_WORKFLOW.definition.trigger = trigger
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -139,8 +134,10 @@ describe("/workflows", () => {
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
expect(res.body.message).toEqual("Workflow created successfully");
|
expect(res.body.message).toEqual("Workflow created successfully")
|
||||||
expect(res.body.workflow.name).toEqual("My Workflow");
|
expect(res.body.workflow.name).toEqual("My Workflow")
|
||||||
|
expect(res.body.workflow._id).not.toEqual(null)
|
||||||
|
workflowId = res.body.workflow._id
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should apply authorization to endpoint", async () => {
|
it("should apply authorization to endpoint", async () => {
|
||||||
|
@ -155,12 +152,34 @@ describe("/workflows", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("trigger", () => {
|
||||||
|
it("trigger the workflow successfully", async () => {
|
||||||
|
let model = await createModel(request, app._id, instance._id)
|
||||||
|
TEST_WORKFLOW.definition.trigger.inputs.modelId = model._id
|
||||||
|
TEST_WORKFLOW.definition.steps[0].inputs.record.modelId = model._id
|
||||||
|
await createWorkflow()
|
||||||
|
const res = await request
|
||||||
|
.post(`/api/workflows/${workflow._id}/trigger`)
|
||||||
|
.send({ name: "Test", description: "Test" })
|
||||||
|
.set(defaultHeaders(app._id, instance._id))
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
expect(res.body.message).toEqual(`Workflow ${workflow._id} has been triggered.`)
|
||||||
|
expect(res.body.workflow.name).toEqual(TEST_WORKFLOW.name)
|
||||||
|
// wait for workflow to complete in background
|
||||||
|
await delay(500)
|
||||||
|
let elements = await getAllFromModel(request, app._id, instance._id, model._id)
|
||||||
|
expect(elements.length).toEqual(1)
|
||||||
|
expect(elements[0].name).toEqual("Test")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("update", () => {
|
describe("update", () => {
|
||||||
it("updates a workflows data", async () => {
|
it("updates a workflows data", async () => {
|
||||||
await createWorkflow();
|
await createWorkflow()
|
||||||
workflow._id = workflow.id
|
workflow._id = workflow.id
|
||||||
workflow._rev = workflow.rev
|
workflow._rev = workflow.rev
|
||||||
workflow.name = "Updated Name";
|
workflow.name = "Updated Name"
|
||||||
workflow.type = "workflow"
|
workflow.type = "workflow"
|
||||||
|
|
||||||
const res = await request
|
const res = await request
|
||||||
|
@ -170,21 +189,21 @@ describe("/workflows", () => {
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
expect(res.body.message).toEqual("Workflow Test Workflow updated successfully.");
|
expect(res.body.message).toEqual("Workflow Test Workflow updated successfully.")
|
||||||
expect(res.body.workflow.name).toEqual("Updated Name");
|
expect(res.body.workflow.name).toEqual("Updated Name")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("fetch", () => {
|
describe("fetch", () => {
|
||||||
it("return all the workflows for an instance", async () => {
|
it("return all the workflows for an instance", async () => {
|
||||||
await createWorkflow();
|
await createWorkflow()
|
||||||
const res = await request
|
const res = await request
|
||||||
.get(`/api/workflows`)
|
.get(`/api/workflows`)
|
||||||
.set(defaultHeaders(app._id, instance._id))
|
.set(defaultHeaders(app._id, instance._id))
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
expect(res.body[0]).toEqual(expect.objectContaining(TEST_WORKFLOW));
|
expect(res.body[0]).toEqual(expect.objectContaining(TEST_WORKFLOW))
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should apply authorization to endpoint", async () => {
|
it("should apply authorization to endpoint", async () => {
|
||||||
|
@ -200,18 +219,18 @@ describe("/workflows", () => {
|
||||||
|
|
||||||
describe("destroy", () => {
|
describe("destroy", () => {
|
||||||
it("deletes a workflow by its ID", async () => {
|
it("deletes a workflow by its ID", async () => {
|
||||||
await createWorkflow();
|
await createWorkflow()
|
||||||
const res = await request
|
const res = await request
|
||||||
.delete(`/api/workflows/${workflow.id}/${workflow.rev}`)
|
.delete(`/api/workflows/${workflow.id}/${workflow.rev}`)
|
||||||
.set(defaultHeaders(app._id, instance._id))
|
.set(defaultHeaders(app._id, instance._id))
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
expect(res.body.id).toEqual(TEST_WORKFLOW._id);
|
expect(res.body.id).toEqual(TEST_WORKFLOW._id)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should apply authorization to endpoint", async () => {
|
it("should apply authorization to endpoint", async () => {
|
||||||
await createWorkflow();
|
await createWorkflow()
|
||||||
await builderEndpointShouldBlockNormalUsers({
|
await builderEndpointShouldBlockNormalUsers({
|
||||||
request,
|
request,
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
|
@ -221,4 +240,4 @@ describe("/workflows", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
|
|
|
@ -2,11 +2,34 @@ const mustache = require("mustache")
|
||||||
const actions = require("./actions")
|
const actions = require("./actions")
|
||||||
const logic = require("./logic")
|
const logic = require("./logic")
|
||||||
|
|
||||||
|
function cleanMustache(string) {
|
||||||
|
let charToReplace = {
|
||||||
|
"[": ".",
|
||||||
|
"]": "",
|
||||||
|
}
|
||||||
|
let regex = new RegExp(/{{[^}}]*}}/g)
|
||||||
|
let match
|
||||||
|
while ((match = regex.exec(string)) !== null) {
|
||||||
|
let baseIdx = string.indexOf(match)
|
||||||
|
for (let key of Object.keys(charToReplace)) {
|
||||||
|
let idxChar = match[0].indexOf(key)
|
||||||
|
if (idxChar !== -1) {
|
||||||
|
string =
|
||||||
|
string.slice(baseIdx, baseIdx + idxChar) +
|
||||||
|
charToReplace[key] +
|
||||||
|
string.slice(baseIdx + idxChar + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string
|
||||||
|
}
|
||||||
|
|
||||||
function recurseMustache(inputs, context) {
|
function recurseMustache(inputs, context) {
|
||||||
for (let key in Object.keys(inputs)) {
|
for (let key of Object.keys(inputs)) {
|
||||||
let val = inputs[key]
|
let val = inputs[key]
|
||||||
if (typeof val === "string") {
|
if (typeof val === "string") {
|
||||||
inputs[key] = mustache.render(val, { context })
|
val = cleanMustache(inputs[key])
|
||||||
|
inputs[key] = mustache.render(val, context)
|
||||||
}
|
}
|
||||||
// this covers objects and arrays
|
// this covers objects and arrays
|
||||||
else if (typeof val === "object") {
|
else if (typeof val === "object") {
|
||||||
|
@ -24,8 +47,8 @@ function recurseMustache(inputs, context) {
|
||||||
class Orchestrator {
|
class Orchestrator {
|
||||||
constructor(workflow, triggerOutput) {
|
constructor(workflow, triggerOutput) {
|
||||||
this._instanceId = triggerOutput.instanceId
|
this._instanceId = triggerOutput.instanceId
|
||||||
// block zero is never used as the mustache is zero indexed for customer facing
|
// step zero is never used as the mustache is zero indexed for customer facing
|
||||||
this._context = { blocks: [{}], trigger: triggerOutput }
|
this._context = { steps: [{}], trigger: triggerOutput }
|
||||||
this._workflow = workflow
|
this._workflow = workflow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,15 +67,15 @@ class Orchestrator {
|
||||||
|
|
||||||
async execute() {
|
async execute() {
|
||||||
let workflow = this._workflow
|
let workflow = this._workflow
|
||||||
for (let block of workflow.definition.steps) {
|
for (let step of workflow.definition.steps) {
|
||||||
let stepFn = await this.getStepFunctionality(block.type, block.stepId)
|
let stepFn = await this.getStepFunctionality(step.type, step.stepId)
|
||||||
block.inputs = recurseMustache(block.inputs, this._context)
|
step.inputs = recurseMustache(step.inputs, this._context)
|
||||||
// instanceId is always passed
|
// instanceId is always passed
|
||||||
const outputs = await stepFn({
|
const outputs = await stepFn({
|
||||||
inputs: block.inputs,
|
inputs: step.inputs,
|
||||||
instanceId: this._instanceId,
|
instanceId: this._instanceId,
|
||||||
})
|
})
|
||||||
this._context.blocks.push(outputs)
|
this._context.steps.push(outputs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue