1 | 'use strict'
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | const chai = require('chai')
|
8 | const sinon = require('sinon')
|
9 | chai.use(require('sinon-chai'))
|
10 |
|
11 | const expect = chai.expect
|
12 |
|
13 |
|
14 | const Brain = require('../src/brain')
|
15 | const User = require('../src/user')
|
16 |
|
17 | describe('Brain', function () {
|
18 | beforeEach(function () {
|
19 | this.clock = sinon.useFakeTimers()
|
20 | this.mockRobot = {
|
21 | emit () {},
|
22 | on () {}
|
23 | }
|
24 |
|
25 |
|
26 |
|
27 | sinon.stub(this.mockRobot, 'on').withArgs('running').callsArg(1)
|
28 |
|
29 | this.brain = new Brain(this.mockRobot)
|
30 |
|
31 | this.user1 = this.brain.userForId('1', {name: 'Guy One'})
|
32 | this.user2 = this.brain.userForId('2', {name: 'Guy One Two'})
|
33 | this.user3 = this.brain.userForId('3', {name: 'Girl Three'})
|
34 | })
|
35 |
|
36 | afterEach(function () {
|
37 | this.clock.restore()
|
38 | })
|
39 |
|
40 | describe('Unit Tests', function () {
|
41 | describe('#mergeData', function () {
|
42 | it('performs a proper merge with the new data taking precedent', function () {
|
43 | this.brain.data = {
|
44 | 1: 'old',
|
45 | 2: 'old'
|
46 | }
|
47 |
|
48 | this.brain.mergeData({2: 'new'})
|
49 |
|
50 | expect(this.brain.data).to.deep.equal({
|
51 | 1: 'old',
|
52 | 2: 'new'
|
53 | })
|
54 | })
|
55 |
|
56 | it('emits a loaded event with the new data', function () {
|
57 | sinon.spy(this.brain, 'emit')
|
58 | this.brain.mergeData({})
|
59 | expect(this.brain.emit).to.have.been.calledWith('loaded', this.brain.data)
|
60 | })
|
61 | })
|
62 |
|
63 | describe('#save', () => it('emits a save event', function () {
|
64 | sinon.spy(this.brain, 'emit')
|
65 | this.brain.save()
|
66 | expect(this.brain.emit).to.have.been.calledWith('save', this.brain.data)
|
67 | }))
|
68 |
|
69 | describe('#resetSaveInterval', () => it('updates the auto-save interval', function () {
|
70 | sinon.spy(this.brain, 'save')
|
71 |
|
72 | this.brain.resetSaveInterval(10)
|
73 |
|
74 | this.brain.setAutoSave(true)
|
75 |
|
76 | this.clock.tick(5000)
|
77 |
|
78 | expect(this.brain.save).to.not.have.been.called
|
79 | this.clock.tick(5000)
|
80 |
|
81 | expect(this.brain.save).to.have.been.calledOnce
|
82 | }))
|
83 |
|
84 | describe('#close', function () {
|
85 | it('saves', function () {
|
86 | sinon.spy(this.brain, 'save')
|
87 | this.brain.close()
|
88 | expect(this.brain.save).to.have.been.calledOnce
|
89 | })
|
90 |
|
91 | it('emits a close event', function () {
|
92 | sinon.spy(this.brain, 'emit')
|
93 | this.brain.close()
|
94 | expect(this.brain.emit).to.have.been.calledWith('close')
|
95 | })
|
96 |
|
97 | it('saves before emitting the close event', function () {
|
98 | sinon.spy(this.brain, 'save')
|
99 | sinon.spy(this.brain, 'emit').withArgs('close')
|
100 | this.brain.close()
|
101 | expect(this.brain.save).to.have.been.calledBefore(this.brain.emit)
|
102 | })
|
103 |
|
104 | it('stops auto-saving', function () {
|
105 |
|
106 | this.brain.setAutoSave(true)
|
107 | this.brain.close()
|
108 |
|
109 |
|
110 | sinon.spy(this.brain, 'save')
|
111 |
|
112 | this.clock.tick(2 * 5000)
|
113 | expect(this.brain.save).to.not.have.been.called
|
114 | })
|
115 | })
|
116 |
|
117 | describe('#get', function () {
|
118 | it('returns the saved value', function () {
|
119 | this.brain.data._private['test-key'] = 'value'
|
120 | expect(this.brain.get('test-key')).to.equal('value')
|
121 | })
|
122 |
|
123 | it('returns null if object is not found', function () {
|
124 | expect(this.brain.get('not a real key')).to.be.null
|
125 | })
|
126 | })
|
127 |
|
128 | describe('#set', function () {
|
129 | it('saves the value', function () {
|
130 | this.brain.set('test-key', 'value')
|
131 | expect(this.brain.data._private['test-key']).to.equal('value')
|
132 | })
|
133 |
|
134 | it('sets multiple keys at once if an object is provided', function () {
|
135 | this.brain.data._private = {
|
136 | key1: 'val1',
|
137 | key2: 'val1'
|
138 | }
|
139 |
|
140 | this.brain.set({
|
141 | key2: 'val2',
|
142 | key3: 'val2'
|
143 | })
|
144 |
|
145 | expect(this.brain.data._private).to.deep.equal({
|
146 | key1: 'val1',
|
147 | key2: 'val2',
|
148 | key3: 'val2'
|
149 | })
|
150 | })
|
151 |
|
152 |
|
153 |
|
154 | it('emits loaded', function () {
|
155 | sinon.spy(this.brain, 'emit')
|
156 | this.brain.set('test-key', 'value')
|
157 | expect(this.brain.emit).to.have.been.calledWith('loaded', this.brain.data)
|
158 | })
|
159 |
|
160 | it('returns the brain', function () {
|
161 | expect(this.brain.set('test-key', 'value')).to.equal(this.brain)
|
162 | })
|
163 | })
|
164 |
|
165 | describe('#remove', () => it('removes the specified key', function () {
|
166 | this.brain.data._private['test-key'] = 'value'
|
167 | this.brain.remove('test-key')
|
168 | expect(this.brain.data._private).to.not.include.keys('test-key')
|
169 | }))
|
170 |
|
171 | describe('#userForId', function () {
|
172 | it('returns the user object', function () {
|
173 | expect(this.brain.userForId(1)).to.equal(this.user1)
|
174 | })
|
175 |
|
176 | it('does an exact match', function () {
|
177 | const user4 = this.brain.userForId('FOUR')
|
178 | expect(this.brain.userForId('four')).to.not.equal(user4)
|
179 | })
|
180 |
|
181 |
|
182 |
|
183 | it('recreates the user if the room option differs from the user object', function () {
|
184 | expect(this.brain.userForId(1).room).to.be.undefined
|
185 |
|
186 |
|
187 | const newUser1 = this.brain.userForId(1, { room: 'room1' })
|
188 | expect(newUser1).to.not.equal(this.user1)
|
189 |
|
190 |
|
191 | const newUser2 = this.brain.userForId(1, { room: 'room2' })
|
192 | expect(newUser2).to.not.equal(newUser1)
|
193 | })
|
194 |
|
195 | describe('when there is no matching user ID', function () {
|
196 | it('creates a new User', function () {
|
197 | expect(this.brain.data.users).to.not.include.key('all-new-user')
|
198 | const newUser = this.brain.userForId('all-new-user')
|
199 | expect(newUser).to.be.instanceof(User)
|
200 | expect(newUser.id).to.equal('all-new-user')
|
201 | expect(this.brain.data.users).to.include.key('all-new-user')
|
202 | })
|
203 |
|
204 | it('passes the provided options to the new User', function () {
|
205 | const newUser = this.brain.userForId('all-new-user', {name: 'All New User', prop: 'mine'})
|
206 | expect(newUser.name).to.equal('All New User')
|
207 | expect(newUser.prop).to.equal('mine')
|
208 | })
|
209 | })
|
210 | })
|
211 |
|
212 | describe('#userForName', function () {
|
213 | it('returns the user with a matching name', function () {
|
214 | expect(this.brain.userForName('Guy One')).to.equal(this.user1)
|
215 | })
|
216 |
|
217 | it('does a case-insensitive match', function () {
|
218 | expect(this.brain.userForName('guy one')).to.equal(this.user1)
|
219 | })
|
220 |
|
221 | it('returns null if no user matches', function () {
|
222 | expect(this.brain.userForName('not a real user')).to.be.null
|
223 | })
|
224 | })
|
225 |
|
226 | describe('#usersForRawFuzzyName', function () {
|
227 | it('does a case-insensitive match', function () {
|
228 | expect(this.brain.usersForRawFuzzyName('guy')).to.have.members([this.user1, this.user2])
|
229 | })
|
230 |
|
231 | it('returns all matching users (prefix match) when there is not an exact match (case-insensitive)', function () {
|
232 | expect(this.brain.usersForRawFuzzyName('Guy')).to.have.members([this.user1, this.user2])
|
233 | })
|
234 |
|
235 | it('returns all matching users (prefix match) when there is an exact match (case-insensitive)', function () {
|
236 |
|
237 | expect(this.brain.usersForRawFuzzyName('Guy One')).to.deep.equal([this.user1, this.user2])
|
238 |
|
239 | expect(this.brain.usersForRawFuzzyName('guy one')).to.deep.equal([this.user1, this.user2])
|
240 | })
|
241 |
|
242 | it('returns an empty array if no users match', function () {
|
243 | const result = this.brain.usersForRawFuzzyName('not a real user')
|
244 | expect(result).to.be.an('array')
|
245 | expect(result).to.be.empty
|
246 | })
|
247 | })
|
248 |
|
249 | describe('#usersForFuzzyName', function () {
|
250 | it('does a case-insensitive match', function () {
|
251 | expect(this.brain.usersForFuzzyName('guy')).to.have.members([this.user1, this.user2])
|
252 | })
|
253 |
|
254 | it('returns all matching users (prefix match) when there is not an exact match', function () {
|
255 | expect(this.brain.usersForFuzzyName('Guy')).to.have.members([this.user1, this.user2])
|
256 | })
|
257 |
|
258 | it('returns just the user when there is an exact match (case-insensitive)', function () {
|
259 |
|
260 | expect(this.brain.usersForFuzzyName('Guy One')).to.deep.equal([this.user1])
|
261 |
|
262 | expect(this.brain.usersForFuzzyName('guy one')).to.deep.equal([this.user1])
|
263 | })
|
264 |
|
265 | it('returns an empty array if no users match', function () {
|
266 | const result = this.brain.usersForFuzzyName('not a real user')
|
267 | expect(result).to.be.an('array')
|
268 | expect(result).to.be.empty
|
269 | })
|
270 | })
|
271 | })
|
272 |
|
273 | describe('Auto-Save', function () {
|
274 | it('is on by default', function () {
|
275 | expect(this.brain.autoSave).to.equal(true)
|
276 | })
|
277 |
|
278 | it('automatically saves every 5 seconds when turned on', function () {
|
279 | sinon.spy(this.brain, 'save')
|
280 |
|
281 | this.brain.setAutoSave(true)
|
282 |
|
283 | this.clock.tick(5000)
|
284 | expect(this.brain.save).to.have.been.called
|
285 | })
|
286 |
|
287 | it('does not auto-save when turned off', function () {
|
288 | sinon.spy(this.brain, 'save')
|
289 |
|
290 | this.brain.setAutoSave(false)
|
291 |
|
292 | this.clock.tick(2 * 5000)
|
293 | expect(this.brain.save).to.not.have.been.called
|
294 | })
|
295 | })
|
296 |
|
297 | describe('User Searching', function () {
|
298 | it('finds users by ID', function () {
|
299 | expect(this.brain.userForId('1')).to.equal(this.user1)
|
300 | })
|
301 |
|
302 | it('finds users by exact name', function () {
|
303 | expect(this.brain.userForName('Guy One')).to.equal(this.user1)
|
304 | })
|
305 |
|
306 | it('finds users by fuzzy name (prefix match)', function () {
|
307 | const result = this.brain.usersForFuzzyName('Guy')
|
308 | expect(result).to.have.members([this.user1, this.user2])
|
309 | expect(result).to.not.have.members([this.user3])
|
310 | })
|
311 | })
|
312 | })
|