@hubot-friends/hubot-slack 0.0.0-development

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 (72) hide show
  1. package/.github/CODE_OF_CONDUCT.md +11 -0
  2. package/.github/contributing.md +60 -0
  3. package/.github/issue_template.md +48 -0
  4. package/.github/maintainers_guide.md +91 -0
  5. package/.github/pull_request_template.md +8 -0
  6. package/.github/workflows/ci-build.yml +74 -0
  7. package/LICENSE +22 -0
  8. package/README.md +29 -0
  9. package/docs/Gemfile +2 -0
  10. package/docs/README.md +15 -0
  11. package/docs/_config.yml +29 -0
  12. package/docs/_includes/analytics.html +7 -0
  13. package/docs/_includes/head.html +33 -0
  14. package/docs/_includes/page_header.html +20 -0
  15. package/docs/_includes/side_nav.html +22 -0
  16. package/docs/_includes/tag_manager.html +13 -0
  17. package/docs/_layouts/changelog.html +15 -0
  18. package/docs/_layouts/default.html +47 -0
  19. package/docs/_layouts/page.html +10 -0
  20. package/docs/_pages/FAQ.md +63 -0
  21. package/docs/_pages/about.md +16 -0
  22. package/docs/_pages/advanced_usage.md +102 -0
  23. package/docs/_pages/auth.md +44 -0
  24. package/docs/_pages/basic_usage.md +302 -0
  25. package/docs/_pages/changelog.html +17 -0
  26. package/docs/_pages/upgrading.md +49 -0
  27. package/docs/_posts/2016-07-15-v4.0.0.md +14 -0
  28. package/docs/_posts/2016-07-19-v4.0.1.md +5 -0
  29. package/docs/_posts/2016-08-03-v4.0.2.md +4 -0
  30. package/docs/_posts/2016-09-12-v4.0.3.md +8 -0
  31. package/docs/_posts/2016-09-12-v4.0.4.md +4 -0
  32. package/docs/_posts/2016-09-14-v4.0.5.md +4 -0
  33. package/docs/_posts/2016-09-21-v4.1.0.md +4 -0
  34. package/docs/_posts/2016-10-12-v4.2.0.md +4 -0
  35. package/docs/_posts/2016-10-12-v4.2.1.md +4 -0
  36. package/docs/_posts/2016-11-05-v4.2.2.md +8 -0
  37. package/docs/_posts/2017-01-05-v4.3.0.md +5 -0
  38. package/docs/_posts/2017-01-09-v4.3.1.md +5 -0
  39. package/docs/_posts/2017-02-15-v4.3.2.md +5 -0
  40. package/docs/_posts/2017-02-17-v4.3.3.md +4 -0
  41. package/docs/_posts/2017-03-29-v4.3.4.md +5 -0
  42. package/docs/_posts/2017-08-24-v4.4.0.md +7 -0
  43. package/docs/_posts/2018-06-08-v4.5.0.md +13 -0
  44. package/docs/_posts/2018-06-14-v4.5.1.md +4 -0
  45. package/docs/_posts/2018-07-03-v4.5.2.md +5 -0
  46. package/docs/_posts/2018-07-17-v4.5.3.md +12 -0
  47. package/docs/_posts/2018-08-10-v4.5.4.md +7 -0
  48. package/docs/_posts/2018-10-01-v4.5.5.md +7 -0
  49. package/docs/_posts/2018-12-21-v4.6.0.md +6 -0
  50. package/docs/_posts/2019-04-29-v4.7.0.md +6 -0
  51. package/docs/_posts/2019-04-30-v4.7.1.md +5 -0
  52. package/docs/_posts/2020-04-03-v4.7.2.md +6 -0
  53. package/docs/_posts/2020-05-19-v4.8.0.md +10 -0
  54. package/docs/_posts/2020-10-19-v4.8.1.md +7 -0
  55. package/docs/_posts/2021-01-26-v4.9.0.md +8 -0
  56. package/docs/_posts/2022-01-12-v4.10.0.md +8 -0
  57. package/docs/index.md +93 -0
  58. package/docs/styles/docs.css +37 -0
  59. package/package.json +50 -0
  60. package/slack.js +20 -0
  61. package/src/SlackAdapter.mjs +302 -0
  62. package/src/SlackAdapter.test.mjs +342 -0
  63. package/src/bot.js +526 -0
  64. package/src/client.js +445 -0
  65. package/src/extensions.js +82 -0
  66. package/src/mention.js +15 -0
  67. package/src/message.js +307 -0
  68. package/src/testing.mjs +24 -0
  69. package/test/bot.js +769 -0
  70. package/test/client.js +446 -0
  71. package/test/message.js +329 -0
  72. package/test/stubs.js +388 -0
