boty 0.0.17 → 0.0.17.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d60d83658211dd0b17fdfeb269033ce2c73ee291
4
- data.tar.gz: 29148f8ba9a8d4dfa83d36f612c2a97959f5e5ef
3
+ metadata.gz: 0ebb5950dfa8625a01e2aca017fbd5ed259c499d
4
+ data.tar.gz: 463e6b73167a63d36ec7441c9205784bf74a5520
5
5
  SHA512:
6
- metadata.gz: 4e583ec20c26d42226cf1e52bedfebab6b184bbccca3a3ecab576fe305a0adb96ea1a6d56a1d19d0e115cb1e1c5682c81ddb15b8505956b8a6e32f2a525269b9
7
- data.tar.gz: cef240051671e266025c744489090c199c54177305da4dd0343b131076c270ad8278c1350be895e8d9b726c5af8224658cac95fc774fc3e8deb49f63cbfd0d91
6
+ metadata.gz: 5ad60851ef2067df1eaafc8a6bf9be654c2494cf1be814a33a920df05f1b702a8f818d4661d4144c5771bb5dfde15b7e6054227ece9d3208fd296b413bab6577
7
+ data.tar.gz: 9fa330463454c9be3297c034a4189d7f6663d8a5ad6bfff6b474d0f9866ab33fbc2d1bf6a541431e70771545f5ee46bd97cb4356f6111ddcde0d6d8a438976c6
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- boty (0.0.17)
4
+ boty (0.0.17.1)
5
5
  eventmachine
6
6
  faraday
7
7
  faye-websocket
data/boty.gemspec CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = "http://github.com/ricardovaleriano/boty"
15
15
  spec.license = "MIT"
16
16
 
17
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(features)/}) }
18
18
  spec.bindir = "exe"
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
data/lib/boty/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Boty
2
- VERSION = "0.0.17"
2
+ VERSION = "0.0.17.1"
3
3
  end
