grape-slack-bot 1.0.0

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.
@@ -0,0 +1,479 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackBot::ApiClient do
4
+ subject(:client) { described_class.new(authorization_token: authorization_token) }
5
+ let(:authorization_token) { "test_authorization_token" }
6
+
7
+ it "does not raise errors" do
8
+ expect { client }.not_to raise_error
9
+ end
10
+
11
+ context "when the authorization token is not set" do
12
+ let(:authorization_token) { nil }
13
+ it "raises an error" do
14
+ expect { client }.to raise_error("Slack bot API token is not set")
15
+ end
16
+ end
17
+
18
+ describe "#users_info" do
19
+ before do
20
+ stub_request(:post, "https://slack.com/api/users.info").to_return(response)
21
+ end
22
+ subject(:users_info) { client.users_info(user_id: user_id) }
23
+ let(:user_id) { "U0R7JM" }
24
+ let(:response) {
25
+ {
26
+ status: 200,
27
+ body: {
28
+ "ok" => true,
29
+ "user" => {
30
+ "id" => "W012A3CDE",
31
+ "team_id" => "T012AB3C4",
32
+ "name" => "spengler",
33
+ "deleted" => false,
34
+ "color" => "9f69e7",
35
+ "real_name" => "Egon Spengler",
36
+ "tz" => "America/Los_Angeles",
37
+ "tz_label" => "Pacific Daylight Time",
38
+ "tz_offset" => -25200,
39
+ "profile" => {
40
+ "avatar_hash" => "ge3b51ca72de",
41
+ "status_text" => "Print is dead",
42
+ "status_emoji" => ":books:",
43
+ "real_name" => "Egon Spengler",
44
+ "display_name" => "spengler",
45
+ "real_name_normalized" => "Egon Spengler",
46
+ "display_name_normalized" => "spengler",
47
+ "email" => "spengler@ghostbusters.example.com",
48
+ "image_original" => "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg",
49
+ "image_24" => "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg",
50
+ "image_32" => "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg",
51
+ "image_48" => "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg",
52
+ "image_72" => "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg",
53
+ "image_192" => "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg",
54
+ "image_512" => "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg",
55
+ "team" => "T012AB3C4"
56
+ },
57
+ "is_admin" => true,
58
+ "is_owner" => false,
59
+ "is_primary_owner" => false,
60
+ "is_restricted" => false,
61
+ "is_ultra_restricted" => false,
62
+ "is_bot" => false,
63
+ "updated" => 1502138686,
64
+ "is_app_user" => false,
65
+ "has_2fa" => false
66
+ }
67
+ }.to_json
68
+ }
69
+ }
70
+ it "sends authorization token" do
71
+ expect(users_info.response.env.request_headers["Authorization"]).to eq("Bearer #{authorization_token}")
72
+ end
73
+ it "returns a successful response" do
74
+ expect(users_info.ok?).to eq(true)
75
+ end
76
+ context "when the response is not successful" do
77
+ let(:response) {
78
+ {
79
+ status: 200,
80
+ body: {
81
+ "ok" => false,
82
+ "error" => "user_not_found"
83
+ }.to_json
84
+ }
85
+ }
86
+ it "returns an unsuccessful response" do
87
+ expect(users_info.ok?).to eq(false)
88
+ end
89
+ end
90
+ end
91
+
92
+ describe "#views_open" do
93
+ before do
94
+ stub_request(:post, "https://slack.com/api/views.open").to_return(response)
95
+ end
96
+ subject(:views_open) {
97
+ client.views_open(
98
+ trigger_id: "trigger_id",
99
+ view: {
100
+ "type" => "modal",
101
+ "title" => {
102
+ "type" => "plain_text",
103
+ "text" => "Quite a plain modal"
104
+ },
105
+ "submit" => {
106
+ "type" => "plain_text",
107
+ "text" => "Create"
108
+ },
109
+ "blocks" => [
110
+ {
111
+ "type" => "input",
112
+ "block_id" => "a_block_id",
113
+ "label" => [
114
+ "type" => "plain_text",
115
+ "text" => "A simple label",
116
+ "emoji" => true
117
+ ],
118
+ "optional" => false,
119
+ "element" => {
120
+ "type" => "plain_text_input",
121
+ "action_id" => "an_action_id"
122
+ }
123
+ }
124
+ ],
125
+ }
126
+ )
127
+ }
128
+ let(:response) {
129
+ {
130
+ status: 200,
131
+ body: {
132
+ "ok" => true,
133
+ "view" => {
134
+ "id" => "VMHU10V25",
135
+ "team_id" => "T8N4K1JN",
136
+ "type" => "modal",
137
+ "title" => {
138
+ "type" => "plain_text",
139
+ "text" => "Quite a plain modal"
140
+ },
141
+ "submit" => {
142
+ "type" => "plain_text",
143
+ "text" => "Create"
144
+ },
145
+ "blocks" => [
146
+ {
147
+ "type" => "input",
148
+ "block_id" => "a_block_id",
149
+ "label" => {
150
+ "type" => "plain_text",
151
+ "text" => "A simple label",
152
+ "emoji" => true
153
+ },
154
+ "optional" => false,
155
+ "element" => {
156
+ "type" => "plain_text_input",
157
+ "action_id" => "an_action_id"
158
+ }
159
+ }
160
+ ],
161
+ "private_metadata" => "Shh it is a secret",
162
+ "callback_id" => "identify_your_modals",
163
+ "external_id" => "",
164
+ "state" => {
165
+ "values" => {}
166
+ },
167
+ "hash" => "156772938.1827394",
168
+ "clear_on_close" => false,
169
+ "notify_on_close" => false,
170
+ "root_view_id" => "VMHU10V25",
171
+ "app_id" => "AA4928AQ",
172
+ "bot_id" => "BA13894H"
173
+ }
174
+ }.to_json
175
+ }
176
+ }
177
+ it "returns a successful response" do
178
+ expect(views_open.ok?).to eq(true)
179
+ end
180
+
181
+ context "when the response is unsuccessful" do
182
+ let(:response) {
183
+ {
184
+ status: 200,
185
+ body: {
186
+ "ok" => false,
187
+ "error" => "invalid_arguments",
188
+ "response_metadata" => {
189
+ "messages" => [
190
+ "invalid `trigger_id`"
191
+ ]
192
+ }
193
+ }.to_json
194
+ }
195
+ }
196
+ it "returns an unsuccessful response" do
197
+ expect(views_open.ok?).to eq(false)
198
+ end
199
+ end
200
+ end
201
+
202
+ describe "#views_update" do
203
+ before do
204
+ stub_request(:post, "https://slack.com/api/views.update").to_return(response)
205
+ end
206
+ subject(:views_update) {
207
+ client.views_update(
208
+ view_id: "VMHU10V25",
209
+ view: {
210
+ "type" => "modal",
211
+ "title" => {
212
+ "type" => "plain_text",
213
+ "text" => "Quite a plain modal"
214
+ },
215
+ "submit" => {
216
+ "type" => "plain_text",
217
+ "text" => "Create"
218
+ },
219
+ "blocks" => [
220
+ {
221
+ "type" => "input",
222
+ "block_id" => "a_block_id",
223
+ "label" => [
224
+ "type" => "plain_text",
225
+ "text" => "A simple label",
226
+ "emoji" => true
227
+ ],
228
+ "optional" => false,
229
+ "element" => {
230
+ "type" => "plain_text_input",
231
+ "action_id" => "an_action_id"
232
+ }
233
+ }
234
+ ],
235
+ }
236
+ )
237
+ }
238
+ let(:response) {
239
+ {
240
+ status: 200,
241
+ body: {
242
+ "ok" => true,
243
+ "view" => {
244
+ "id" => "VMHU10V25",
245
+ "team_id" => "T8N4K1JN",
246
+ "type" => "modal",
247
+ "title" => {
248
+ "type" => "plain_text",
249
+ "text" => "Quite a plain modal"
250
+ },
251
+ "submit" => {
252
+ "type" => "plain_text",
253
+ "text" => "Create"
254
+ },
255
+ "blocks" => [
256
+ {
257
+ "type" => "input",
258
+ "block_id" => "a_block_id",
259
+ "label" => {
260
+ "type" => "plain_text",
261
+ "text" => "A simple label",
262
+ "emoji" => true
263
+ },
264
+ "optional" => false,
265
+ "element" => {
266
+ "type" => "plain_text_input",
267
+ "action_id" => "an_action_id"
268
+ }
269
+ }
270
+ ],
271
+ "private_metadata" => "Shh it is a secret",
272
+ "callback_id" => "identify_your_modals",
273
+ "external_id" => "",
274
+ "state" => {
275
+ "values" => {}
276
+ },
277
+ "hash" => "156772938.1827394",
278
+ "clear_on_close" => false,
279
+ "notify_on_close" => false,
280
+ "root_view_id" => "VMHU10V25",
281
+ "app_id" => "AA4928AQ",
282
+ "bot_id" => "BA13894H"
283
+ }
284
+ }.to_json
285
+ }
286
+ }
287
+ it "returns a successful response" do
288
+ expect(views_update.ok?).to eq(true)
289
+ end
290
+ context "when the response is unsuccessful" do
291
+ let(:response) {
292
+ {
293
+ status: 200,
294
+ body: {
295
+ "ok" => false,
296
+ "error" => "invalid_arguments",
297
+ "response_metadata" => {
298
+ "messages" => [
299
+ "invalid `trigger_id`"
300
+ ]
301
+ }
302
+ }.to_json
303
+ }
304
+ }
305
+ it "returns an unsuccessful response" do
306
+ expect(views_update.ok?).to eq(false)
307
+ end
308
+ end
309
+ end
310
+
311
+ describe "#chat_post_message" do
312
+ before do
313
+ stub_request(:post, "https://slack.com/api/chat.postMessage").to_return(response)
314
+ end
315
+ subject(:chat_post_message) {
316
+ client.chat_post_message(
317
+ channel: "C1234567890",
318
+ text: "Hello world",
319
+ blocks: [
320
+ {
321
+ "type" => "section",
322
+ "text" => {
323
+ "type" => "mrkdwn",
324
+ "text" => "Hello world"
325
+ }
326
+ }
327
+ ]
328
+ )
329
+ }
330
+ let(:response) {
331
+ {
332
+ status: 200,
333
+ body: {
334
+ "ok" => true,
335
+ "channel" => "C1234567890",
336
+ "ts" => "1503435956.000247",
337
+ "message" => {
338
+ "text" => "Hello world",
339
+ "username" => "ecto1",
340
+ "bot_id" => "B19LU7CSY",
341
+ "attachments" => [
342
+ {
343
+ "text" => "This is an attachment",
344
+ "id" => 1,
345
+ "fallback" => "This is an attachment's fallback"
346
+ }
347
+ ],
348
+ "type" => "message",
349
+ "subtype" => "bot_message",
350
+ "ts" => "1503435956.000247"
351
+ }
352
+ }.to_json
353
+ }
354
+ }
355
+ it "returns a successful response" do
356
+ expect(chat_post_message.ok?).to eq(true)
357
+ end
358
+ context "when the response is unsuccessful" do
359
+ let(:response) {
360
+ {
361
+ status: 200,
362
+ body: {
363
+ "ok" => false,
364
+ "error" => "too_many_attachments"
365
+ }.to_json
366
+ }
367
+ }
368
+ it "returns an unsuccessful response" do
369
+ expect(chat_post_message.ok?).to eq(false)
370
+ end
371
+ end
372
+ end
373
+
374
+ describe "#chat_update" do
375
+ before do
376
+ stub_request(:post, "https://slack.com/api/chat.update").to_return(response)
377
+ end
378
+ subject(:chat_update) {
379
+ client.chat_update(
380
+ channel: "C1234567890",
381
+ ts: "1503435956.000247",
382
+ text: "Hello world",
383
+ blocks: [
384
+ {
385
+ "type" => "section",
386
+ "text" => {
387
+ "type" => "mrkdwn",
388
+ "text" => "Hello world"
389
+ }
390
+ }
391
+ ]
392
+ )
393
+ }
394
+ let(:response) {
395
+ {
396
+ status: 200,
397
+ body: {
398
+ "ok" => true,
399
+ "channel" => "C1234567890",
400
+ "ts" => "1503435956.000247",
401
+ "message" => {
402
+ "text" => "Hello world",
403
+ "username" => "ecto1",
404
+ "bot_id" => "B19LU7CSY",
405
+ "attachments" => [
406
+ {
407
+ "text" => "This is an attachment",
408
+ "id" => 1,
409
+ "fallback" => "This is an attachment's fallback"
410
+ }
411
+ ],
412
+ "type" => "message",
413
+ "subtype" => "bot_message",
414
+ "ts" => "1503435956.000247"
415
+ }
416
+ }.to_json
417
+ }
418
+ }
419
+ it "returns a successful response" do
420
+ expect(chat_update.ok?).to eq(true)
421
+ end
422
+ context "when the response is unsuccessful" do
423
+ let(:response) {
424
+ {
425
+ status: 200,
426
+ body: {
427
+ "ok" => false,
428
+ "error" => "too_many_attachments"
429
+ }.to_json
430
+ }
431
+ }
432
+ it "returns an unsuccessful response" do
433
+ expect(chat_update.ok?).to eq(false)
434
+ end
435
+ end
436
+ end
437
+
438
+ describe "#views_publish" do
439
+ before do
440
+ stub_request(:post, "https://slack.com/api/views.publish").to_return(response)
441
+ end
442
+ subject(:views_publish) {
443
+ client.views_publish(
444
+ user_id: "U0R7JM",
445
+ view: {
446
+ "type" => "home",
447
+ "blocks" => [
448
+ {
449
+ "type" => "section",
450
+ "text" => {
451
+ "type" => "mrkdwn",
452
+ "text" => "Welcome to your _App's Home_* :tada:"
453
+ }
454
+ },
455
+ {
456
+ "type" => "divider"
457
+ },
458
+ {
459
+ "type" => "section",
460
+ "text" => {
461
+ "type" => "mrkdwn",
462
+ "text" => "This is a section block with a button."
463
+ },
464
+ "accessory" => {
465
+ "type" => "button",
466
+ "text" => {
467
+ "type" => "plain_text",
468
+ "text" => "Click Me"
469
+ },
470
+ "action_id" => "button_click"
471
+ }
472
+ }
473
+ ]
474
+ }
475
+ )
476
+ }
477
+ # TODO: Add a test for the response
478
+ end
479
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackBot::Args do
4
+ let(:args) { SlackBot::Args.new }
5
+ let(:raw_args) { "foo=bar&baz=qux" }
6
+
7
+ describe "#raw_args=" do
8
+ it "parses raw args" do
9
+ args.raw_args = raw_args
10
+ expect(args.args).to eq({ "foo" => "bar", "baz" => "qux" }.with_indifferent_access)
11
+ end
12
+ end
13
+
14
+ describe "#to_s" do
15
+ it "builds args" do
16
+ args.raw_args = raw_args
17
+ expect(args.to_s).to eq(raw_args)
18
+ end
19
+ end
20
+
21
+ describe "#merge" do
22
+ it "merges args" do
23
+ args.raw_args = raw_args
24
+ expect(args.merge(foo: "baz").args).to eq({ "foo" => "baz", "baz" => "qux" }.with_indifferent_access)
25
+ end
26
+ end
27
+
28
+ describe "#except" do
29
+ it "removes args" do
30
+ args.raw_args = raw_args
31
+ expect(args.except(:foo).args).to eq({ "baz" => "qux" }.with_indifferent_access)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackBot::Callback do
4
+ subject(:callback) {
5
+ described_class.new(
6
+ class_name: "Test",
7
+ method_name: "test",
8
+ user: user,
9
+ channel_id: "test_channel_id",
10
+ extra: { test: "test" },
11
+ config: config
12
+ )
13
+ }
14
+
15
+ let(:config) {
16
+ instance_double(
17
+ SlackBot::Config,
18
+ callback_storage_instance: callback_storage_instance,
19
+ callback_user_finder_method: callback_user_finder_method
20
+ )
21
+ }
22
+ let(:callback_storage_instance) { instance_double(SlackBot::CallbackStorage) }
23
+ let(:callback_user_finder_method) { ->(user_id) { user } }
24
+
25
+ let(:user) { double(:user, id: 1) }
26
+
27
+ let(:callback_id) { "test_callback_id" }
28
+
29
+ describe ".find" do
30
+ subject(:find) { described_class.find(callback_id, config: config) }
31
+
32
+ before do
33
+ allow(callback_storage_instance).to receive(:read).with("slack-bot-callback:test_callback_id").and_return(data)
34
+ end
35
+
36
+ context "when callback is found" do
37
+ let(:data) { { class_name: "Test", method_name: "test", user_id: 1, channel_id: "test_channel_id", extra: { test: "test" } } }
38
+
39
+ it "returns callback" do
40
+ expect(find).to be_a(described_class)
41
+ expect(find.id).to eq(callback_id)
42
+ expect(find.class_name).to eq("Test")
43
+ expect(find.user).to eq(user)
44
+ expect(find.user_id).to eq(1)
45
+ expect(find.channel_id).to eq("test_channel_id")
46
+ expect(find.method_name).to eq("test")
47
+ expect(find.extra).to eq({ test: "test" })
48
+ end
49
+ end
50
+ end
51
+
52
+ describe ".create" do
53
+ subject(:create) { described_class.create(class_name: "Test", method_name: "test", user: user, channel_id: "test_channel_id", config: config) }
54
+
55
+ before do
56
+ allow_any_instance_of(described_class).to receive(:generate_id).and_return("test_callback_id")
57
+ allow(callback_storage_instance).to receive(:write).with("slack-bot-callback:test_callback_id", {
58
+ args: "",
59
+ class_name: "Test",
60
+ method_name: "test",
61
+ user_id: 1,
62
+ channel_id: "test_channel_id",
63
+ extra: nil
64
+ }, expires_in: 1.hour)
65
+ end
66
+
67
+ let(:data) { { class_name: "Test", method_name: "test", user_id: 1, channel_id: "test_channel_id", extra: nil } }
68
+
69
+ it "returns callback" do
70
+ expect(create).to be_a(described_class)
71
+ expect(create.id).to eq("test_callback_id")
72
+ expect(create.class_name).to eq("Test")
73
+ expect(create.user).to eq(user)
74
+ expect(create.user_id).to eq(1)
75
+ expect(create.channel_id).to eq("test_channel_id")
76
+ expect(create.method_name).to eq("test")
77
+ expect(create.extra).to eq(nil)
78
+ end
79
+ end
80
+
81
+ describe "#reload" do
82
+
83
+ end
84
+
85
+ describe "#save" do
86
+
87
+ end
88
+
89
+ describe "#update" do
90
+
91
+ end
92
+
93
+ describe "#destroy" do
94
+
95
+ end
96
+
97
+ describe "#user" do
98
+
99
+ end
100
+
101
+ describe "#handler_class" do
102
+
103
+ end
104
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackBot::Command do
4
+
5
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackBot::Config do
4
+ subject(:config) { described_class.new }
5
+
6
+ describe ".configure" do
7
+
8
+ end
9
+
10
+ describe ".current_instance" do
11
+
12
+ end
13
+
14
+ describe "#callback_storage" do
15
+
16
+ end
17
+
18
+ describe "#callback_user_finder" do
19
+
20
+ end
21
+
22
+ describe "#event" do
23
+
24
+ end
25
+
26
+ describe "#slash_command_endpoint" do
27
+
28
+ end
29
+
30
+ describe "#menu_options" do
31
+
32
+ end
33
+
34
+ describe "#handler_class" do
35
+
36
+ end
37
+
38
+ describe "#find_event_handler" do
39
+
40
+ end
41
+
42
+ describe "#find_slash_command_config" do
43
+
44
+ end
45
+
46
+ describe "#find_menu_options" do
47
+
48
+ end
49
+
50
+ describe "#find_handler_class" do
51
+
52
+ end
53
+
54
+ describe "#find_command_config" do
55
+
56
+ end
57
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackBot::Event do
4
+
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackBot::GrapeExtension do
4
+
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackBot::Interaction do
4
+
5
+ end