package/test/bot.js ADDED
@@ -0,0 +1,769 @@
1
+ const {describe, it, beforeEach, before, after} = require('node:test');
2
+ const assert = require('node:assert/strict');
3
+ const Module = require('module');
4
+
5
+ const hookModuleToReturnMockFromRequire = (module, mock) => {
6
+ const originalRequire = Module.prototype.require;
7
+ Module.prototype.require = function() {
8
+ if (arguments[0] === module) {
9
+ return mock;
10
+ }
11
+ return originalRequire.apply(this, arguments);
12
+ };
13
+ };
14
+
15
+ const hubotSlackMock = require('../slack.js');
16
+ hookModuleToReturnMockFromRequire('hubot-slack', hubotSlackMock);
17
+
18
+ const { loadBot } = require.main.require('hubot');
19
+ const { SlackTextMessage, ReactionMessage, FileSharedMessage } = require('../src/message');
20
+ const { env } = require('node:process');
21
+
22
+ describe('Adapter', function() {
23
+ let stubs, slackbot;
24
+ beforeEach(function() {
25
+ ({stubs, slackbot} = require('./stubs.js')());
26
+ });
27
+
28
+ it('Should initialize with a robot', function() {
29
+ assert.deepEqual(slackbot.robot, stubs.robot);
30
+ });
31
+
32
+ it('Should load an instance of Robot with extended methods', async function() {
33
+ process.env.HUBOT_SLACK_APP_TOKEN = 'xapp-faketoken';
34
+ process.env.HUBOT_SLACK_BOT_TOKEN = 'xoxb-faketoken';
35
+
36
+ const loadedRobot = loadBot('slack', false, 'Hubot');
37
+ await loadedRobot.loadAdapter();
38
+
39
+ assert.ok(loadedRobot.hearReaction instanceof Function);
40
+ assert.deepEqual(loadedRobot.hearReaction.length, 3);
41
+ assert.ok(loadedRobot.fileShared instanceof Function);
42
+ assert.deepEqual(loadedRobot.fileShared.length, 3);
43
+ delete process.env.HUBOT_SLACK_APP_TOKEN;
44
+ delete process.env.HUBOT_SLACK_BOT_TOKEN;
45
+ });
46
+ });
47
+
48
+ describe('Connect', () => {
49
+ let stubs, slackbot;
50
+ beforeEach(function() {
51
+ ({stubs, slackbot} = require('./stubs.js')());
52
+ });
53
+
54
+ it('Should connect successfully', (t, done) => {
55
+ slackbot.on('connected', () => {
56
+ assert.ok(true);
57
+ done();
58
+ });
59
+ slackbot.run();
60
+ })
61
+ });
62
+
63
+ describe('Authenticate', () => {
64
+ let stubs, slackbot;
65
+ beforeEach(function() {
66
+ ({stubs, slackbot} = require('./stubs.js')());
67
+ });
68
+
69
+ it('Should authenticate successfully', async () => {
70
+ const {logger} = slackbot.robot;
71
+ const start = {
72
+ self: {
73
+ id: stubs.self.id,
74
+ name: stubs.self.name
75
+ },
76
+ team: {
77
+ id: stubs.team.id,
78
+ name: stubs.team.name
79
+ },
80
+ users: [
81
+ stubs.self,
82
+ stubs.user
83
+ ]
84
+ };
85
+
86
+ await slackbot.authenticated(start);
87
+ assert.deepEqual(slackbot.self.id, stubs.self.id);
88
+ assert.deepEqual(slackbot.robot.name, stubs.self.name);
89
+ assert.ok(logger.logs["info"].length > 0)
90
+ });
91
+ });
92
+
93
+ describe('Logger', function() {
94
+ let stubs, slackbot;
95
+ beforeEach(function() {
96
+ ({stubs, slackbot} = require('./stubs.js')());
97
+ });
98
+
99
+ it('It should log invalid botToken error', (t, done) => {
100
+ const {logger} = slackbot.robot;
101
+ logger.error = message => {
102
+ assert.deepEqual(message, 'Invalid botToken provided, please follow the upgrade instructions');
103
+ done();
104
+ }
105
+ slackbot.options.appToken = "xapp-faketoken";
106
+ slackbot.options.botToken = "ABC123";
107
+ slackbot.run();
108
+ });
109
+
110
+ it('It should log invalid appToken error', (t, done) => {
111
+ const {logger} = slackbot.robot;
112
+ logger.error = message => {
113
+ assert.deepEqual(message, 'Invalid appToken provided, please follow the upgrade instructions');
114
+ done();
115
+ }
116
+ slackbot.options.appToken = "ABC123";
117
+ slackbot.options.botToken = "xoxb-faketoken";
118
+ slackbot.run();
119
+ });
120
+ });
121
+
122
+ describe('Disable Sync', function() {
123
+ let slackbot;
124
+ beforeEach(function() {
125
+ ({stubs, slackbot} = require('./stubs.js')());
126
+ });
127
+
128
+ it('Should sync users by default', function() {
129
+ slackbot.run();
130
+ assert.deepEqual(Object.keys(slackbot.robot.brain.data.users), ['1','2','3','4']);
131
+ });
132
+
133
+ it('Should not sync users when disabled', function() {
134
+ slackbot.options.disableUserSync = true;
135
+ slackbot.run();
136
+ assert.deepEqual(Object.keys(slackbot.robot.brain.data.users).length, 0);
137
+ });
138
+ });
139
+
140
+ describe('Send Messages', function() {
141
+ let stubs, slackbot;
142
+ beforeEach(function() {
143
+ ({stubs, slackbot} = require('./stubs.js')());
144
+ });
145
+
146
+ it('Should send a message', function() {
147
+ slackbot.client.send = (envelope, message) => {
148
+ stubs._sendCount++;
149
+ stubs._msg = message;
150
+ };
151
+ slackbot.send({room: stubs.channel.id}, 'message');
152
+ assert.deepEqual(stubs._sendCount, 1);
153
+ assert.deepEqual(stubs._msg, 'message');
154
+ });
155
+
156
+ it('Should send multiple messages', function() {
157
+ slackbot.client.send = (envelope, message) => {
158
+ stubs._sendCount++;
159
+ };
160
+
161
+ slackbot.send({room: stubs.channel.id}, 'one', 'two', 'three');
162
+ assert.deepEqual(stubs._sendCount, 3);
163
+ });
164
+
165
+ it('Should not send empty messages', function() {
166
+ slackbot.client.send = (envelope, message) => {
167
+ stubs._sendCount++;
168
+ };
169
+ slackbot.send({room: stubs.channel.id}, 'Hello', '', '', 'world!');
170
+ assert.deepEqual(stubs._sendCount, 2);
171
+ });
172
+
173
+ it('Should not fail for inexistant user', function() {
174
+ assert.doesNotThrow(() => slackbot.send({room: 'U987'}, 'Hello'));
175
+ });
176
+
177
+ it('Should open a DM channel if needed', function() {
178
+ const msg = 'Test';
179
+ slackbot.client.send = (envelope, message) => {
180
+ stubs._dmmsg = message;
181
+ };
182
+ slackbot.send({room: stubs.user.id}, msg);
183
+ assert.deepEqual(stubs._dmmsg, msg);
184
+ });
185
+
186
+ it('Should send a message to a user', function() {
187
+ slackbot.client.send = (envelope, message) => {
188
+ stubs._dmmsg = message;
189
+ stubs._room = envelope.room;
190
+ };
191
+ slackbot.send({room: stubs.user.id}, 'message');
192
+ assert.deepEqual(stubs._dmmsg, 'message');
193
+ assert.deepEqual(stubs._room, stubs.user.id);
194
+ });
195
+
196
+ it('Should send a message with a callback', function(t, done) {
197
+ slackbot.client.send = (envelope, message) => {
198
+ stubs._msg = message;
199
+ stubs._sendCount++;
200
+ };
201
+ slackbot.send({room: stubs.channel.id}, 'message with a callback', function() {
202
+ assert.ok(true);
203
+ done();
204
+ });
205
+ assert.deepEqual(stubs._sendCount, 1);
206
+ assert.deepEqual(stubs._msg, 'message with a callback');
207
+ });
208
+ });
209
+
210
+ describe('Client sending message', function() {
211
+ let stubs, client;
212
+ beforeEach(function() {
213
+ ({stubs, client} = require('./stubs.js')());
214
+ });
215
+
216
+ it('Should append as_user = true', function() {
217
+ client.send({room: stubs.channel.id}, {text: 'foo', user: stubs.user, channel: stubs.channel.id});
218
+ assert.ok(stubs._opts.as_user);
219
+ });
220
+
221
+ it('Should append as_user = true only as a default', function() {
222
+ client.send({room: stubs.channel.id}, {text: 'foo', user: stubs.user, channel: stubs.channel.id, as_user: false});
223
+ assert.deepEqual(stubs._opts.as_user, true);
224
+ });
225
+ });
226
+
227
+ describe('Reply to Messages', function() {
228
+ let stubs, slackbot;
229
+ beforeEach(function() {
230
+ ({stubs, slackbot} = require('./stubs.js')());
231
+ });
232
+
233
+ it('Should mention the user in a reply sent in a channel', function() {
234
+ slackbot.client.send = (envelope, message) => {
235
+ stubs._sendCount++;
236
+ stubs._msg = message;
237
+ };
238
+ slackbot.reply({user: stubs.user, room: stubs.channel.id}, 'message');
239
+ assert.deepEqual(stubs._sendCount, 1);
240
+ assert.deepEqual(stubs._msg, `<@${stubs.user.id}>: message`);
241
+ });
242
+
243
+ it('Should mention the user in multiple replies sent in a channel', function() {
244
+ slackbot.client.send = (envelope, message) => {
245
+ stubs._sendCount++;
246
+ stubs._msg = message;
247
+ };
248
+ slackbot.reply({user: stubs.user, room: stubs.channel.id}, 'one', 'two', 'three');
249
+ assert.deepEqual(stubs._sendCount, 3);
250
+ assert.deepEqual(stubs._msg, `<@${stubs.user.id}>: three`);
251
+ });
252
+
253
+ it('Should send nothing if messages are empty', function() {
254
+ slackbot.client.send = (envelope, message) => {
255
+ stubs._sendCount++;
256
+ stubs._msg = message;
257
+ };
258
+ slackbot.reply({user: stubs.user, room: stubs.channel.id}, '');
259
+ assert.deepEqual(stubs._sendCount, 0);
260
+ });
261
+
262
+ it('Should NOT mention the user in a reply sent in a DM', function() {
263
+ slackbot.client.send = (envelope, message) => {
264
+ stubs._sendCount++;
265
+ stubs._dmmsg = message;
266
+ };
267
+ slackbot.reply({user: stubs.user, room: stubs.DM.id }, 'message');
268
+ assert.deepEqual(stubs._sendCount, 1);
269
+ assert.deepEqual(stubs._dmmsg, 'message');
270
+ });
271
+
272
+ it('Should call the callback', function(t, done) {
273
+ slackbot.client.send = (envelope, message) => {
274
+ stubs._sendCount++;
275
+ stubs._msg = message;
276
+ };
277
+ slackbot.reply({user: stubs.user, room: stubs.channel.id}, 'message', function() {
278
+ assert.ok(true);
279
+ done();
280
+ });
281
+ assert.deepEqual(stubs._sendCount, 1);
282
+ assert.deepEqual(stubs._msg, `<@${stubs.user.id}>: message`);
283
+ });
284
+ });
285
+
286
+ describe('Setting the channel topic', function() {
287
+ let stubs, slackbot;
288
+ beforeEach(function() {
289
+ ({stubs, slackbot} = require('./stubs.js')());
290
+ });
291
+
292
+ it('Should set the topic in channels', function(t, done) {
293
+ stubs.receiveMock.onTopic = function(topic) {
294
+ assert.deepEqual(topic, 'channel');
295
+ done();
296
+ };
297
+ slackbot.setTopic({room: stubs.channel.id}, 'channel');
298
+ });
299
+
300
+ it('Should NOT set the topic in DMs', function() {
301
+ slackbot.setTopic({room: 'D1232'}, 'DM');
302
+ assert.equal(stubs._topic, undefined);
303
+ });
304
+ });
305
+
306
+ describe('Receiving an error event', function() {
307
+ let slackbot;
308
+ beforeEach(function() {
309
+ ({slackbot} = require('./stubs.js')());
310
+ });
311
+ it('Should propagate that error', function() {
312
+ hit = false;
313
+ slackbot.robot.on('error', error => {
314
+ assert.deepEqual(error.msg, 'ohno');
315
+ hit = true;
316
+ });
317
+ assert.ok(!hit);
318
+ slackbot.error({msg: 'ohno', code: -2});
319
+ assert.ok(hit);
320
+ });
321
+
322
+ it('Should handle rate limit errors', function() {
323
+ const {logger} = slackbot.robot;
324
+ slackbot.error({msg: 'ratelimit', code: -1});
325
+ assert.ok(logger.logs["error"].length > 0);
326
+ });
327
+ });
328
+
329
+ describe('Handling incoming messages', function() {
330
+ let stubs, slackbot;
331
+ beforeEach(function() {
332
+ ({stubs, slackbot} = require('./stubs.js')());
333
+ });
334
+
335
+ it('Should handle regular messages as hoped and dreamed', function(t, done) {
336
+ stubs.receiveMock.onReceived = function(msg) {
337
+ assert.deepEqual(msg.text, 'foo');
338
+ done();
339
+ };
340
+ slackbot.eventHandler({body: { event: { text: 'foo', type: 'message', user: stubs.user.id }}, event: { text: 'foo', type: 'message', user: stubs.user.id, channel: stubs.channel.id }});
341
+ });
342
+
343
+ it('Should prepend our name to a name-lacking message addressed to us in a DM', function(t, done) {
344
+ const bot_name = slackbot.robot.name;
345
+ stubs.receiveMock.onReceived = function(msg) {
346
+ assert.deepEqual(msg.text, `@${bot_name} foo`);
347
+ done();
348
+ };
349
+ slackbot.eventHandler({body: { event: { text: 'foo', type: 'message', user: stubs.user.id, channel_type: 'im' }}, event: { text: 'foo', type: 'message', user: stubs.user.id, channel_type: 'im', channel:stubs.DM.id }});
350
+ });
351
+
352
+ it('Should NOT prepend our name to a name-containing message addressed to us in a DM', function(t, done) {
353
+ const bot_name = slackbot.robot.name;
354
+ stubs.receiveMock.onReceived = function(msg) {
355
+ assert.deepEqual(msg.text, `@${bot_name} foo`);
356
+ done();
357
+ };
358
+ slackbot.eventHandler({body: { event: { text: `@${bot_name} foo`, type: 'message', user: stubs.user.id }}, event: { text: 'foo', type: 'message', user: stubs.user.id, channel:stubs.DM.id }});
359
+ });
360
+
361
+ it('Should return a message object with raw text and message', function(t, done) {
362
+ //the shape of this data is an RTM message event passed through SlackClient#messageWrapper
363
+ //see: https://api.slack.com/events/message
364
+ const messageData = {
365
+ body: {
366
+ event: {
367
+ type: 'message',
368
+ text: 'foo <http://www.example.com> bar',
369
+ user: stubs.user.id,
370
+ channel: stubs.channel.id,
371
+ }
372
+ },
373
+ event: {
374
+ type: 'message',
375
+ text: 'foo <http://www.example.com> bar',
376
+ user: stubs.user.id,
377
+ channel: stubs.channel.id,
378
+ }
379
+ };
380
+ stubs.receiveMock.onReceived = function(msg) {
381
+ assert.deepEqual((msg instanceof SlackTextMessage), true);
382
+ assert.deepEqual(msg.text, "foo http://www.example.com bar");
383
+ assert.deepEqual(msg.rawText, "foo <http://www.example.com> bar");
384
+ assert.deepEqual(msg.rawMessage, messageData.event);
385
+ done();
386
+ };
387
+ slackbot.eventHandler(messageData);
388
+ });
389
+
390
+ it('Should handle member_joined_channel events as envisioned', function() {
391
+ stubs.receiveMock.onReceived = function(msg) {
392
+ assert.deepEqual(msg.constructor.name, "EnterMessage");
393
+ assert.deepEqual(msg.ts, stubs.event_timestamp);
394
+ assert.deepEqual(msg.user.id, stubs.user.id);
395
+ done();
396
+ };
397
+ slackbot.eventHandler({
398
+ body: {
399
+ event: {
400
+ type: 'member_joined_channel',
401
+ user: stubs.user.id,
402
+ channel: stubs.channel.id,
403
+ ts: stubs.event_timestamp
404
+ }
405
+ },
406
+ event: {
407
+ type: 'member_joined_channel',
408
+ user: stubs.user.id,
409
+ channel: stubs.channel.id,
410
+ ts: stubs.event_timestamp
411
+ }
412
+ });
413
+ });
414
+
415
+ it('Should handle member_left_channel events as envisioned', function() {
416
+ stubs.receiveMock.onReceived = function(msg) {
417
+ assert.deepEqual(msg.constructor.name, "LeaveMessage");
418
+ assert.deepEqual(msg.ts, stubs.event_timestamp);
419
+ assert.deepEqual(msg.user.id, stubs.user.id);
420
+ done();
421
+ };
422
+ slackbot.eventHandler({
423
+ body: {
424
+ event: {
425
+ type: 'member_left_channel',
426
+ user: stubs.user.id,
427
+ channel: stubs.channel.id,
428
+ ts: stubs.event_timestamp
429
+ }
430
+ },
431
+ event: {
432
+ type: 'member_left_channel',
433
+ user: stubs.user.id,
434
+ channel: stubs.channel.id,
435
+ ts: stubs.event_timestamp
436
+ }
437
+ });
438
+ });
439
+
440
+ it('Should handle reaction_added events as envisioned', (t, done) => {
441
+ const reactionMessage = {
442
+ body: {
443
+ event: {
444
+ type: 'reaction_added',
445
+ user: stubs.user.id,
446
+ item_user: stubs.self,
447
+ channel: stubs.channel.id,
448
+ ts: stubs.event_timestamp,
449
+ item: {
450
+ type: 'message',
451
+ channel: stubs.channel.id,
452
+ ts: '1360782804.083113'
453
+ },
454
+ reaction: 'thumbsup',
455
+ event_ts: '1360782804.083113'
456
+
457
+ }
458
+ },
459
+ event: {
460
+ type: 'reaction_added',
461
+ user: stubs.user.id,
462
+ item_user: stubs.self,
463
+ channel: stubs.channel.id,
464
+ ts: stubs.event_timestamp,
465
+ item: {
466
+ type: 'message',
467
+ channel: stubs.channel.id,
468
+ ts: '1360782804.083113'
469
+ },
470
+ reaction: 'thumbsup',
471
+ event_ts: '1360782804.083113'
472
+ }
473
+ };
474
+
475
+ stubs.receiveMock.onReceived = function(msg) {
476
+ assert.deepEqual((msg instanceof ReactionMessage), true);
477
+ assert.deepEqual(msg.user.id, stubs.user.id);
478
+ assert.deepEqual(msg.user.room, stubs.channel.id);
479
+ assert.deepEqual(msg.item_user.id, stubs.self.id);
480
+ assert.deepEqual(msg.type, 'added');
481
+ assert.deepEqual(msg.reaction, 'thumbsup');
482
+ done();
483
+ }
484
+ slackbot.eventHandler(reactionMessage);
485
+ });
486
+
487
+ it('Should handle reaction_removed events as envisioned', (t, done) => {
488
+ const reactionMessage = {
489
+ body: {
490
+ event: {
491
+ type: 'reaction_removed',
492
+ user: stubs.user.id,
493
+ item_user: stubs.self,
494
+ channel: stubs.channel.id,
495
+ ts: stubs.event_timestamp,
496
+ item: {
497
+ type: 'message',
498
+ channel: stubs.channel.id,
499
+ ts: '1360782804.083113'
500
+ },
501
+ reaction: 'thumbsup',
502
+ event_ts: '1360782804.083113'
503
+
504
+ }
505
+ },
506
+ event: {
507
+ type: 'reaction_removed',
508
+ user: stubs.user.id,
509
+ item_user: stubs.self,
510
+ channel: stubs.channel.id,
511
+ ts: stubs.event_timestamp,
512
+ item: {
513
+ type: 'message',
514
+ channel: stubs.channel.id,
515
+ ts: '1360782804.083113'
516
+ },
517
+ reaction: 'thumbsup',
518
+ event_ts: '1360782804.083113'
519
+ }
520
+ };
521
+ stubs.receiveMock.onReceived = function(msg) {
522
+ assert.deepEqual((msg instanceof ReactionMessage), true);
523
+ assert.deepEqual(msg.user.id, stubs.user.id);
524
+ assert.deepEqual(msg.user.room, stubs.channel.id);
525
+ assert.deepEqual(msg.item_user.id, stubs.self.id);
526
+ assert.deepEqual(msg.type, 'removed');
527
+ assert.deepEqual(msg.reaction, 'thumbsup');
528
+ done();
529
+ };
530
+ slackbot.eventHandler(reactionMessage);
531
+ });
532
+
533
+ it('Should ignore messages it sent itself', (t, done) => {
534
+ stubs.receiveMock.onReceived = function(msg) {
535
+ assert.fail('Should not have received a message');
536
+ };
537
+
538
+ slackbot.eventHandler({
539
+ body: {
540
+ event: {
541
+ type: 'message',
542
+ text: 'Ignore me',
543
+ user: stubs.self.id,
544
+ channel: stubs.channel.id,
545
+ ts: stubs.event_timestamp
546
+ }
547
+ },
548
+ event: {
549
+ type: 'message',
550
+ text: 'Ignore me',
551
+ user: stubs.self.id,
552
+ channel: stubs.channel.id,
553
+ ts: stubs.event_timestamp
554
+ }
555
+ });
556
+ done();
557
+ });
558
+
559
+ it('Should handle empty users as envisioned', function(t, done){
560
+ stubs.receiveMock.onReceived = function(msg) {
561
+ assert.fail('Should not have received a message');
562
+ };
563
+ slackbot.eventHandler({
564
+ body: {
565
+ event: {
566
+ type: 'message',
567
+ text: 'Foo',
568
+ user: '',
569
+ channel: stubs.channel.id,
570
+ ts: stubs.event_timestamp
571
+ }
572
+ },
573
+ event: {
574
+ type: 'message',
575
+ text: 'Foo',
576
+ user: '',
577
+ channel: stubs.channel.id,
578
+ ts: stubs.event_timestamp
579
+ }
580
+ });
581
+ done();
582
+ });
583
+
584
+ it('Should handle file_shared events as envisioned', function() {
585
+ const fileMessage = {
586
+ body: {
587
+ event: {
588
+ type: 'file_shared',
589
+ text: 'Foo',
590
+ user: stubs.user.id,
591
+ channel: stubs.channel.id,
592
+ ts: stubs.event_timestamp,
593
+ file_id: 'F2147483862',
594
+ event_ts: stubs.event_timestamp
595
+ }
596
+ },
597
+ event: {
598
+ type: 'file_shared',
599
+ text: 'Foo',
600
+ user: stubs.user.id,
601
+ channel: stubs.channel.id,
602
+ ts: stubs.event_timestamp,
603
+ file_id: 'F2147483862',
604
+ event_ts: stubs.event_timestamp
605
+ }
606
+ };
607
+ stubs.receiveMock.onReceived = function(msg) {
608
+ assert.deepEqual((msg instanceof FileSharedMessage), true);
609
+ assert.deepEqual(msg.user.id, stubs.user.id);
610
+ assert.deepEqual(msg.user.room, stubs.channel.id);
611
+ assert.deepEqual(msg.file_id, 'F2147483862');
612
+ };
613
+ slackbot.eventHandler(fileMessage);
614
+ });
615
+ });
616
+
617
+ describe('Robot.fileShared', function() {
618
+ let stubs, slackbot, fileSharedMessage;
619
+ const handleFileShared = msg => `${msg.file_id} shared`;
620
+
621
+ beforeEach(function() {
622
+ ({stubs, slackbot} = require('./stubs.js')());
623
+ const user = { id: stubs.user.id, room: stubs.channel.id };
624
+ fileSharedMessage = new FileSharedMessage(user, "F2147483862", '1360782804.083113');
625
+ });
626
+
627
+ it('Should register a Listener with callback only', function() {
628
+ slackbot.robot.fileShared(handleFileShared);
629
+ const listener = slackbot.robot.listeners.shift();
630
+ assert.ok(listener.matcher(fileSharedMessage));
631
+ assert.deepEqual(listener.options, {id: null});
632
+ assert.deepEqual(listener.callback(fileSharedMessage), 'F2147483862 shared');
633
+ });
634
+
635
+ it('Should register a Listener with opts and callback', function() {
636
+ slackbot.robot.fileShared({id: 'foobar'}, handleFileShared);
637
+ const listener = slackbot.robot.listeners.shift();
638
+ assert.ok(listener.matcher(fileSharedMessage));
639
+ assert.deepEqual(listener.options, {id: 'foobar'});
640
+ assert.deepEqual(listener.callback(fileSharedMessage), 'F2147483862 shared');
641
+ });
642
+
643
+ it('Should register a Listener with matcher and callback', function() {
644
+ const matcher = msg => msg.file_id === 'F2147483862';
645
+ slackbot.robot.fileShared(matcher, handleFileShared);
646
+ const listener = slackbot.robot.listeners.shift();
647
+ assert.ok(listener.matcher(fileSharedMessage));
648
+ assert.deepEqual(listener.options, {id: null});
649
+ assert.deepEqual(listener.callback(fileSharedMessage), 'F2147483862 shared');
650
+ });
651
+
652
+ it('Should register a Listener with matcher, opts, and callback', function() {
653
+ const matcher = msg => msg.file_id === 'F2147483862';
654
+ slackbot.robot.fileShared(matcher, {id: 'foobar'}, handleFileShared);
655
+ const listener = slackbot.robot.listeners.shift();
656
+ assert.ok(listener.matcher(fileSharedMessage));
657
+ assert.deepEqual(listener.options, {id: 'foobar'});
658
+ assert.deepEqual(listener.callback(fileSharedMessage), 'F2147483862 shared');
659
+ });
660
+
661
+ it('Should register a Listener that does not match the ReactionMessage', function() {
662
+ const matcher = msg => msg.file_id === 'J12387ALDFK';
663
+ slackbot.robot.fileShared(matcher, handleFileShared);
664
+ const listener = slackbot.robot.listeners.shift();
665
+ assert.ok(!listener.matcher(fileSharedMessage));
666
+ });
667
+ });
668
+
669
+ describe('Robot.hearReaction', function() {
670
+ let stubs, slackbot, reactionMessage;
671
+ const handleReaction = msg => `${msg.reaction} handled`;
672
+ beforeEach(function() {
673
+ ({stubs, slackbot} = require('./stubs.js')());
674
+ const user = { id: stubs.user.id, room: stubs.channel.id };
675
+ const item = {
676
+ type: 'message', channel: stubs.channel.id, ts: '1360782804.083113'
677
+ };
678
+ reactionMessage = new ReactionMessage(
679
+ 'reaction_added', user, 'thumbsup', item, '1360782804.083113'
680
+ );
681
+ });
682
+
683
+ it('Should register a Listener with callback only', function() {
684
+ slackbot.robot.hearReaction(handleReaction);
685
+ const listener = slackbot.robot.listeners.shift();
686
+ assert.ok(listener.matcher(reactionMessage));
687
+ assert.deepEqual(listener.options, {id: null});
688
+ assert.deepEqual(listener.callback(reactionMessage), 'thumbsup handled');
689
+ });
690
+
691
+ it('Should register a Listener with opts and callback', function() {
692
+ slackbot.robot.hearReaction({id: 'foobar'}, handleReaction);
693
+ const listener = slackbot.robot.listeners.shift();
694
+ assert.ok(listener.matcher(reactionMessage));
695
+ assert.deepEqual(listener.options, {id: 'foobar'});
696
+ assert.deepEqual(listener.callback(reactionMessage), 'thumbsup handled');
697
+ });
698
+
699
+ it('Should register a Listener with matcher and callback', function() {
700
+ const matcher = msg => msg.type === 'added';
701
+ slackbot.robot.hearReaction(matcher, handleReaction);
702
+ const listener = slackbot.robot.listeners.shift();
703
+ assert.ok(listener.matcher(reactionMessage));
704
+ assert.deepEqual(listener.options, {id: null});
705
+ assert.deepEqual(listener.callback(reactionMessage), 'thumbsup handled');
706
+ });
707
+
708
+ it('Should register a Listener with matcher, opts, and callback', function() {
709
+ const matcher = msg => (msg.type === 'removed') || (msg.reaction === 'thumbsup');
710
+ slackbot.robot.hearReaction(matcher, {id: 'foobar'}, handleReaction);
711
+ const listener = slackbot.robot.listeners.shift();
712
+ assert.ok(listener.matcher(reactionMessage));
713
+ assert.deepEqual(listener.options, {id: 'foobar'});
714
+ assert.deepEqual(listener.callback(reactionMessage), 'thumbsup handled');
715
+ });
716
+
717
+ it('Should register a Listener that does not match the ReactionMessage', function() {
718
+ const matcher = msg => msg.type === 'removed';
719
+ slackbot.robot.hearReaction(matcher, handleReaction);
720
+ const listener = slackbot.robot.listeners.shift();
721
+ assert.ok(!listener.matcher(reactionMessage));
722
+ });
723
+ });
724
+
725
+ describe('Users data', function() {
726
+ let stubs, slackbot;
727
+ beforeEach(function() {
728
+ ({stubs, slackbot} = require('./stubs.js')());
729
+ });
730
+ it('Should load users data from web api', function() {
731
+ slackbot.usersLoaded(null, stubs.responseUsersList);
732
+
733
+ const user = slackbot.robot.brain.data.users[stubs.user.id];
734
+ assert.deepEqual(user.id, stubs.user.id);
735
+ assert.deepEqual(user.name, stubs.user.name);
736
+ assert.deepEqual(user.real_name, stubs.user.real_name);
737
+ assert.deepEqual(user.email_address, stubs.user.profile.email);
738
+ assert.deepEqual(user.slack.misc, stubs.user.misc);
739
+
740
+ const userperiod = slackbot.robot.brain.data.users[stubs.userperiod.id];
741
+ assert.deepEqual(userperiod.id, stubs.userperiod.id);
742
+ assert.deepEqual(userperiod.name, stubs.userperiod.name);
743
+ assert.deepEqual(userperiod.real_name, stubs.userperiod.real_name);
744
+ assert.deepEqual(userperiod.email_address, stubs.userperiod.profile.email);
745
+ });
746
+
747
+ it('Should merge with user data which is stored by other program', function() {
748
+ const originalUser =
749
+ {something: 'something'};
750
+
751
+ slackbot.robot.brain.userForId(stubs.user.id, originalUser);
752
+ slackbot.usersLoaded(null, stubs.responseUsersList);
753
+
754
+ const user = slackbot.robot.brain.data.users[stubs.user.id];
755
+ assert.deepEqual(user.id, stubs.user.id);
756
+ assert.deepEqual(user.name, stubs.user.name);
757
+ assert.deepEqual(user.real_name, stubs.user.real_name);
758
+ assert.deepEqual(user.email_address, stubs.user.profile.email);
759
+ assert.deepEqual(user.slack.misc, stubs.user.misc);
760
+ assert.deepEqual(user.something, originalUser.something);
761
+ });
762
+
763
+ it('Should detect wrong response from web api', function() {
764
+ slackbot.usersLoaded(null, stubs.wrongResponseUsersList);
765
+ assert.deepEqual(slackbot.robot.brain.data.users[stubs.user.id], undefined);
766
+ });
767
+ });
768
+
769
+