1 |
|
2 |
|
3 | const tymly = require('./../lib')
|
4 | const path = require('path')
|
5 | const chai = require('chai')
|
6 | chai.use(require('dirty-chai'))
|
7 | const expect = chai.expect
|
8 |
|
9 | const DAY_IN_THE_LIFE_LAUNCHER = 'tymlyTest_launchADayInTheLife'
|
10 | const DAY_IN_THE_LIFE = 'tymlyTest_aDayInTheLife'
|
11 | const JUSTFAIL_LAUNCHER = 'tymlyTest_launchJustFail'
|
12 | const JUSTFAIL = 'tymlyTest_justFail'
|
13 |
|
14 | describe('Launch-state-machine state resources', function () {
|
15 | this.timeout(process.env.TIMEOUT || 5000)
|
16 |
|
17 | describe('launched state machines runs successfully', () => {
|
18 | let tymlyService
|
19 | let statebox
|
20 | let launched
|
21 |
|
22 | before('boot tymly', function (done) {
|
23 | tymly.boot(
|
24 | {
|
25 | blueprintPaths: [
|
26 | path.resolve(__dirname, './fixtures/blueprints/cats-blueprint'),
|
27 | path.resolve(__dirname, './fixtures/blueprints/cats-launcher-blueprint')
|
28 | ],
|
29 |
|
30 | pluginPaths: [
|
31 | path.resolve(__dirname, './fixtures/plugins/cats-plugin'),
|
32 | path.resolve(__dirname, '../node_modules/@wmfs/tymly-test-helpers/plugins/allow-everything-rbac-plugin')
|
33 | ]
|
34 | },
|
35 | function (err, tymlyServices) {
|
36 | expect(err).to.eql(null)
|
37 | tymlyService = tymlyServices.tymly
|
38 | statebox = tymlyServices.statebox
|
39 | done()
|
40 | }
|
41 | )
|
42 | })
|
43 |
|
44 | it('launcher completes successfully', async () => {
|
45 | const executionDescription = await statebox.startExecution(
|
46 | {
|
47 | petName: 'Rupert',
|
48 | gender: 'male',
|
49 | hoursSinceLastMotion: 11,
|
50 | hoursSinceLastMeal: 5,
|
51 | petDiary: []
|
52 | },
|
53 | DAY_IN_THE_LIFE_LAUNCHER,
|
54 | {
|
55 | sendResponse: 'COMPLETE'
|
56 | }
|
57 | )
|
58 |
|
59 | expect(executionDescription.status).to.eql('SUCCEEDED')
|
60 | expect(executionDescription.stateMachineName).to.eql(DAY_IN_THE_LIFE_LAUNCHER)
|
61 | expect(executionDescription.currentStateName).to.eql('Start')
|
62 |
|
63 | const launchedResult = executionDescription.ctx.launched
|
64 | expect(launchedResult).to.not.be.null()
|
65 | expect(launchedResult.executionName).to.not.be.null()
|
66 | expect(launchedResult.status).to.eql('RUNNING')
|
67 | expect(launchedResult.startDate).to.not.be.null()
|
68 |
|
69 | launched = launchedResult.executionName
|
70 | })
|
71 |
|
72 | it('launched state machine completes successfully', async () => {
|
73 | const executionDescription = await statebox.waitUntilStoppedRunning(launched)
|
74 |
|
75 | expect(executionDescription.status).to.eql('SUCCEEDED')
|
76 | expect(executionDescription.stateMachineName).to.eql(DAY_IN_THE_LIFE)
|
77 | expect(executionDescription.ctx.hoursSinceLastMeal).to.eql(0)
|
78 | expect(executionDescription.ctx.hoursSinceLastMotion).to.eql(0)
|
79 | expect(executionDescription.ctx.gender).to.eql('male')
|
80 | expect(executionDescription.ctx.petDiary).to.be.an('array')
|
81 | expect(executionDescription.ctx.petDiary[0]).to.equal('Look out, Rupert is waking up!')
|
82 | expect(executionDescription.ctx.petDiary[2]).to.equal('Rupert is walking... where\'s he off to?')
|
83 | expect(executionDescription.ctx.petDiary[6]).to.equal('Shh, Rupert is eating...')
|
84 | })
|
85 |
|
86 | after('shutdown Tymly', async () => {
|
87 | await tymlyService.shutdown()
|
88 | })
|
89 | })
|
90 |
|
91 | describe('launched state machine doesn\'t exist', () => {
|
92 | let tymlyService
|
93 | let statebox
|
94 | let launcher
|
95 |
|
96 | before('boot tymly', function (done) {
|
97 | tymly.boot(
|
98 | {
|
99 | blueprintPaths: [
|
100 | path.resolve(__dirname, './fixtures/blueprints/cats-launcher-blueprint')
|
101 | ],
|
102 | pluginPaths: [
|
103 | path.resolve(__dirname, '../node_modules/@wmfs/tymly-test-helpers/plugins/allow-everything-rbac-plugin')
|
104 | ]
|
105 | },
|
106 | function (err, tymlyServices) {
|
107 | expect(err).to.eql(null)
|
108 | tymlyService = tymlyServices.tymly
|
109 | statebox = tymlyServices.statebox
|
110 | done()
|
111 | }
|
112 | )
|
113 | })
|
114 |
|
115 | it('start launcher', async () => {
|
116 | const result = await statebox.startExecution(
|
117 | {
|
118 | petName: 'Rupert',
|
119 | gender: 'male',
|
120 | hoursSinceLastMotion: 11,
|
121 | hoursSinceLastMeal: 5,
|
122 | petDiary: []
|
123 | },
|
124 | DAY_IN_THE_LIFE_LAUNCHER,
|
125 | {}
|
126 | )
|
127 |
|
128 | launcher = result.executionName
|
129 | })
|
130 |
|
131 | it('launcher failed', async () => {
|
132 | const executionDescription = await statebox.waitUntilStoppedRunning(launcher)
|
133 |
|
134 | expect(executionDescription.status).to.eql('FAILED')
|
135 | expect(executionDescription.errorCode).to.eql('launchStateMachine')
|
136 | expect(executionDescription.stateMachineName).to.eql(DAY_IN_THE_LIFE_LAUNCHER)
|
137 | expect(executionDescription.currentStateName).to.eql('Start')
|
138 | })
|
139 |
|
140 | after('shutdown Tymly', async () => {
|
141 | await tymlyService.shutdown()
|
142 | })
|
143 | })
|
144 |
|
145 | describe('launched state machine fails', () => {
|
146 | let tymlyService
|
147 | let statebox
|
148 | let launched
|
149 |
|
150 | before('boot tymly', function (done) {
|
151 | tymly.boot(
|
152 | {
|
153 | blueprintPaths: [
|
154 | path.resolve(__dirname, './fixtures/blueprints/failing-blueprint')
|
155 | ],
|
156 | pluginPaths: [
|
157 | path.resolve(__dirname, './fixtures/plugins/justfail-plugin'),
|
158 | path.resolve(__dirname, '../node_modules/@wmfs/tymly-test-helpers/plugins/allow-everything-rbac-plugin')
|
159 | ]
|
160 | },
|
161 | function (err, tymlyServices) {
|
162 | expect(err).to.eql(null)
|
163 | tymlyService = tymlyServices.tymly
|
164 | statebox = tymlyServices.statebox
|
165 | done()
|
166 | }
|
167 | )
|
168 | })
|
169 |
|
170 | it('launcher completes successfully', async () => {
|
171 | const executionDescription = await statebox.startExecution(
|
172 | { },
|
173 | JUSTFAIL_LAUNCHER,
|
174 | {
|
175 | sendResponse: 'COMPLETED'
|
176 | }
|
177 | )
|
178 |
|
179 | expect(executionDescription.status).to.eql('SUCCEEDED')
|
180 | expect(executionDescription.stateMachineName).to.eql(JUSTFAIL_LAUNCHER)
|
181 | expect(executionDescription.currentStateName).to.eql('Start')
|
182 |
|
183 | const launchedResult = executionDescription.ctx
|
184 | expect(launchedResult).to.not.be.null()
|
185 | expect(launchedResult.executionName).to.not.be.null()
|
186 | expect(launchedResult.status).to.eql('RUNNING')
|
187 | expect(launchedResult.startDate).to.not.be.null()
|
188 |
|
189 | launched = launchedResult.executionName
|
190 | })
|
191 |
|
192 | it('launched state machine fails', async () => {
|
193 | const executionDescription = await statebox.waitUntilStoppedRunning(launched)
|
194 |
|
195 | expect(executionDescription.status).to.eql('FAILED')
|
196 | expect(executionDescription.errorCode).to.eql('justFail')
|
197 | expect(executionDescription.stateMachineName).to.eql(JUSTFAIL)
|
198 | expect(executionDescription.currentStateName).to.eql('JustFail')
|
199 | })
|
200 |
|
201 | after('shutdown Tymly', async () => {
|
202 | await tymlyService.shutdown()
|
203 | })
|
204 | })
|
205 |
|
206 | describe('launched state machine gets parent execution name', () => {
|
207 | let tymlyService
|
208 | let statebox
|
209 | let launcher
|
210 | let launched
|
211 |
|
212 | it('boot tymly', async () => {
|
213 | const tymlyServices = await tymly.boot(
|
214 | {
|
215 | blueprintPaths: [
|
216 | path.resolve(__dirname, './fixtures/blueprints/launcher-blueprint')
|
217 | ],
|
218 | pluginPaths: [
|
219 | path.resolve(__dirname, '../node_modules/@wmfs/tymly-test-helpers/plugins/allow-everything-rbac-plugin')
|
220 | ]
|
221 | }
|
222 | )
|
223 | tymlyService = tymlyServices.tymly
|
224 | statebox = tymlyServices.statebox
|
225 | })
|
226 |
|
227 | it('launch state machine', async () => {
|
228 | const executionDescription = await statebox.startExecution(
|
229 | { },
|
230 | 'tymlyTest_passExecutionNameToLaunched',
|
231 | {
|
232 | sendResponse: 'COMPLETE'
|
233 | }
|
234 | )
|
235 |
|
236 | expect(executionDescription.status).to.eql('SUCCEEDED')
|
237 |
|
238 | const launchedResult = executionDescription.ctx
|
239 | expect(launchedResult).to.not.be.null()
|
240 | expect(launchedResult.executionName).to.not.be.null()
|
241 |
|
242 | launched = launchedResult.executionName
|
243 | launcher = executionDescription.executionName
|
244 | })
|
245 |
|
246 | it('launched state machine returns parent execution name', async () => {
|
247 | const executionDescription = await statebox.waitUntilStoppedRunning(launched)
|
248 |
|
249 | expect(executionDescription.status).to.eql('SUCCEEDED')
|
250 |
|
251 | expect(executionDescription.executionName).to.eql(launched)
|
252 | expect(executionDescription.ctx).to.eql(launcher)
|
253 | })
|
254 |
|
255 | after('shutdown Tymly', async () => {
|
256 | await tymlyService.shutdown()
|
257 | })
|
258 | })
|
259 |
|
260 | describe('launched state machine sends result to parent execution', async () => {
|
261 | let tymlyService
|
262 | let statebox
|
263 | let parent
|
264 | let launched
|
265 | let launchedResult
|
266 |
|
267 | before('boot tymly', async () => {
|
268 | const tymlyServices = await tymly.boot(
|
269 | {
|
270 | blueprintPaths: [
|
271 | path.resolve(__dirname, './fixtures/blueprints/launcher-blueprint')
|
272 | ],
|
273 | pluginPaths: [
|
274 | path.resolve(__dirname, '../node_modules/@wmfs/tymly-test-helpers/plugins/allow-everything-rbac-plugin')
|
275 | ]
|
276 | }
|
277 | )
|
278 | tymlyService = tymlyServices.tymly
|
279 | statebox = tymlyServices.statebox
|
280 | })
|
281 |
|
282 | it('launch state machine', async () => {
|
283 | const parentExecDesc = await statebox.startExecution(
|
284 | { },
|
285 | 'tymlyTest_parentWaitsForResult',
|
286 | { }
|
287 | )
|
288 |
|
289 | parent = parentExecDesc.executionName
|
290 | })
|
291 |
|
292 | it('launcher is paused, waiting for result', async () => {
|
293 | const parentExecDesc = await statebox.describeExecution(parent)
|
294 | expect(parentExecDesc.status).to.eql('RUNNING')
|
295 |
|
296 | launched = parentExecDesc.ctx.executionName
|
297 | })
|
298 |
|
299 | it('wait for launched state machine to complete', async () => {
|
300 | const launchedExecDesc = await statebox.waitUntilStoppedRunning(launched)
|
301 |
|
302 | expect(launchedExecDesc.status).to.eql('SUCCEEDED')
|
303 | expect(launchedExecDesc.executionName).to.eql(launched)
|
304 |
|
305 | launchedResult = launchedExecDesc.ctx
|
306 | })
|
307 |
|
308 | it('launcher completes, returning result passed back from launched', async () => {
|
309 | const parentExecDesc = await statebox.waitUntilStoppedRunning(parent)
|
310 |
|
311 | expect(parentExecDesc.status).to.eql('SUCCEEDED')
|
312 | expect(parentExecDesc.executionName).to.eql(parent)
|
313 |
|
314 | expect(parentExecDesc.ctx.launchedResult).to.eql(launchedResult)
|
315 | })
|
316 |
|
317 | after('shutdown Tymly', async () => {
|
318 | await tymlyService.shutdown()
|
319 | })
|
320 | })
|
321 |
|
322 | describe('awaitingExternalInput state resource', async () => {
|
323 | let tymlyService
|
324 | let statebox
|
325 |
|
326 | before('boot tymly', async () => {
|
327 | const tymlyServices = await tymly.boot(
|
328 | {
|
329 | blueprintPaths: [
|
330 | path.resolve(__dirname, './fixtures/blueprints/launcher-blueprint')
|
331 | ],
|
332 | pluginPaths: [
|
333 | path.resolve(__dirname, '../node_modules/@wmfs/tymly-test-helpers/plugins/allow-everything-rbac-plugin')
|
334 | ]
|
335 | }
|
336 | )
|
337 | tymlyService = tymlyServices.tymly
|
338 | statebox = tymlyServices.statebox
|
339 | })
|
340 |
|
341 | it('time out and continue', async () => {
|
342 | const parentExecDesc = await statebox.startExecution(
|
343 | { },
|
344 | 'tymlyTest_waitTimesOutAndContinue',
|
345 | {
|
346 | sendResponse: 'COMPLETED'
|
347 | }
|
348 | )
|
349 | expect(parentExecDesc.status).to.eql('SUCCEEDED')
|
350 | expect(parentExecDesc.ctx.launchedResult).to.eql('time-out')
|
351 | expect(parentExecDesc.ctx.good).to.eql('stuff')
|
352 | })
|
353 |
|
354 | it('time out and fail', async () => {
|
355 | const parentExecDesc = await statebox.startExecution(
|
356 | {},
|
357 | 'tymlyTest_waitTimesOutAndFail',
|
358 | {
|
359 | sendResponse: 'COMPLETED'
|
360 | }
|
361 | )
|
362 | expect(parentExecDesc.status).to.eql('FAILED')
|
363 | })
|
364 |
|
365 | after('shutdown Tymly', async () => {
|
366 | await tymlyService.shutdown()
|
367 | })
|
368 | })
|
369 |
|
370 | describe('sendTaskSuccess state resource', async () => {
|
371 | let tymlyService
|
372 | let statebox
|
373 |
|
374 | before('boot tymly', async () => {
|
375 | const tymlyServices = await tymly.boot(
|
376 | {
|
377 | blueprintPaths: [
|
378 | path.resolve(__dirname, './fixtures/blueprints/launcher-blueprint')
|
379 | ],
|
380 | pluginPaths: [
|
381 | path.resolve(__dirname, '../node_modules/@wmfs/tymly-test-helpers/plugins/allow-everything-rbac-plugin')
|
382 | ]
|
383 | }
|
384 | )
|
385 | tymlyService = tymlyServices.tymly
|
386 | statebox = tymlyServices.statebox
|
387 | })
|
388 |
|
389 | it('fails if invalid execution name', async () => {
|
390 | const executionDescription = await statebox.startExecution(
|
391 | { },
|
392 | 'tymlyTest_launchedSendsResultToParent',
|
393 | {
|
394 | sendResponse: 'COMPLETE'
|
395 | }
|
396 | )
|
397 |
|
398 | expect(executionDescription.status).to.eql('FAILED')
|
399 | })
|
400 |
|
401 | it('doesn\'t fail if invalid execution name when relaxed is true', async () => {
|
402 | const executionDescription = await statebox.startExecution(
|
403 | { },
|
404 | 'tymlyTest_relaxedSendTaskSuccess',
|
405 | {
|
406 | sendResponse: 'COMPLETE'
|
407 | }
|
408 | )
|
409 |
|
410 | expect(executionDescription.status).to.eql('SUCCEEDED')
|
411 | })
|
412 |
|
413 | after('shutdown Tymly', async () => {
|
414 | await tymlyService.shutdown()
|
415 | })
|
416 | })
|
417 |
|
418 | describe('sendTaskHeartbeat state resource', async () => {
|
419 | let tymlyService
|
420 | let statebox
|
421 | let parentExecution
|
422 |
|
423 | before('boot tymly', async () => {
|
424 | const tymlyServices = await tymly.boot(
|
425 | {
|
426 | blueprintPaths: [
|
427 | path.resolve(__dirname, './fixtures/blueprints/launcher-blueprint')
|
428 | ],
|
429 | pluginPaths: [
|
430 | path.resolve(__dirname, '../node_modules/@wmfs/tymly-test-helpers/plugins/allow-everything-rbac-plugin')
|
431 | ]
|
432 | }
|
433 | )
|
434 | tymlyService = tymlyServices.tymly
|
435 | statebox = tymlyServices.statebox
|
436 | })
|
437 |
|
438 | it('launched execution sends heartbeat to parent', async () => {
|
439 | const executionDescription = await statebox.startExecution(
|
440 | { },
|
441 | 'tymlyTest_parentGetsUpdates',
|
442 | {
|
443 | sendResponse: 'IMMEDIATELY'
|
444 | }
|
445 | )
|
446 |
|
447 | parentExecution = executionDescription.executionName
|
448 | expect(executionDescription.status).to.eql('RUNNING')
|
449 | })
|
450 |
|
451 | it('check for first update', async () => {
|
452 | await pause()
|
453 |
|
454 | const executionDescription = await statebox.describeExecution(parentExecution)
|
455 | expect(executionDescription.status).to.eql('RUNNING')
|
456 | expect(executionDescription.ctx.launchedResult).to.equals('STARTED')
|
457 | })
|
458 |
|
459 | it('wait for second update', async () => {
|
460 | await pause()
|
461 | await pause()
|
462 |
|
463 | const executionDescription = await statebox.describeExecution(parentExecution)
|
464 | expect(executionDescription.status).to.eql('RUNNING')
|
465 | expect(executionDescription.ctx.launchedResult).to.equals('UPDATED')
|
466 | })
|
467 |
|
468 | it('third update completes parent execution', async () => {
|
469 | const executionDescription = await statebox.waitUntilStoppedRunning(parentExecution)
|
470 |
|
471 | expect(executionDescription.status).to.eql('SUCCEEDED')
|
472 | expect(executionDescription.ctx.launchedResult).to.equals('EXPIRED')
|
473 | })
|
474 |
|
475 | after('shutdown Tymly', async () => {
|
476 | await tymlyService.shutdown()
|
477 | })
|
478 | })
|
479 | })
|
480 |
|
481 | function pause () {
|
482 | return new Promise((resolve, reject) => {
|
483 | setTimeout(() => resolve(), 1000)
|
484 | })
|
485 | }
|