@@ -0,0 +1,419 @@
1
+ module Boty
2
+ RSpec.describe "happy brighty shiny path", :session do
3
+ before do
4
+ start_session
5
+ end
6
+
7
+ let(:user_id) { "U5678" }
8
+
9
+ before do
10
+ bot.hear(/jeeba/i) do
11
+ say "Ohay <@#{user.id}>! I'm here, that's for sure."
12
+ end
13
+
14
+ bot.hear(/anybody there\?/i) do
15
+ say "Me! Here."
16
+ end
17
+
18
+ bot.match(/with match/i) do
19
+ say "Ohay <@#{user.id}>! It matched."
20
+ end
21
+
22
+ bot.command(/do stuff/i) do
23
+ say "Doing some stuff"
24
+ end
25
+
26
+ bot.command(/exec command/i) do
27
+ say "Command issued."
28
+ end
29
+ end
30
+
31
+ it "responds to a message" do
32
+ expect(bot).to receive(:say).
33
+ with "Ohay <@U5678>! I'm here, that's for sure."
34
+ faye.message "jeeba, are you there?", user: "U5678"
35
+ end
36
+
37
+ it "responds to a match" do
38
+ expect(bot).to receive(:say).
39
+ with "Ohay <@U5678>! It matched."
40
+ faye.message "called with match?", user: "U5678"
41
+ end
42
+
43
+ it "does not respond to a message not binded" do
44
+ expect(bot).to_not receive(:say)
45
+ faye.message "are you there?"
46
+ end
47
+
48
+ it "understands #hear as a message binding" do
49
+ expect(bot).to receive(:say).with("Me! Here.")
50
+ faye.message "anybody there?"
51
+ end
52
+
53
+ context "Direct message" do
54
+ it "responds when mentioned by name" do
55
+ expect(bot).to receive(:say).with "Doing some stuff"
56
+ faye.message "<@jeeba>: do stuff!"
57
+ end
58
+
59
+ it "responds when mentioned by id" do
60
+ expect(bot).to receive(:say).with "Doing some stuff"
61
+ faye.message "<@U1234>: do stuff!"
62
+ end
63
+
64
+ it "responds just once" do
65
+ expect(bot).to receive(:im).once
66
+ faye.message "<@U1234>: knows"
67
+ end
68
+
69
+ it "responds when mentioned by both name and id in the same message" do
70
+ expect(bot).to receive(:im).once
71
+ faye.message "<@U1234|jabber>: knows"
72
+ end
73
+
74
+ it "understands `#command` bindings" do
75
+ expect(bot).to receive(:say).with "Command issued."
76
+ faye.message "<@U1234>: exec command xpto"
77
+ end
78
+ end
79
+ end
80
+
81
+ RSpec.describe Bot do
82
+ subject(:bot) { described_class.new bot_info, Session.new }
83
+
84
+ let(:bot_info) {{
85
+ "id" => "666",
86
+ "name" => "jabber"
87
+ }}
88
+
89
+ describe "#on" do
90
+ it "binds an event `'type'` to a block" do
91
+ data = {
92
+ "type" => "omg",
93
+ "text" => "lol"
94
+ }
95
+
96
+ expect { |b|
97
+ bot.on :omg, &b
98
+ bot.event data
99
+ }.to yield_with_args data
100
+ end
101
+ end
102
+
103
+ describe "#off" do
104
+ let(:data) {{
105
+ "type" => "bbq",
106
+ "text" => "omg. wtf."
107
+ }}
108
+
109
+ it "unbounds an event by type AND block, just if the block is the same" do
110
+ @permanent_executed = false
111
+ permanent_block = ->(_){ @permanent_executed = true }
112
+ bot.on :bbq, &permanent_block
113
+
114
+ @ephemeral_executed = false
115
+ ephemeral_block = ->(_){ @ephemeral_executed = true }
116
+ bot.on :bbq, &ephemeral_block
117
+ bot.off :bbq, &ephemeral_block
118
+
119
+ bot.event data
120
+
121
+ expect(@permanent_executed).to eq true
122
+ expect(@ephemeral_executed).to eq false
123
+ end
124
+
125
+ it "unbounds all events by type" do
126
+ @first_block = @second_block = @third_block = false
127
+ bot.on(:bbq) { |_| @first_block = true }
128
+ bot.on(:bbq) { |_| @second_block = true }
129
+ bot.on(:bbq) { |_| @third_block = true }
130
+ bot.off(:bbq)
131
+
132
+ bot.event data
133
+
134
+ expect(@first_block).to eq false
135
+ expect(@second_block).to eq false
136
+ expect(@third_block).to eq false
137
+ end
138
+ end
139
+
140
+ describe "#match", :users do
141
+ let(:data) { {"type" => "message", "text" => "bbq omg lol"} }
142
+
143
+ it "binds a regex to events of `type => message`" do
144
+ _message = nil
145
+ bot.match(/omg/i) do
146
+ _message = message
147
+ end
148
+ bot.event data
149
+
150
+ expect(_message).to be_a Message
151
+ expect(_message.text).to eq "bbq omg lol"
152
+ expect(_message.match[0]).to eq "omg"
153
+ end
154
+
155
+ it "binds various actions to events of type message" do
156
+ iterations = []
157
+ bot.match(/omg/i) do iterations << "first" end
158
+ bot.match(/omg/i) do iterations << "second" end
159
+ bot.event data
160
+
161
+ expect(iterations).to eq ["first", "second"]
162
+ end
163
+
164
+ it "passes the matched strings as parameters to block action" do
165
+ _lol, _bbq = nil
166
+ bot.match(/(bbq) omg (lol)/i) do |bbq, lol|
167
+ _lol, _bbq = lol, bbq
168
+ end
169
+ bot.event data
170
+
171
+ expect(_lol).to eq "lol"
172
+ expect(_bbq).to eq "bbq"
173
+ end
174
+ end
175
+
176
+ describe "#respond", :users do
177
+ let(:data) {{
178
+ "type" => "message",
179
+ "text" => "hey <@jabber>, omg me"
180
+ }}
181
+
182
+ it "binds actions for messages only when there is a mention (@bot)" do
183
+ expect { |b|
184
+ bot.respond(/omg me/, &b)
185
+ bot.event data
186
+ }.to yield_control
187
+ end
188
+
189
+ it "recognizes the id when it's mentioned" do
190
+ data["text"] = "hey <@666>: omg me"
191
+ expect { |b|
192
+ bot.respond(/omg me/, &b)
193
+ bot.event data
194
+ }.to yield_control
195
+ end
196
+
197
+ it "does not bind when regex matches but there is no mention" do
198
+ data["text"] = "hey <@other_bot>, omg me"
199
+
200
+ expect { |b|
201
+ bot.respond(/omg me/, &b)
202
+ bot.event data
203
+ }.to_not yield_control
204
+ end
205
+
206
+ it "ignores mentions from itself" do
207
+ data["user"] = "666"
208
+
209
+ expect { |b|
210
+ bot.respond(/omg me/, &b)
211
+ bot.event data
212
+ }.to_not yield_control
213
+ end
214
+
215
+ it "evals the block in the context of the bot" do
216
+ dsl = nil
217
+ bot.respond(/omg me/) { dsl = self }
218
+ bot.event data
219
+
220
+ expect(dsl.bot).to eq bot
221
+ end
222
+ end
223
+
224
+ context "removing binds for messages and responses", :session do
225
+ before do
226
+ start_session
227
+ end
228
+
229
+ describe "#no_message" do
230
+ let(:data) { {"type" => "message", "text" => "bbq omg lol"} }
231
+
232
+ it "removes a message based on the regex AND the block" do
233
+ permanent_executed = false
234
+ permanent_block = ->() { permanent_executed = true }
235
+ bot.hear(/omg/i, &permanent_block)
236
+
237
+ ephemeral_executed = false
238
+ ephemeral_block = ->() { ephemeral_executed = true }
239
+ bot.hear(/omg/i, &ephemeral_block)
240
+ bot.no_match(/omg/i, &ephemeral_block)
241
+
242
+ dsl.bot.event data
243
+
244
+ expect(permanent_executed).to eq true
245
+ expect(ephemeral_executed).to eq false
246
+ end
247
+
248
+ it "removes all binds for a specific regex" do
249
+ first = second = false
250
+ bot.hear(/omg/i) { first = true }
251
+ bot.hear(/omg/i) { second = true }
252
+ bot.no_match(/omg/i)
253
+
254
+ dsl.bot.event data
255
+
256
+ expect(first).to eq false
257
+ expect(second).to eq false
258
+ end
259
+ end
260
+
261
+ describe "#no_respond" do
262
+ let(:data) {{
263
+ "type" => "message",
264
+ "text" => "hey <@#{bot.name}>, omg me"
265
+ }}
266
+
267
+ it "removes a message based on the regex AND the block" do
268
+ permanent_executed = false
269
+ permanent_block = ->() { permanent_executed = true }
270
+ bot.respond(/omg/i, &permanent_block)
271
+
272
+ ephemeral_executed = false
273
+ ephemeral_block = ->() { ephemeral_executed = true }
274
+ bot.respond(/omg/i, &ephemeral_block)
275
+ bot.no_respond(/omg/i, &ephemeral_block)
276
+
277
+ dsl.bot.event data
278
+
279
+ expect(permanent_executed).to eq true
280
+ expect(ephemeral_executed).to eq false
281
+ end
282
+
283
+ it "removes all binds for a specific regex" do
284
+ first = second = false
285
+ bot.respond(/omg/i) { first = true }
286
+ bot.respond(/omg/i) { second = true }
287
+ bot.no_respond(/omg/i)
288
+
289
+ dsl.bot.event data
290
+
291
+ expect(first).to eq false
292
+ expect(second).to eq false
293
+ end
294
+ end
295
+ end
296
+
297
+ describe "#say", :users do
298
+ let(:data) {{
299
+ "type" => "message",
300
+ "text" => "hey <@jabber>, omg me",
301
+ "channel" => "omg"
302
+ }}
303
+
304
+ it "sends a string using the slack api to general (default) channel" do
305
+ expect(Slack.chat).to receive(:post_message).
306
+ with "something", channel: "general"
307
+ bot.say "something"
308
+ end
309
+
310
+ it "send a message to the channel specified by a current binded message" do
311
+ expect(Slack.chat).to receive(:post_message).
312
+ with "omg pugs!", channel: "omg"
313
+
314
+ bot.respond(/omg me/) { say "omg pugs!" }
315
+ bot.event data
316
+ end
317
+ end
318
+
319
+ describe "#im", :session, :users do
320
+ before do
321
+ start_session
322
+ end
323
+
324
+ let(:user_id) { "U4321" }
325
+ let(:data) {{
326
+ "type" => "message",
327
+ "text" => "<@#{bot.name}>: omg",
328
+ "user" => "U4321"
329
+ }}
330
+
331
+ it "sends a message in the back channel (particular, im...)" do
332
+ bot.respond(/omg/) { im "lol" }
333
+ expect(Boty::Slack.chat).to receive(:post_im).with "U4321", "lol"
334
+
335
+ dsl.bot.event data
336
+ end
337
+ end
338
+
339
+ describe "#brain", :users do
340
+ it "exposes a hash that lives while bot is alive. =)" do
341
+ bot.brain[:something] = "going on"
342
+ expect(bot.brain[:something]).to eq "going on"
343
+ end
344
+ end
345
+
346
+ context "loading script/**/*.rb files", :fakefs, :users do
347
+ let(:data) {{
348
+ "type" => "message",
349
+ "text" => "hey <@jabber>, pug me"
350
+ }}
351
+
352
+ before do
353
+ FileUtils.mkdir "script" unless Dir.exists? "script"
354
+ File.open "script/omg.rb", "w" do |f|
355
+ f.write <<-RUBY
356
+ respond(/pug me/i) do
357
+ say "omg"
358
+ end
359
+ RUBY
360
+ end
361
+ end
362
+
363
+ it "uses the logic in the script located at script/omg.rb" do
364
+ expect(bot).to receive(:say).with "omg"
365
+ bot.event data
366
+ end
367
+
368
+ context "describing commands", :fakefs, :users do
369
+ before do
370
+ File.open "script/omg.rb", "w" do |f|
371
+ f.write <<-RUBY
372
+ desc "pug me", "show some pretty random pug"
373
+ respond(/pug me/i) do
374
+ say "omg"
375
+ end
376
+
377
+ desc "just a description"
378
+ respond(/just desc/i) do
379
+ say "just description, raw command"
380
+ end
381
+
382
+ respond(/without desc/i) do
383
+ say "no desc, raw command"
384
+ end
385
+
386
+ respond(/without desc sensitive/) do
387
+ say "no desc, raw command"
388
+ end
389
+ RUBY
390
+ end
391
+ end
392
+
393
+ it "stores the description within command usage" do
394
+ expect(bot.know_how).to include({
395
+ "pug me" => "show some pretty random pug"
396
+ })
397
+ end
398
+
399
+ it "stores the description for a regex when no command usage is given" do
400
+ expect(bot.know_how).to include({
401
+ "/just desc/i" => "just a description"
402
+ })
403
+ end
404
+
405
+ it "presents the commands without description as regexes" do
406
+ expect(bot.know_how).to include({
407
+ "/without desc/i" => nil
408
+ })
409
+ end
410
+
411
+ it "knows when a regex is case sensitive" do
412
+ expect(bot.know_how).to include({
413
+ "/without desc sensitive/" => nil
414
+ })
415
+ end
416
+ end
417
+ end
418
+ end
419
+ end