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.
- package/package.json +1 -1
- package/src/robot.js +0 -11
- package/.editorconfig +0 -14
- package/.github/stale.yml +0 -23
- package/.github/workflows/nodejs-macos.yml +0 -26
- package/.github/workflows/nodejs-ubuntu.yml +0 -28
- package/.github/workflows/nodejs-windows.yml +0 -26
- package/.github/workflows/release.yml +0 -37
- package/bin/e2e-test.sh +0 -47
- package/docs/adapters/campfire.md +0 -79
- package/docs/adapters/development.md +0 -125
- package/docs/adapters/shell.md +0 -24
- package/docs/adapters.md +0 -27
- package/docs/deploying/azure.md +0 -97
- package/docs/deploying/bluemix.md +0 -111
- package/docs/deploying/heroku.md +0 -66
- package/docs/deploying/unix.md +0 -72
- package/docs/deploying/windows.md +0 -66
- package/docs/deploying.md +0 -11
- package/docs/implementation.md +0 -55
- package/docs/index.md +0 -125
- package/docs/patterns.md +0 -265
- package/docs/scripting.md +0 -1051
- package/examples/hubot-start.ps1 +0 -12
- package/examples/hubot.service +0 -27
- package/script/bootstrap +0 -3
- package/script/release +0 -44
- package/script/server +0 -3
- package/script/smoke-test +0 -3
- package/script/test +0 -3
- package/test/adapter_test.js +0 -97
- package/test/brain_test.js +0 -336
- package/test/datastore_test.js +0 -154
- package/test/es2015_test.js +0 -199
- package/test/fixtures/MockAdapter.coffee +0 -10
- package/test/fixtures/MockAdapter.mjs +0 -43
- package/test/fixtures/TestScript.coffee +0 -9
- package/test/fixtures/TestScript.js +0 -13
- package/test/fixtures/mock-adapter.js +0 -35
- package/test/listener_test.js +0 -379
- package/test/message_test.js +0 -46
- package/test/middleware_test.js +0 -507
- package/test/robot_test.js +0 -1153
- package/test/shell_test.js +0 -73
- package/test/user_test.js +0 -29
package/test/es2015_test.js
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
/* global describe, it */
|
|
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
|
-
const mockery = require('mockery')
|
|
11
|
-
|
|
12
|
-
const expect = chai.expect
|
|
13
|
-
|
|
14
|
-
// Hubot classes
|
|
15
|
-
const Hubot = require('../es2015')
|
|
16
|
-
const User = Hubot.User
|
|
17
|
-
const Brain = Hubot.Brain
|
|
18
|
-
const Robot = Hubot.Robot
|
|
19
|
-
const Adapter = Hubot.Adapter
|
|
20
|
-
const Response = Hubot.Response
|
|
21
|
-
const Listener = Hubot.Listener
|
|
22
|
-
const TextListener = Hubot.TextListener
|
|
23
|
-
const Message = Hubot.Message
|
|
24
|
-
const TextMessage = Hubot.TextMessage
|
|
25
|
-
const EnterMessage = Hubot.EnterMessage
|
|
26
|
-
const LeaveMessage = Hubot.LeaveMessage
|
|
27
|
-
const TopicMessage = Hubot.TopicMessage
|
|
28
|
-
const CatchAllMessage = Hubot.CatchAllMessage
|
|
29
|
-
const loadBot = Hubot.loadBot
|
|
30
|
-
|
|
31
|
-
describe('hubot/es2015', function () {
|
|
32
|
-
it('exports User class', function () {
|
|
33
|
-
class MyUser extends User {}
|
|
34
|
-
const user = new MyUser('id123', { foo: 'bar' })
|
|
35
|
-
|
|
36
|
-
expect(user).to.be.an.instanceof(User)
|
|
37
|
-
expect(user.id).to.equal('id123')
|
|
38
|
-
expect(user.foo).to.equal('bar')
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('exports Brain class', function () {
|
|
42
|
-
class MyBrain extends Brain {}
|
|
43
|
-
const robotMock = {
|
|
44
|
-
on: sinon.spy()
|
|
45
|
-
}
|
|
46
|
-
const brain = new MyBrain(robotMock)
|
|
47
|
-
|
|
48
|
-
expect(brain).to.be.an.instanceof(Brain)
|
|
49
|
-
expect(robotMock.on).to.have.been.called
|
|
50
|
-
|
|
51
|
-
brain.set('foo', 'bar')
|
|
52
|
-
expect(brain.get('foo')).to.equal('bar')
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('exports Robot class', async function () {
|
|
56
|
-
mockery.enable({
|
|
57
|
-
warnOnReplace: false,
|
|
58
|
-
warnOnUnregistered: false
|
|
59
|
-
})
|
|
60
|
-
mockery.registerMock('hubot-mock-adapter', require('./fixtures/mock-adapter.js'))
|
|
61
|
-
|
|
62
|
-
class MyRobot extends Robot {}
|
|
63
|
-
const robot = new MyRobot('mock-adapter', false, 'TestHubot')
|
|
64
|
-
await robot.loadAdapter()
|
|
65
|
-
expect(robot).to.be.an.instanceof(Robot)
|
|
66
|
-
expect(robot.name).to.equal('TestHubot')
|
|
67
|
-
|
|
68
|
-
mockery.disable()
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it('exports Adapter class', function () {
|
|
72
|
-
class MyAdapter extends Adapter {}
|
|
73
|
-
const adapter = new MyAdapter('myrobot')
|
|
74
|
-
|
|
75
|
-
expect(adapter).to.be.an.instanceof(Adapter)
|
|
76
|
-
expect(adapter.robot).to.equal('myrobot')
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
it('exports Response class', function () {
|
|
80
|
-
class MyResponse extends Response {}
|
|
81
|
-
const robotMock = 'robotMock'
|
|
82
|
-
const messageMock = {
|
|
83
|
-
room: 'room',
|
|
84
|
-
user: 'user'
|
|
85
|
-
}
|
|
86
|
-
const matchMock = 'matchMock'
|
|
87
|
-
const response = new MyResponse(robotMock, messageMock, matchMock)
|
|
88
|
-
|
|
89
|
-
expect(response).to.be.an.instanceof(Response)
|
|
90
|
-
expect(response.message).to.equal(messageMock)
|
|
91
|
-
expect(response.match).to.equal(matchMock)
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
it('exports Listener class', function () {
|
|
95
|
-
class MyListener extends Listener {}
|
|
96
|
-
const robotMock = 'robotMock'
|
|
97
|
-
const matcherMock = 'matchMock'
|
|
98
|
-
const callback = sinon.spy()
|
|
99
|
-
const listener = new MyListener(robotMock, matcherMock, callback)
|
|
100
|
-
|
|
101
|
-
expect(listener).to.be.an.instanceof(Listener)
|
|
102
|
-
expect(listener.robot).to.equal(robotMock)
|
|
103
|
-
expect(listener.matcher).to.equal(matcherMock)
|
|
104
|
-
expect(listener.options).to.deep.include({
|
|
105
|
-
id: null
|
|
106
|
-
})
|
|
107
|
-
expect(listener.callback).to.equal(callback)
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
it('exports TextListener class', function () {
|
|
111
|
-
class MyTextListener extends TextListener {}
|
|
112
|
-
const robotMock = 'robotMock'
|
|
113
|
-
const regex = /regex/
|
|
114
|
-
const callback = sinon.spy()
|
|
115
|
-
const textListener = new MyTextListener(robotMock, regex, callback)
|
|
116
|
-
|
|
117
|
-
expect(textListener).to.be.an.instanceof(TextListener)
|
|
118
|
-
expect(textListener.regex).to.equal(regex)
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
it('exports Message class', function () {
|
|
122
|
-
class MyMessage extends Message {}
|
|
123
|
-
const userMock = {
|
|
124
|
-
room: 'room'
|
|
125
|
-
}
|
|
126
|
-
const message = new MyMessage(userMock)
|
|
127
|
-
|
|
128
|
-
expect(message).to.be.an.instanceof(Message)
|
|
129
|
-
expect(message.user).to.equal(userMock)
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
it('exports TextMessage class', function () {
|
|
133
|
-
class MyTextMessage extends TextMessage {}
|
|
134
|
-
const userMock = {
|
|
135
|
-
room: 'room'
|
|
136
|
-
}
|
|
137
|
-
const textMessage = new MyTextMessage(userMock, 'bla blah')
|
|
138
|
-
|
|
139
|
-
expect(textMessage).to.be.an.instanceof(TextMessage)
|
|
140
|
-
expect(textMessage).to.be.an.instanceof(Message)
|
|
141
|
-
expect(textMessage.text).to.equal('bla blah')
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
it('exports EnterMessage class', function () {
|
|
145
|
-
class MyEnterMessage extends EnterMessage {}
|
|
146
|
-
const userMock = {
|
|
147
|
-
room: 'room'
|
|
148
|
-
}
|
|
149
|
-
const enterMessage = new MyEnterMessage(userMock)
|
|
150
|
-
|
|
151
|
-
expect(enterMessage).to.be.an.instanceof(EnterMessage)
|
|
152
|
-
expect(enterMessage).to.be.an.instanceof(Message)
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
it('exports LeaveMessage class', function () {
|
|
156
|
-
class MyLeaveMessage extends LeaveMessage {}
|
|
157
|
-
const userMock = {
|
|
158
|
-
room: 'room'
|
|
159
|
-
}
|
|
160
|
-
const leaveMessage = new MyLeaveMessage(userMock)
|
|
161
|
-
|
|
162
|
-
expect(leaveMessage).to.be.an.instanceof(LeaveMessage)
|
|
163
|
-
expect(leaveMessage).to.be.an.instanceof(Message)
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
it('exports TopicMessage class', function () {
|
|
167
|
-
class MyTopicMessage extends TopicMessage {}
|
|
168
|
-
const userMock = {
|
|
169
|
-
room: 'room'
|
|
170
|
-
}
|
|
171
|
-
const topicMessage = new MyTopicMessage(userMock)
|
|
172
|
-
|
|
173
|
-
expect(topicMessage).to.be.an.instanceof(TopicMessage)
|
|
174
|
-
expect(topicMessage).to.be.an.instanceof(Message)
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
it('exports CatchAllMessage class', function () {
|
|
178
|
-
class MyCatchAllMessage extends CatchAllMessage {}
|
|
179
|
-
const messageMock = {
|
|
180
|
-
user: {
|
|
181
|
-
room: 'room'
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
const catchAllMessage = new MyCatchAllMessage(messageMock)
|
|
185
|
-
|
|
186
|
-
expect(catchAllMessage).to.be.an.instanceof(CatchAllMessage)
|
|
187
|
-
expect(catchAllMessage).to.be.an.instanceof(Message)
|
|
188
|
-
expect(catchAllMessage.message).to.equal(messageMock)
|
|
189
|
-
expect(catchAllMessage.user).to.equal(messageMock.user)
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
it('exports loadBot function', function () {
|
|
193
|
-
sinon.stub(Hubot, 'Robot')
|
|
194
|
-
|
|
195
|
-
expect(loadBot).to.be.a('function')
|
|
196
|
-
Hubot.loadBot(null, 'adapter', 'enableHttpd', 'botName', 'botAlias')
|
|
197
|
-
expect(Hubot.Robot).to.be.called.calledWith(null, 'adapter', 'enableHttpd', 'botName', 'botAlias')
|
|
198
|
-
})
|
|
199
|
-
})
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
import { Adapter } from '../../es2015.js' // eslint-disable-line import/no-unresolved
|
|
4
|
-
|
|
5
|
-
class MockAdapter extends Adapter {
|
|
6
|
-
constructor (robot) {
|
|
7
|
-
super(robot)
|
|
8
|
-
this.name = 'MockAdapter'
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
send (envelope, ...strings) {
|
|
12
|
-
this.emit('send', envelope, strings)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
reply (envelope, ...strings) {
|
|
16
|
-
this.emit('reply', envelope, strings)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
topic (envelope, ...strings) {
|
|
20
|
-
this.emit('topic', envelope, strings)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
play (envelope, ...strings) {
|
|
24
|
-
this.emit('play', envelope, strings)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
run () {
|
|
28
|
-
// This is required to get the scripts loaded
|
|
29
|
-
this.emit('connected')
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
close () {
|
|
33
|
-
this.emit('closed')
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
export {
|
|
37
|
-
MockAdapter
|
|
38
|
-
}
|
|
39
|
-
export default {
|
|
40
|
-
use (robot) {
|
|
41
|
-
return new MockAdapter(robot)
|
|
42
|
-
}
|
|
43
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const Adapter = require('../..').Adapter
|
|
4
|
-
|
|
5
|
-
class MockAdapter extends Adapter {
|
|
6
|
-
send (envelope/* , ...strings */) {
|
|
7
|
-
const strings = [].slice.call(arguments, 1)
|
|
8
|
-
this.emit('send', envelope, strings)
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
reply (envelope/* , ...strings */) {
|
|
12
|
-
const strings = [].slice.call(arguments, 1)
|
|
13
|
-
this.emit('reply', envelope, strings)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
topic (envelope/* , ...strings */) {
|
|
17
|
-
const strings = [].slice.call(arguments, 1)
|
|
18
|
-
this.emit('topic', envelope, strings)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
play (envelope/* , ...strings */) {
|
|
22
|
-
const strings = [].slice.call(arguments, 1)
|
|
23
|
-
this.emit('play', envelope, strings)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
run () {
|
|
27
|
-
this.emit('connected')
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
close () {
|
|
31
|
-
this.emit('closed')
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
module.exports.use = robot => new MockAdapter(robot)
|
package/test/listener_test.js
DELETED
|
@@ -1,379 +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
|
-
const sinon = require('sinon')
|
|
9
|
-
chai.use(require('sinon-chai'))
|
|
10
|
-
|
|
11
|
-
const expect = chai.expect
|
|
12
|
-
|
|
13
|
-
// Hubot classes
|
|
14
|
-
const EnterMessage = require('../src/message').EnterMessage
|
|
15
|
-
const TextMessage = require('../src/message').TextMessage
|
|
16
|
-
const Listener = require('../src/listener').Listener
|
|
17
|
-
const TextListener = require('../src/listener').TextListener
|
|
18
|
-
const Response = require('../src/response')
|
|
19
|
-
const User = require('../src/user')
|
|
20
|
-
|
|
21
|
-
describe('Listener', function () {
|
|
22
|
-
beforeEach(function () {
|
|
23
|
-
// Dummy robot
|
|
24
|
-
this.robot = {
|
|
25
|
-
// Re-throw AssertionErrors for clearer test failures
|
|
26
|
-
emit (name, err, response) {
|
|
27
|
-
if (err.constructor.name === 'AssertionError') {
|
|
28
|
-
return process.nextTick(function () {
|
|
29
|
-
throw err
|
|
30
|
-
})
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
// Ignore log messages
|
|
34
|
-
logger: {
|
|
35
|
-
debug () {}
|
|
36
|
-
},
|
|
37
|
-
// Why is this part of the Robot object??
|
|
38
|
-
Response
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Test user
|
|
42
|
-
this.user = new User({
|
|
43
|
-
id: 1,
|
|
44
|
-
name: 'hubottester',
|
|
45
|
-
room: '#mocha'
|
|
46
|
-
})
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
describe('Unit Tests', function () {
|
|
50
|
-
describe('#call', function () {
|
|
51
|
-
it('calls the matcher', function (done) {
|
|
52
|
-
const callback = sinon.spy()
|
|
53
|
-
const testMatcher = sinon.spy()
|
|
54
|
-
const testMessage = {}
|
|
55
|
-
|
|
56
|
-
const testListener = new Listener(this.robot, testMatcher, callback)
|
|
57
|
-
testListener.call(testMessage, function (_) {
|
|
58
|
-
expect(testMatcher).to.have.been.calledWith(testMessage)
|
|
59
|
-
done()
|
|
60
|
-
})
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
it('passes the matcher result on to the listener callback', function (done) {
|
|
64
|
-
const matcherResult = {}
|
|
65
|
-
const testMatcher = sinon.stub().returns(matcherResult)
|
|
66
|
-
const testMessage = {}
|
|
67
|
-
const listenerCallback = response => expect(response.match).to.be.equal(matcherResult)
|
|
68
|
-
|
|
69
|
-
// sanity check; matcherResult must be truthy
|
|
70
|
-
expect(matcherResult).to.be.ok
|
|
71
|
-
|
|
72
|
-
const testListener = new Listener(this.robot, testMatcher, listenerCallback)
|
|
73
|
-
testListener.call(testMessage, function (result) {
|
|
74
|
-
// sanity check; message should have been processed
|
|
75
|
-
expect(testMatcher).to.have.been.called
|
|
76
|
-
expect(result).to.be.ok
|
|
77
|
-
|
|
78
|
-
done()
|
|
79
|
-
})
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
describe('if the matcher returns true', function () {
|
|
83
|
-
beforeEach(function () {
|
|
84
|
-
this.createListener = function (cb) {
|
|
85
|
-
return new Listener(this.robot, sinon.stub().returns(true), cb)
|
|
86
|
-
}
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
it('executes the listener callback', function (done) {
|
|
90
|
-
const listenerCallback = sinon.spy()
|
|
91
|
-
const testMessage = {}
|
|
92
|
-
|
|
93
|
-
const testListener = this.createListener(listenerCallback)
|
|
94
|
-
testListener.call(testMessage, function (_) {
|
|
95
|
-
expect(listenerCallback).to.have.been.called
|
|
96
|
-
done()
|
|
97
|
-
})
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
it('returns true', function () {
|
|
101
|
-
const testMessage = {}
|
|
102
|
-
|
|
103
|
-
const testListener = this.createListener(function () {})
|
|
104
|
-
const result = testListener.call(testMessage)
|
|
105
|
-
expect(result).to.be.ok
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
it('calls the provided callback with true', function (done) {
|
|
109
|
-
const testMessage = {}
|
|
110
|
-
|
|
111
|
-
const testListener = this.createListener(function () {})
|
|
112
|
-
testListener.call(testMessage, function (result) {
|
|
113
|
-
expect(result).to.be.ok
|
|
114
|
-
done()
|
|
115
|
-
})
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
it('calls the provided callback after the function returns', function (done) {
|
|
119
|
-
const testMessage = {}
|
|
120
|
-
|
|
121
|
-
const testListener = this.createListener(function () {})
|
|
122
|
-
let finished = false
|
|
123
|
-
testListener.call(testMessage, function (result) {
|
|
124
|
-
expect(finished).to.be.ok
|
|
125
|
-
done()
|
|
126
|
-
})
|
|
127
|
-
finished = true
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
it('handles uncaught errors from the listener callback', function (done) {
|
|
131
|
-
const testMessage = {}
|
|
132
|
-
const theError = new Error()
|
|
133
|
-
|
|
134
|
-
const listenerCallback = function (response) {
|
|
135
|
-
throw theError
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
this.robot.emit = function (name, err, response) {
|
|
139
|
-
expect(name).to.equal('error')
|
|
140
|
-
expect(err).to.equal(theError)
|
|
141
|
-
expect(response.message).to.equal(testMessage)
|
|
142
|
-
done()
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const testListener = this.createListener(listenerCallback)
|
|
146
|
-
testListener.call(testMessage, sinon.spy())
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
it('calls the provided callback with true if there is an error thrown by the listener callback', function (done) {
|
|
150
|
-
const testMessage = {}
|
|
151
|
-
const theError = new Error()
|
|
152
|
-
|
|
153
|
-
const listenerCallback = function (response) {
|
|
154
|
-
throw theError
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const testListener = this.createListener(listenerCallback)
|
|
158
|
-
testListener.call(testMessage, function (result) {
|
|
159
|
-
expect(result).to.be.ok
|
|
160
|
-
done()
|
|
161
|
-
})
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
it('calls the listener callback with a Response that wraps the Message', function (done) {
|
|
165
|
-
const testMessage = {}
|
|
166
|
-
|
|
167
|
-
const listenerCallback = function (response) {
|
|
168
|
-
expect(response.message).to.equal(testMessage)
|
|
169
|
-
done()
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const testListener = this.createListener(listenerCallback)
|
|
173
|
-
|
|
174
|
-
testListener.call(testMessage, sinon.spy())
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
it('passes through the provided middleware stack', function (testDone) {
|
|
178
|
-
const testMessage = {}
|
|
179
|
-
|
|
180
|
-
const testListener = this.createListener(function () {})
|
|
181
|
-
const testMiddleware = {
|
|
182
|
-
execute (context, next, done) {
|
|
183
|
-
expect(context.listener).to.be.equal(testListener)
|
|
184
|
-
expect(context.response).to.be.instanceof(Response)
|
|
185
|
-
expect(context.response.message).to.be.equal(testMessage)
|
|
186
|
-
expect(next).to.be.a('function')
|
|
187
|
-
expect(done).to.be.a('function')
|
|
188
|
-
testDone()
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
testListener.call(testMessage, testMiddleware, sinon.spy())
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
it('executes the listener callback if middleware succeeds', function (testDone) {
|
|
196
|
-
const listenerCallback = sinon.spy()
|
|
197
|
-
const testMessage = {}
|
|
198
|
-
|
|
199
|
-
const testListener = this.createListener(listenerCallback)
|
|
200
|
-
|
|
201
|
-
testListener.call(testMessage, function (result) {
|
|
202
|
-
expect(listenerCallback).to.have.been.called
|
|
203
|
-
// Matcher matched, so we true
|
|
204
|
-
expect(result).to.be.ok
|
|
205
|
-
testDone()
|
|
206
|
-
})
|
|
207
|
-
})
|
|
208
|
-
|
|
209
|
-
it('does not execute the listener callback if middleware fails', function (testDone) {
|
|
210
|
-
const listenerCallback = sinon.spy()
|
|
211
|
-
const testMessage = {}
|
|
212
|
-
|
|
213
|
-
const testListener = this.createListener(listenerCallback)
|
|
214
|
-
const testMiddleware = {
|
|
215
|
-
execute (context, next, done) {
|
|
216
|
-
// Middleware fails
|
|
217
|
-
done()
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
testListener.call(testMessage, testMiddleware, function (result) {
|
|
222
|
-
expect(listenerCallback).to.not.have.been.called
|
|
223
|
-
// Matcher still matched, so we true
|
|
224
|
-
expect(result).to.be.ok
|
|
225
|
-
testDone()
|
|
226
|
-
})
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
it('unwinds the middleware stack if there is an error in the listener callback', function (testDone) {
|
|
230
|
-
const listenerCallback = sinon.stub().throws(new Error())
|
|
231
|
-
const testMessage = {}
|
|
232
|
-
let extraDoneFunc = null
|
|
233
|
-
|
|
234
|
-
const testListener = this.createListener(listenerCallback)
|
|
235
|
-
const testMiddleware = {
|
|
236
|
-
execute (context, next, done) {
|
|
237
|
-
extraDoneFunc = sinon.spy(done)
|
|
238
|
-
next(context, extraDoneFunc)
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
testListener.call(testMessage, testMiddleware, function (result) {
|
|
243
|
-
// Listener callback was called (and failed)
|
|
244
|
-
expect(listenerCallback).to.have.been.called
|
|
245
|
-
// Middleware stack was unwound correctly
|
|
246
|
-
expect(extraDoneFunc).to.have.been.called
|
|
247
|
-
// Matcher still matched, so we true
|
|
248
|
-
expect(result).to.be.ok
|
|
249
|
-
testDone()
|
|
250
|
-
})
|
|
251
|
-
})
|
|
252
|
-
})
|
|
253
|
-
|
|
254
|
-
describe('if the matcher returns false', function () {
|
|
255
|
-
beforeEach(function () {
|
|
256
|
-
this.createListener = function (cb) {
|
|
257
|
-
return new Listener(this.robot, sinon.stub().returns(false), cb)
|
|
258
|
-
}
|
|
259
|
-
})
|
|
260
|
-
|
|
261
|
-
it('does not execute the listener callback', function (done) {
|
|
262
|
-
const listenerCallback = sinon.spy()
|
|
263
|
-
const testMessage = {}
|
|
264
|
-
|
|
265
|
-
const testListener = this.createListener(listenerCallback)
|
|
266
|
-
testListener.call(testMessage, function (_) {
|
|
267
|
-
expect(listenerCallback).to.not.have.been.called
|
|
268
|
-
done()
|
|
269
|
-
})
|
|
270
|
-
})
|
|
271
|
-
|
|
272
|
-
it('returns false', function () {
|
|
273
|
-
const testMessage = {}
|
|
274
|
-
|
|
275
|
-
const testListener = this.createListener(function () {})
|
|
276
|
-
const result = testListener.call(testMessage)
|
|
277
|
-
expect(result).to.not.be.ok
|
|
278
|
-
})
|
|
279
|
-
|
|
280
|
-
it('calls the provided callback with false', function (done) {
|
|
281
|
-
const testMessage = {}
|
|
282
|
-
|
|
283
|
-
const testListener = this.createListener(function () {})
|
|
284
|
-
testListener.call(testMessage, function (result) {
|
|
285
|
-
expect(result).to.not.be.ok
|
|
286
|
-
done()
|
|
287
|
-
})
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
it('calls the provided callback after the function returns', function (done) {
|
|
291
|
-
const testMessage = {}
|
|
292
|
-
|
|
293
|
-
const testListener = this.createListener(function () {})
|
|
294
|
-
let finished = false
|
|
295
|
-
testListener.call(testMessage, function (result) {
|
|
296
|
-
expect(finished).to.be.ok
|
|
297
|
-
done()
|
|
298
|
-
})
|
|
299
|
-
finished = true
|
|
300
|
-
})
|
|
301
|
-
|
|
302
|
-
it('does not execute any middleware', function (done) {
|
|
303
|
-
const testMessage = {}
|
|
304
|
-
|
|
305
|
-
const testListener = this.createListener(function () {})
|
|
306
|
-
const testMiddleware = { execute: sinon.spy() }
|
|
307
|
-
|
|
308
|
-
testListener.call(testMessage, result => {
|
|
309
|
-
expect(testMiddleware.execute).to.not.have.been.called
|
|
310
|
-
done()
|
|
311
|
-
})
|
|
312
|
-
})
|
|
313
|
-
})
|
|
314
|
-
})
|
|
315
|
-
|
|
316
|
-
describe('#constructor', function () {
|
|
317
|
-
it('requires a matcher', () => expect(function () {
|
|
318
|
-
return new Listener(this.robot, undefined, {}, sinon.spy())
|
|
319
|
-
}).to.throw(Error))
|
|
320
|
-
|
|
321
|
-
it('requires a callback', function () {
|
|
322
|
-
// No options
|
|
323
|
-
expect(function () {
|
|
324
|
-
return new Listener(this.robot, sinon.spy())
|
|
325
|
-
}).to.throw(Error)
|
|
326
|
-
// With options
|
|
327
|
-
expect(function () {
|
|
328
|
-
return new Listener(this.robot, sinon.spy(), {})
|
|
329
|
-
}).to.throw(Error)
|
|
330
|
-
})
|
|
331
|
-
|
|
332
|
-
it('gracefully handles missing options', function () {
|
|
333
|
-
const testMatcher = sinon.spy()
|
|
334
|
-
const listenerCallback = sinon.spy()
|
|
335
|
-
const testListener = new Listener(this.robot, testMatcher, listenerCallback)
|
|
336
|
-
// slightly brittle because we are testing for the default options Object
|
|
337
|
-
expect(testListener.options).to.deep.equal({ id: null })
|
|
338
|
-
expect(testListener.callback).to.be.equal(listenerCallback)
|
|
339
|
-
})
|
|
340
|
-
|
|
341
|
-
it('gracefully handles a missing ID (set to null)', function () {
|
|
342
|
-
const testMatcher = sinon.spy()
|
|
343
|
-
const listenerCallback = sinon.spy()
|
|
344
|
-
const testListener = new Listener(this.robot, testMatcher, {}, listenerCallback)
|
|
345
|
-
expect(testListener.options.id).to.be.null
|
|
346
|
-
})
|
|
347
|
-
})
|
|
348
|
-
|
|
349
|
-
describe('TextListener', () =>
|
|
350
|
-
describe('#matcher', function () {
|
|
351
|
-
it('matches TextMessages', function () {
|
|
352
|
-
const callback = sinon.spy()
|
|
353
|
-
const testMessage = new TextMessage(this.user, 'test')
|
|
354
|
-
testMessage.match = sinon.stub().returns(true)
|
|
355
|
-
const testRegex = /test/
|
|
356
|
-
|
|
357
|
-
const testListener = new TextListener(this.robot, testRegex, callback)
|
|
358
|
-
const result = testListener.matcher(testMessage)
|
|
359
|
-
|
|
360
|
-
expect(result).to.be.ok
|
|
361
|
-
expect(testMessage.match).to.have.been.calledWith(testRegex)
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
it('does not match EnterMessages', function () {
|
|
365
|
-
const callback = sinon.spy()
|
|
366
|
-
const testMessage = new EnterMessage(this.user)
|
|
367
|
-
testMessage.match = sinon.stub().returns(true)
|
|
368
|
-
const testRegex = /test/
|
|
369
|
-
|
|
370
|
-
const testListener = new TextListener(this.robot, testRegex, callback)
|
|
371
|
-
const result = testListener.matcher(testMessage)
|
|
372
|
-
|
|
373
|
-
expect(result).to.not.be.ok
|
|
374
|
-
expect(testMessage.match).to.not.have.been.called
|
|
375
|
-
})
|
|
376
|
-
})
|
|
377
|
-
)
|
|
378
|
-
})
|
|
379
|
-
})
|