hubot 5.0.4 → 5.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/package.json +1 -1
  2. package/src/robot.js +0 -11
  3. package/.editorconfig +0 -14
  4. package/.github/stale.yml +0 -23
  5. package/.github/workflows/nodejs-macos.yml +0 -26
  6. package/.github/workflows/nodejs-ubuntu.yml +0 -28
  7. package/.github/workflows/nodejs-windows.yml +0 -26
  8. package/.github/workflows/release.yml +0 -37
  9. package/bin/e2e-test.sh +0 -47
  10. package/docs/adapters/campfire.md +0 -79
  11. package/docs/adapters/development.md +0 -125
  12. package/docs/adapters/shell.md +0 -24
  13. package/docs/adapters.md +0 -27
  14. package/docs/deploying/azure.md +0 -97
  15. package/docs/deploying/bluemix.md +0 -111
  16. package/docs/deploying/heroku.md +0 -66
  17. package/docs/deploying/unix.md +0 -72
  18. package/docs/deploying/windows.md +0 -66
  19. package/docs/deploying.md +0 -11
  20. package/docs/implementation.md +0 -55
  21. package/docs/index.md +0 -125
  22. package/docs/patterns.md +0 -265
  23. package/docs/scripting.md +0 -1051
  24. package/examples/hubot-start.ps1 +0 -12
  25. package/examples/hubot.service +0 -27
  26. package/script/bootstrap +0 -3
  27. package/script/release +0 -44
  28. package/script/server +0 -3
  29. package/script/smoke-test +0 -3
  30. package/script/test +0 -3
  31. package/test/adapter_test.js +0 -97
  32. package/test/brain_test.js +0 -336
  33. package/test/datastore_test.js +0 -154
  34. package/test/es2015_test.js +0 -199
  35. package/test/fixtures/MockAdapter.coffee +0 -10
  36. package/test/fixtures/MockAdapter.mjs +0 -43
  37. package/test/fixtures/TestScript.coffee +0 -9
  38. package/test/fixtures/TestScript.js +0 -13
  39. package/test/fixtures/mock-adapter.js +0 -35
  40. package/test/listener_test.js +0 -379
  41. package/test/message_test.js +0 -46
  42. package/test/middleware_test.js +0 -507
  43. package/test/robot_test.js +0 -1153
  44. package/test/shell_test.js +0 -73
  45. package/test/user_test.js +0 -29
