Skip to content

Commit 2dfc9c2

Browse files
Automations API (#243)
* BKNDLSS-34294 - JS-SDK. Add method to run a specific automation flow
1 parent 4c720d4 commit 2dfc9c2

File tree

6 files changed

+229
-0
lines changed

6 files changed

+229
-0
lines changed

backendless.d.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,20 @@ declare module Backendless {
599599
}
600600
}
601601

602+
/**
603+
* @public
604+
* @namespace Backendless.Automations
605+
*/
606+
namespace Automations {
607+
/**
608+
* @public
609+
* @type: Function
610+
*/
611+
612+
function activateFlow(flowName: string, initialData?: object): Promise<void>
613+
function activateFlowTrigger(flowName: string, triggerName: string, data?: object): Promise<void>
614+
}
615+
602616
/**
603617
* @public
604618
* @namespace Backendless.UserService

src/automations/index.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import Utils from '../utils'
2+
3+
export default class Automations {
4+
constructor(app) {
5+
this.app = app
6+
}
7+
8+
async activateFlow(flowName, initialData) {
9+
if (!flowName || typeof flowName !== 'string') {
10+
throw new Error('The "flowName" argument must be provided and must be a string.')
11+
}
12+
13+
if (initialData !== undefined && !Utils.isObject(initialData)) {
14+
throw new Error('The "initialData" argument must be an object with an arbitrary structure.')
15+
}
16+
17+
return this.app.request.post({
18+
url : `${this.app.urls.automationFlow()}/activate-by-name`,
19+
data: {
20+
name: flowName,
21+
initialData,
22+
}
23+
})
24+
}
25+
26+
async activateFlowTrigger(flowName, triggerName, data) {
27+
if (!flowName || typeof flowName !== 'string') {
28+
throw new Error('The "flowName" argument must be provided and must be a string.')
29+
}
30+
31+
if (!triggerName || typeof triggerName !== 'string') {
32+
throw new Error('The "triggerName" argument must be provided and must be a string.')
33+
}
34+
35+
if (data !== undefined && !Utils.isObject(data)) {
36+
throw new Error('The "data" argument must be an object with an arbitrary structure.')
37+
}
38+
39+
return this.app.request.post({
40+
url : `${this.app.urls.automationFlowTrigger()}/activate-by-name`,
41+
query: { flowName, triggerName },
42+
data,
43+
})
44+
}
45+
}

src/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ const SERVICES = {
8484
'LocalCache' : () => require('./local-cache').default,
8585
'UnitOfWork' : () => require('./unit-of-work').default,
8686
'Management' : () => require('./management').default,
87+
'Automations' : () => require('./automations').default,
8788
}
8889

8990
class Backendless {
@@ -427,6 +428,10 @@ class Backendless {
427428
return this.__getService('Management')
428429
}
429430

431+
get Automations() {
432+
return this.__getService('Automations')
433+
}
434+
430435
///-------------- SERVICES -------------///
431436
///-------------------------------------///
432437

src/urls.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ export default class Urls {
77
return this.app.appPath
88
}
99

10+
//automations
11+
12+
automation() {
13+
return `${this.root()}/automation`
14+
}
15+
16+
automationFlow() {
17+
return `${this.automation()}/flow`
18+
}
19+
20+
automationFlowTrigger() {
21+
return `${this.automationFlow()}/trigger`
22+
}
23+
1024
//bl
1125

1226
blServices() {

test/tsd.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,17 @@ function testEmailEnvelope() {
15221522
uniqueEmails = envelopeObject.getUniqueEmails();
15231523
}
15241524

1525+
function testAutomations() {
1526+
type TestObjType = { [x: string]: number }
1527+
const obj: TestObjType = {x: 1, y: 2};
1528+
const flowName: string = 'str';
1529+
const triggerName: string = 'str';
1530+
let promiseObject: Promise<void>;
1531+
1532+
promiseObject = Backendless.Automations.activateFlow(flowName, obj);
1533+
promiseObject = Backendless.Automations.activateFlowTrigger(flowName, triggerName, obj);
1534+
}
1535+
15251536
function testMessaging() {
15261537
const channelName: string = 'str';
15271538
const deviceToken: string = 'str';
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import { expect } from 'chai'
2+
import { describe, it } from 'mocha'
3+
4+
import Backendless, { prepareMockRequest, APP_PATH, forTest } from '../../helpers/sandbox'
5+
6+
describe('<Automations> Basic', function() {
7+
forTest(this)
8+
9+
const FLOW_NAME = 'FlowName'
10+
const TRIGGER_NAME = 'TriggerName'
11+
12+
describe('activate flow by name', function() {
13+
it('success', async () => {
14+
const req1 = prepareMockRequest()
15+
const req2 = prepareMockRequest()
16+
await Backendless.Automations.activateFlow(FLOW_NAME)
17+
await Backendless.Automations.activateFlow(FLOW_NAME, { name: 'Nick' })
18+
19+
expect(req1).to.deep.include({
20+
method: 'POST',
21+
path : `${APP_PATH}/automation/flow/activate-by-name`,
22+
body : {
23+
name: 'FlowName',
24+
}
25+
})
26+
27+
expect(req2).to.deep.include({
28+
method: 'POST',
29+
path : `${APP_PATH}/automation/flow/activate-by-name`,
30+
body : {
31+
name : 'FlowName',
32+
initialData: {
33+
name: 'Nick',
34+
},
35+
}
36+
})
37+
38+
})
39+
40+
it('fails when flow name is invalid', async () => {
41+
const errorMsg = 'The "flowName" argument must be provided and must be a string.'
42+
43+
await expect(Backendless.Automations.activateFlow()).to.eventually.be.rejectedWith(errorMsg)
44+
await expect(Backendless.Automations.activateFlow(undefined)).to.eventually.be.rejectedWith(errorMsg)
45+
await expect(Backendless.Automations.activateFlow(null)).to.eventually.be.rejectedWith(errorMsg)
46+
await expect(Backendless.Automations.activateFlow(true)).to.eventually.be.rejectedWith(errorMsg)
47+
await expect(Backendless.Automations.activateFlow(false)).to.eventually.be.rejectedWith(errorMsg)
48+
await expect(Backendless.Automations.activateFlow(0)).to.eventually.be.rejectedWith(errorMsg)
49+
await expect(Backendless.Automations.activateFlow(123)).to.eventually.be.rejectedWith(errorMsg)
50+
await expect(Backendless.Automations.activateFlow('')).to.eventually.be.rejectedWith(errorMsg)
51+
await expect(Backendless.Automations.activateFlow({})).to.eventually.be.rejectedWith(errorMsg)
52+
await expect(Backendless.Automations.activateFlow([])).to.eventually.be.rejectedWith(errorMsg)
53+
await expect(Backendless.Automations.activateFlow(() => ({}))).to.eventually.be.rejectedWith(errorMsg)
54+
})
55+
56+
it('fails when initial data is invalid', async () => {
57+
const errorMsg = 'The "initialData" argument must be an object with an arbitrary structure.'
58+
59+
await expect(Backendless.Automations.activateFlow(FLOW_NAME, null)).to.eventually.be.rejectedWith(errorMsg)
60+
await expect(Backendless.Automations.activateFlow(FLOW_NAME, true)).to.eventually.be.rejectedWith(errorMsg)
61+
await expect(Backendless.Automations.activateFlow(FLOW_NAME, false)).to.eventually.be.rejectedWith(errorMsg)
62+
await expect(Backendless.Automations.activateFlow(FLOW_NAME, 0)).to.eventually.be.rejectedWith(errorMsg)
63+
await expect(Backendless.Automations.activateFlow(FLOW_NAME, 123)).to.eventually.be.rejectedWith(errorMsg)
64+
await expect(Backendless.Automations.activateFlow(FLOW_NAME, 'asd')).to.eventually.be.rejectedWith(errorMsg)
65+
await expect(Backendless.Automations.activateFlow(FLOW_NAME, '')).to.eventually.be.rejectedWith(errorMsg)
66+
await expect(Backendless.Automations.activateFlow(FLOW_NAME, [])).to.eventually.be.rejectedWith(errorMsg)
67+
await expect(Backendless.Automations.activateFlow(FLOW_NAME, () => ({}))).to.eventually.be.rejectedWith(errorMsg)
68+
})
69+
})
70+
71+
describe('activate flow trigger', function() {
72+
it('success', async () => {
73+
const req1 = prepareMockRequest()
74+
const req2 = prepareMockRequest()
75+
await Backendless.Automations.activateFlowTrigger(FLOW_NAME, TRIGGER_NAME)
76+
await Backendless.Automations.activateFlowTrigger(FLOW_NAME, TRIGGER_NAME, { name: 'Nick' })
77+
78+
expect(req1).to.deep.include({
79+
method: 'POST',
80+
path : `${APP_PATH}/automation/flow/trigger/activate-by-name?flowName=${FLOW_NAME}&triggerName=${TRIGGER_NAME}`,
81+
})
82+
83+
expect(req2).to.deep.include({
84+
method: 'POST',
85+
path : `${APP_PATH}/automation/flow/trigger/activate-by-name?flowName=${FLOW_NAME}&triggerName=${TRIGGER_NAME}`,
86+
body : {
87+
name: 'Nick',
88+
}
89+
})
90+
91+
})
92+
93+
it('fails when flow name is invalid', async () => {
94+
const errorMsg = 'The "flowName" argument must be provided and must be a string.'
95+
96+
await expect(Backendless.Automations.activateFlowTrigger()).to.eventually.be.rejectedWith(errorMsg)
97+
await expect(Backendless.Automations.activateFlowTrigger(undefined)).to.eventually.be.rejectedWith(errorMsg)
98+
await expect(Backendless.Automations.activateFlowTrigger(null)).to.eventually.be.rejectedWith(errorMsg)
99+
await expect(Backendless.Automations.activateFlowTrigger(true)).to.eventually.be.rejectedWith(errorMsg)
100+
await expect(Backendless.Automations.activateFlowTrigger(false)).to.eventually.be.rejectedWith(errorMsg)
101+
await expect(Backendless.Automations.activateFlowTrigger(0)).to.eventually.be.rejectedWith(errorMsg)
102+
await expect(Backendless.Automations.activateFlowTrigger(123)).to.eventually.be.rejectedWith(errorMsg)
103+
await expect(Backendless.Automations.activateFlowTrigger('')).to.eventually.be.rejectedWith(errorMsg)
104+
await expect(Backendless.Automations.activateFlowTrigger({})).to.eventually.be.rejectedWith(errorMsg)
105+
await expect(Backendless.Automations.activateFlowTrigger([])).to.eventually.be.rejectedWith(errorMsg)
106+
await expect(Backendless.Automations.activateFlowTrigger(() => ({}))).to.eventually.be.rejectedWith(errorMsg)
107+
})
108+
109+
it('fails when trigger name is invalid', async () => {
110+
const errorMsg = 'The "triggerName" argument must be provided and must be a string.'
111+
112+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, )).to.eventually.be.rejectedWith(errorMsg)
113+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, undefined)).to.eventually.be.rejectedWith(errorMsg)
114+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME,null)).to.eventually.be.rejectedWith(errorMsg)
115+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, true)).to.eventually.be.rejectedWith(errorMsg)
116+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, false)).to.eventually.be.rejectedWith(errorMsg)
117+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, 0)).to.eventually.be.rejectedWith(errorMsg)
118+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, 123)).to.eventually.be.rejectedWith(errorMsg)
119+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, '')).to.eventually.be.rejectedWith(errorMsg)
120+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, {})).to.eventually.be.rejectedWith(errorMsg)
121+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, [])).to.eventually.be.rejectedWith(errorMsg)
122+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, () => ({}))).to.eventually.be.rejectedWith(errorMsg)
123+
})
124+
125+
it('fails when data is invalid', async () => {
126+
const errorMsg = 'The "data" argument must be an object with an arbitrary structure.'
127+
128+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, TRIGGER_NAME, null)).to.eventually.be.rejectedWith(errorMsg)
129+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, TRIGGER_NAME, true)).to.eventually.be.rejectedWith(errorMsg)
130+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, TRIGGER_NAME, false)).to.eventually.be.rejectedWith(errorMsg)
131+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, TRIGGER_NAME, 0)).to.eventually.be.rejectedWith(errorMsg)
132+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, TRIGGER_NAME, 123)).to.eventually.be.rejectedWith(errorMsg)
133+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, TRIGGER_NAME, 'asd')).to.eventually.be.rejectedWith(errorMsg)
134+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, TRIGGER_NAME, '')).to.eventually.be.rejectedWith(errorMsg)
135+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, TRIGGER_NAME, [])).to.eventually.be.rejectedWith(errorMsg)
136+
await expect(Backendless.Automations.activateFlowTrigger(FLOW_NAME, TRIGGER_NAME, () => ({}))).to.eventually.be.rejectedWith(errorMsg)
137+
})
138+
})
139+
140+
})

0 commit comments

Comments
 (0)