@@ -1,46 +0,0 @@
1
- 'use strict'
2
-
3
- /* global describe, beforeEach, it */
4
- /* eslint-disable no-unused-expressions */
5
-
6
- // Assertions and Stubbing
7
- const chai = require('chai')
8
- chai.use(require('sinon-chai'))
9
-
10
- const expect = chai.expect
11
-
12
- // Hubot classes
13
- const User = require('../src/user')
14
- const Message = require('../src/message').Message
15
- const TextMessage = require('../src/message').TextMessage
16
-
17
- describe('Message', function () {
18
- beforeEach(function () {
19
- this.user = new User({
20
- id: 1,
21
- name: 'hubottester',
22
- room: '#mocha'
23
- })
24
- })
25
-
26
- describe('Unit Tests', function () {
27
- describe('#finish', () =>
28
- it('marks the message as done', function () {
29
- const testMessage = new Message(this.user)
30
- expect(testMessage.done).to.not.be.ok
31
- testMessage.finish()
32
- expect(testMessage.done).to.be.ok
33
- })
34
- )
35
-
36
- describe('TextMessage', () =>
37
- describe('#match', () =>
38
- it('should perform standard regex matching', function () {
39
- const testMessage = new TextMessage(this.user, 'message123')
40
- expect(testMessage.match(/^message123$/)).to.be.ok
41
- expect(testMessage.match(/^does-not-match$/)).to.not.be.ok
42
- })
43
- )
44
- )
45
- })
46
- })
@@ -1,507 +0,0 @@
1
- 'use strict'
2
-
3
- /* global describe, beforeEach, it, afterEach */
4
- /* eslint-disable no-unused-expressions */
5
-
6
- // Assertions and Stubbing
7
- const chai = require('chai')
8
- const sinon = require('sinon')
9
- chai.use(require('sinon-chai'))
10
-
11
- const expect = chai.expect
12
-
13
- // Hubot classes
14
- const Robot = require('../src/robot')
15
- const TextMessage = require('../src/message').TextMessage
16
- const Response = require('../src/response')
17
- const Middleware = require('../src/middleware')
18
-
19
- // mock `hubot-mock-adapter` module from fixture
20
- const mockery = require('mockery')
21
-
22
- describe('Middleware', function () {
23
- describe('Unit Tests', function () {
24
- beforeEach(function () {
25
- // Stub out event emitting
26
- this.robot = { emit: sinon.spy() }
27
-
28
- this.middleware = new Middleware(this.robot)
29
- })
30
-
31
- describe('#execute', function () {
32
- it('executes synchronous middleware', function (testDone) {
33
- const testMiddleware = sinon.spy((context, next, done) => {
34
- next(done)
35
- })
36
-
37
- this.middleware.register(testMiddleware)
38
-
39
- const middlewareFinished = function () {
40
- expect(testMiddleware).to.have.been.called
41
- testDone()
42
- }
43
-
44
- this.middleware.execute(
45
- {},
46
- (_, done) => done(),
47
- middlewareFinished
48
- )
49
- })
50
-
51
- it('executes asynchronous middleware', function (testDone) {
52
- const testMiddleware = sinon.spy((context, next, done) =>
53
- // Yield to the event loop
54
- process.nextTick(() => next(done))
55
- )
56
-
57
- this.middleware.register(testMiddleware)
58
-
59
- const middlewareFinished = function (context, done) {
60
- expect(testMiddleware).to.have.been.called
61
- testDone()
62
- }
63
-
64
- this.middleware.execute(
65
- {},
66
- (_, done) => done(),
67
- middlewareFinished
68
- )
69
- })
70
-
71
- it('passes the correct arguments to each middleware', function (testDone) {
72
- const testContext = {}
73
- const testMiddleware = (context, next, done) =>
74
- // Break out of middleware error handling so assertion errors are
75
- // more visible
76
- process.nextTick(function () {
77
- // Check that variables were passed correctly
78
- expect(context).to.equal(testContext)
79
- next(done)
80
- })
81
-
82
- this.middleware.register(testMiddleware)
83
-
84
- this.middleware.execute(
85
- testContext,
86
- (_, done) => done(),
87
- () => testDone())
88
- })
89
-
90
- it('executes all registered middleware in definition order', function (testDone) {
91
- const middlewareExecution = []
92
-
93
- const testMiddlewareA = (context, next, done) => {
94
- middlewareExecution.push('A')
95
- next(done)
96
- }
97
-
98
- const testMiddlewareB = function (context, next, done) {
99
- middlewareExecution.push('B')
100
- next(done)
101
- }
102
-
103
- this.middleware.register(testMiddlewareA)
104
- this.middleware.register(testMiddlewareB)
105
-
106
- const middlewareFinished = function () {
107
- expect(middlewareExecution).to.deep.equal(['A', 'B'])
108
- testDone()
109
- }
110
-
111
- this.middleware.execute(
112
- {},
113
- (_, done) => done(),
114
- middlewareFinished
115
- )
116
- })
117
-
118
- it('executes the next callback after the function returns when there is no middleware', function (testDone) {
119
- let finished = false
120
- this.middleware.execute(
121
- {},
122
- function () {
123
- expect(finished).to.be.ok
124
- testDone()
125
- },
126
- function () {}
127
- )
128
- finished = true
129
- })
130
-
131
- it('always executes middleware after the function returns', function (testDone) {
132
- let finished = false
133
-
134
- this.middleware.register(function (context, next, done) {
135
- expect(finished).to.be.ok
136
- testDone()
137
- })
138
-
139
- this.middleware.execute({}, function () {}, function () {})
140
- finished = true
141
- })
142
-
143
- it('creates a default "done" function', function (testDone) {
144
- let finished = false
145
-
146
- this.middleware.register(function (context, next, done) {
147
- expect(finished).to.be.ok
148
- testDone()
149
- })
150
-
151
- // we're testing the lack of a third argument here.
152
- this.middleware.execute({}, function () {})
153
- finished = true
154
- })
155
-
156
- it('does the right thing with done callbacks', function (testDone) {
157
- // we want to ensure that the 'done' callbacks are nested correctly
158
- // (executed in reverse order of definition)
159
- const execution = []
160
-
161
- const testMiddlewareA = function (context, next, done) {
162
- execution.push('middlewareA')
163
- next(function () {
164
- execution.push('doneA')
165
- done()
166
- })
167
- }
168
-
169
- const testMiddlewareB = function (context, next, done) {
170
- execution.push('middlewareB')
171
- next(function () {
172
- execution.push('doneB')
173
- done()
174
- })
175
- }
176
-
177
- this.middleware.register(testMiddlewareA)
178
- this.middleware.register(testMiddlewareB)
179
-
180
- const allDone = function () {
181
- expect(execution).to.deep.equal(['middlewareA', 'middlewareB', 'doneB', 'doneA'])
182
- testDone()
183
- }
184
-
185
- this.middleware.execute(
186
- {},
187
- // Short circuit at the bottom of the middleware stack
188
- (_, done) => done(),
189
- allDone
190
- )
191
- })
192
-
193
- it('defaults to the latest done callback if none is provided', function (testDone) {
194
- // we want to ensure that the 'done' callbacks are nested correctly
195
- // (executed in reverse order of definition)
196
- const execution = []
197
-
198
- const testMiddlewareA = function (context, next, done) {
199
- execution.push('middlewareA')
200
- next(function () {
201
- execution.push('doneA')
202
- done()
203
- })
204
- }
205
-
206
- const testMiddlewareB = function (context, next, done) {
207
- execution.push('middlewareB')
208
- next()
209
- }
210
-
211
- this.middleware.register(testMiddlewareA)
212
- this.middleware.register(testMiddlewareB)
213
-
214
- const allDone = function () {
215
- expect(execution).to.deep.equal(['middlewareA', 'middlewareB', 'doneA'])
216
- testDone()
217
- }
218
-
219
- this.middleware.execute(
220
- {},
221
- // Short circuit at the bottom of the middleware stack
222
- (_, done) => done(),
223
- allDone
224
- )
225
- })
226
-
227
- describe('error handling', function () {
228
- it('does not execute subsequent middleware after the error is thrown', function (testDone) {
229
- const middlewareExecution = []
230
-
231
- const testMiddlewareA = function (context, next, done) {
232
- middlewareExecution.push('A')
233
- next(done)
234
- }
235
-
236
- const testMiddlewareB = function (context, next, done) {
237
- middlewareExecution.push('B')
238
- throw new Error()
239
- }
240
-
241
- const testMiddlewareC = function (context, next, done) {
242
- middlewareExecution.push('C')
243
- next(done)
244
- }
245
-
246
- this.middleware.register(testMiddlewareA)
247
- this.middleware.register(testMiddlewareB)
248
- this.middleware.register(testMiddlewareC)
249
-
250
- const middlewareFinished = sinon.spy()
251
- const middlewareFailed = () => {
252
- expect(middlewareFinished).to.not.have.been.called
253
- expect(middlewareExecution).to.deep.equal(['A', 'B'])
254
- testDone()
255
- }
256
-
257
- this.middleware.execute(
258
- {},
259
- middlewareFinished,
260
- middlewareFailed
261
- )
262
- })
263
-
264
- it('emits an error event', function (testDone) {
265
- const testResponse = {}
266
- const theError = new Error()
267
-
268
- const testMiddleware = function (context, next, done) {
269
- throw theError
270
- }
271
-
272
- this.middleware.register(testMiddleware)
273
-
274
- this.robot.emit = sinon.spy(function (name, err, response) {
275
- expect(name).to.equal('error')
276
- expect(err).to.equal(theError)
277
- expect(response).to.equal(testResponse)
278
- })
279
-
280
- const middlewareFinished = sinon.spy()
281
- const middlewareFailed = () => {
282
- expect(this.robot.emit).to.have.been.called
283
- testDone()
284
- }
285
-
286
- this.middleware.execute(
287
- { response: testResponse },
288
- middlewareFinished,
289
- middlewareFailed
290
- )
291
- })
292
-
293
- it('unwinds the middleware stack (calling all done functions)', function (testDone) {
294
- let extraDoneFunc = null
295
-
296
- const testMiddlewareA = function (context, next, done) {
297
- // Goal: make sure that the middleware stack is unwound correctly
298
- extraDoneFunc = sinon.spy(done)
299
- next(extraDoneFunc)
300
- }
301
-
302
- const testMiddlewareB = function (context, next, done) {
303
- throw new Error()
304
- }
305
-
306
- this.middleware.register(testMiddlewareA)
307
- this.middleware.register(testMiddlewareB)
308
-
309
- const middlewareFinished = sinon.spy()
310
- const middlewareFailed = function () {
311
- // Sanity check that the error was actually thrown
312
- expect(middlewareFinished).to.not.have.been.called
313
-
314
- expect(extraDoneFunc).to.have.been.called
315
- testDone()
316
- }
317
-
318
- this.middleware.execute(
319
- {},
320
- middlewareFinished,
321
- middlewareFailed
322
- )
323
- })
324
- })
325
- })
326
-
327
- describe('#register', function () {
328
- it('adds to the list of middleware', function () {
329
- const testMiddleware = function (context, next, done) {}
330
-
331
- this.middleware.register(testMiddleware)
332
-
333
- expect(this.middleware.stack).to.include(testMiddleware)
334
- })
335
-
336
- it('validates the arity of middleware', function () {
337
- const testMiddleware = function (context, next, done, extra) {}
338
-
339
- expect(() => this.middleware.register(testMiddleware)).to.throw(/Incorrect number of arguments/)
340
- })
341
- })
342
- })
343
-
344
- // Per the documentation in docs/scripting.md
345
- // Any new fields that are exposed to middleware should be explicitly
346
- // tested for.
347
- describe('Public Middleware APIs', function () {
348
- beforeEach(async function () {
349
- mockery.enable({
350
- warnOnReplace: false,
351
- warnOnUnregistered: false
352
- })
353
- mockery.registerMock('hubot-mock-adapter', require('./fixtures/mock-adapter.js'))
354
- process.env.EXPRESS_PORT = 0
355
- this.robot = new Robot('mock-adapter', true, 'TestHubot')
356
- await this.robot.loadAdapter()
357
- this.robot.run
358
-
359
- // Re-throw AssertionErrors for clearer test failures
360
- this.robot.on('error', function (name, err, response) {
361
- if (__guard__(err != null ? err.constructor : undefined, x => x.name) === 'AssertionError') {
362
- process.nextTick(function () {
363
- throw err
364
- })
365
- }
366
- })
367
-
368
- this.user = this.robot.brain.userForId('1', {
369
- name: 'hubottester',
370
- room: '#mocha'
371
- })
372
-
373
- // Dummy middleware
374
- this.middleware = sinon.spy((context, next, done) => next(done))
375
-
376
- this.testMessage = new TextMessage(this.user, 'message123')
377
- this.robot.hear(/^message123$/, function (response) {})
378
- this.testListener = this.robot.listeners[0]
379
- })
380
-
381
- afterEach(function () {
382
- mockery.disable()
383
- this.robot.shutdown()
384
- })
385
-
386
- describe('listener middleware context', function () {
387
- beforeEach(function () {
388
- this.robot.listenerMiddleware((context, next, done) => {
389
- this.middleware(context, next, done)
390
- })
391
- })
392
-
393
- describe('listener', function () {
394
- it('is the listener object that matched', function (testDone) {
395
- this.robot.receive(this.testMessage, () => {
396
- expect(this.middleware).to.have.been.calledWithMatch(
397
- sinon.match.has('listener',
398
- sinon.match.same(this.testListener)), // context
399
- sinon.match.any, // next
400
- sinon.match.any // done
401
- )
402
- testDone()
403
- })
404
- })
405
-
406
- it('has options.id (metadata)', function (testDone) {
407
- this.robot.receive(this.testMessage, () => {
408
- expect(this.middleware).to.have.been.calledWithMatch(
409
- sinon.match.has('listener',
410
- sinon.match.has('options',
411
- sinon.match.has('id'))), // context
412
- sinon.match.any, // next
413
- sinon.match.any // done
414
- )
415
- testDone()
416
- })
417
- })
418
- })
419
-
420
- describe('response', () =>
421
- it('is a Response that wraps the message', function (testDone) {
422
- this.robot.receive(this.testMessage, () => {
423
- expect(this.middleware).to.have.been.calledWithMatch(
424
- sinon.match.has('response',
425
- sinon.match.instanceOf(Response).and(
426
- sinon.match.has('message',
427
- sinon.match.same(this.testMessage)))), // context
428
- sinon.match.any, // next
429
- sinon.match.any // done
430
- )
431
- testDone()
432
- })
433
- })
434
- )
435
- })
436
-
437
- describe('receive middleware context', function () {
438
- beforeEach(function () {
439
- this.robot.receiveMiddleware((context, next, done) => {
440
- this.middleware(context, next, done)
441
- })
442
- })
443
-
444
- describe('response', () =>
445
- it('is a match-less Response object', function (testDone) {
446
- this.robot.receive(this.testMessage, () => {
447
- expect(this.middleware).to.have.been.calledWithMatch(
448
- sinon.match.has('response',
449
- sinon.match.instanceOf(Response).and(
450
- sinon.match.has('message',
451
- sinon.match.same(this.testMessage)))), // context
452
- sinon.match.any, // next
453
- sinon.match.any // done
454
- )
455
- testDone()
456
- })
457
- })
458
- )
459
- })
460
-
461
- describe('next', function () {
462
- beforeEach(function () {
463
- this.robot.listenerMiddleware((context, next, done) => {
464
- this.middleware(context, next, done)
465
- })
466
- })
467
-
468
- it('is a function with arity one', function (testDone) {
469
- this.robot.receive(this.testMessage, () => {
470
- expect(this.middleware).to.have.been.calledWithMatch(
471
- sinon.match.any, // context
472
- sinon.match.func.and(
473
- sinon.match.has('length',
474
- sinon.match(1))), // next
475
- sinon.match.any // done
476
- )
477
- testDone()
478
- })
479
- })
480
- })
481
-
482
- describe('done', function () {
483
- beforeEach(function () {
484
- this.robot.listenerMiddleware((context, next, done) => {
485
- this.middleware(context, next, done)
486
- })
487
- })
488
-
489
- it('is a function with arity zero', function (testDone) {
490
- this.robot.receive(this.testMessage, () => {
491
- expect(this.middleware).to.have.been.calledWithMatch(
492
- sinon.match.any, // context
493
- sinon.match.any, // next
494
- sinon.match.func.and(
495
- sinon.match.has('length',
496
- sinon.match(0))) // done
497
- )
498
- testDone()
499
- })
500
- })
501
- })
502
- })
503
- })
504
-
505
- function __guard__ (value, transform) {
506
- (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined
507
- }