slack-ruby-client 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +0 -1
  3. data/.rubocop_todo.yml +23 -6
  4. data/.travis.yml +3 -0
  5. data/CHANGELOG.md +11 -0
  6. data/Gemfile +2 -0
  7. data/README.md +89 -1
  8. data/RELEASING.md +3 -1
  9. data/UPGRADING.md +26 -0
  10. data/bin/commands.rb +20 -0
  11. data/bin/commands/api.rb +14 -0
  12. data/bin/commands/auth.rb +12 -0
  13. data/bin/commands/channels.rb +140 -0
  14. data/bin/commands/chat.rb +47 -0
  15. data/bin/commands/emoji.rb +12 -0
  16. data/bin/commands/files.rb +61 -0
  17. data/bin/commands/groups.rb +158 -0
  18. data/bin/commands/im.rb +53 -0
  19. data/bin/commands/mpim.rb +53 -0
  20. data/bin/commands/oauth.rb +16 -0
  21. data/bin/commands/pins.rb +37 -0
  22. data/bin/commands/reactions.rb +53 -0
  23. data/bin/commands/rtm.rb +15 -0
  24. data/bin/commands/search.rb +40 -0
  25. data/bin/commands/stars.rb +37 -0
  26. data/bin/commands/team.rb +32 -0
  27. data/bin/commands/usergroups.rb +73 -0
  28. data/bin/commands/users.rb +48 -0
  29. data/bin/slack +50 -0
  30. data/examples/hi_real_time/Gemfile +2 -0
  31. data/examples/hi_real_time_and_web/Gemfile +2 -0
  32. data/examples/hi_real_time_async/Gemfile +5 -0
  33. data/examples/hi_real_time_async/hi.rb +29 -0
  34. data/lib/slack-ruby-client.rb +2 -2
  35. data/lib/slack/real_time/client.rb +72 -30
  36. data/lib/slack/real_time/concurrency.rb +8 -0
  37. data/lib/slack/real_time/concurrency/celluloid.rb +92 -0
  38. data/lib/slack/real_time/concurrency/eventmachine.rb +39 -0
  39. data/lib/slack/real_time/config.rb +23 -1
  40. data/lib/slack/real_time/socket.rb +50 -12
  41. data/lib/slack/version.rb +1 -1
  42. data/lib/slack/web/api/endpoints.rb +2 -0
  43. data/lib/slack/web/api/endpoints/groups.rb +1 -1
  44. data/lib/slack/web/api/endpoints/team.rb +1 -1
  45. data/lib/slack/web/api/endpoints/usergroups.rb +113 -0
  46. data/lib/slack/web/api/error.rb +6 -0
  47. data/lib/slack/web/api/schema/group.json +14 -0
  48. data/lib/slack/web/api/tasks/generate.rake +19 -3
  49. data/lib/slack/web/api/templates/command.erb +34 -0
  50. data/lib/slack/web/api/templates/commands.erb +5 -0
  51. data/lib/slack/web/config.rb +2 -0
  52. data/lib/slack/web/faraday/connection.rb +3 -2
  53. data/lib/slack/web/faraday/response/raise_error.rb +2 -1
  54. data/slack-ruby-client.gemspec +4 -2
  55. data/spec/fixtures/slack/web/429_error.yml +83 -0
  56. data/spec/fixtures/slack/web/rtm_start.yml +1 -1
  57. data/spec/fixtures/slack/web/users_list.yml +72 -0
  58. data/spec/integration/integration_spec.rb +88 -0
  59. data/spec/slack/real_time/client_spec.rb +8 -5
  60. data/spec/slack/real_time/concurrency/celluloid_spec.rb +58 -0
  61. data/spec/slack/real_time/concurrency/eventmachine_spec.rb +49 -0
  62. data/spec/slack/slack_spec.rb +52 -0
  63. data/spec/slack/web/api/endpoints/auth_spec.rb +6 -1
  64. data/spec/slack/web/api/endpoints/users_spec.rb +13 -0
  65. data/spec/slack/web/api/error_spec.rb +14 -0
  66. data/spec/slack/web/client_spec.rb +16 -0
  67. data/spec/support/real_time/concurrency/mock.rb +31 -0
  68. data/spec/support/real_time/connected_client.rb +5 -2
  69. metadata +55 -8
  70. data/spec/slack/real_time/socket_spec.rb +0 -46
@@ -13,8 +13,16 @@ namespace :slack do
13
13
 
14
14
  desc 'Update API.'
15
15
  task update: [:git_update] do
16
+ group_schema = JSON.parse(File.read('lib/slack/web/api/schema/group.json'))
17
+ groups = Dir.glob('lib/slack/web/api/slack-api-ref/groups/**/*.json').each_with_object({}) do |path, result|
18
+ name = File.basename(path, '.json')
19
+ parsed = JSON.parse(File.read(path))
20
+ JSON::Validator.validate(group_schema, parsed, insert_defaults: true)
21
+ result[name] = parsed
22
+ end
23
+
16
24
  method_schema = JSON.parse(File.read('lib/slack/web/api/schema/method.json'))
17
- data = Dir.glob('lib/slack/web/api/slack-api-ref/methods/*.json').each_with_object({}) do |path, result|
25
+ data = Dir.glob('lib/slack/web/api/slack-api-ref/methods/**/*.json').each_with_object({}) do |path, result|
18
26
  name = File.basename(path, '.json')
19
27
  prefix, name = name.split('.')
20
28
  result[prefix] ||= {}
@@ -24,18 +32,26 @@ namespace :slack do
24
32
  end
25
33
 
26
34
  method_template = Erubis::Eruby.new(File.read('lib/slack/web/api/templates/method.erb'))
35
+ command_template = Erubis::Eruby.new(File.read('lib/slack/web/api/templates/command.erb'))
27
36
  data.each_with_index do |(group, names), index|
28
37
  printf "%2d/%2d %10s %s\n", index, data.size, group, names.keys
29
- rendered = method_template.result(group: group, names: names)
30
- File.write "lib/slack/web/api/endpoints/#{group}.rb", rendered
38
+ # method
39
+ rendered_method = method_template.result(group: group, names: names)
40
+ File.write "lib/slack/web/api/endpoints/#{group}.rb", rendered_method
31
41
  Dir.glob("lib/slack/web/api/patches/#{group}*.patch").sort.each do |patch|
32
42
  puts "- patching #{patch}"
33
43
  system("git apply #{patch}") || fail('failed to apply patch')
34
44
  end
45
+ # command
46
+ rendered_command = command_template.result(group: groups[group], names: names)
47
+ File.write "bin/commands/#{group}.rb", rendered_command
35
48
  end
36
49
 
37
50
  endpoints_template = Erubis::Eruby.new(File.read('lib/slack/web/api/templates/endpoints.erb'))
38
51
  File.write 'lib/slack/web/api/endpoints.rb', endpoints_template.result(files: data.keys)
52
+
53
+ commands_template = Erubis::Eruby.new(File.read('lib/slack/web/api/templates/commands.erb'))
54
+ File.write 'bin/commands.rb', commands_template.result(files: data.keys)
39
55
  end
40
56
  end
41
57
  end
@@ -0,0 +1,34 @@
1
+ # This file was auto-generated by lib/slack/web/api/tasks/generate.rake
2
+
3
+ <% desc = group['desc'] || "#{group['name'].capitalize} methods." %>
4
+ <% if desc.include?("'") %>
5
+ desc "<%= desc %>"
6
+ <% else %>
7
+ desc '<%= desc %>'
8
+ <% end %>
9
+ command '<%= group['name'] %>' do |g|
10
+ <% names.each_with_index do |(name, data), index| %>
11
+ <% if index > 0 %>
12
+
13
+ <% end %>
14
+ <% short_desc = data["desc"].split("\n").first %>
15
+ <% if short_desc.include?("'") %>
16
+ g.desc "<%= short_desc %>"
17
+ <% else %>
18
+ g.desc '<%= short_desc %>'
19
+ <% end %>
20
+ g.long_desc %( <%= data["desc"].split("\n").join(" ") %> )
21
+ g.command '<%= name %>' do |c|
22
+ <% data["args"].each do |arg_name, arg_v| %>
23
+ <% if arg_v["desc"].include?("'") %>
24
+ c.flag '<%= arg_name %>', desc: "<%= arg_v["desc"] %>"
25
+ <% else %>
26
+ c.flag '<%= arg_name %>', desc: '<%= arg_v["desc"] %>'
27
+ <% end %>
28
+ <% end %>
29
+ c.action do |_global_options, options, _args|
30
+ puts JSON.dump($client.<%=group['name'] %>_<%= name %>(options))
31
+ end
32
+ end
33
+ <% end %>
34
+ end
@@ -0,0 +1,5 @@
1
+ # This file was auto-generated by lib/slack/web/api/tasks/generate.rake
2
+
3
+ <% files.each do |f| %>
4
+ require 'commands/<%= f %>'
5
+ <% end %>
@@ -8,6 +8,7 @@ module Slack
8
8
  :user_agent,
9
9
  :ca_path,
10
10
  :ca_file,
11
+ :logger,
11
12
  :endpoint,
12
13
  :token
13
14
  ]
@@ -21,6 +22,7 @@ module Slack
21
22
  self.ca_file = "#{ca_path}/ca-certificates.crt"
22
23
  self.token = nil
23
24
  self.proxy = nil
25
+ self.logger = nil
24
26
  end
25
27
  end
26
28
 
@@ -16,10 +16,11 @@ module Slack
16
16
  ::Faraday::Connection.new(endpoint, options) do |connection|
17
17
  connection.use ::Faraday::Request::Multipart
18
18
  connection.use ::Faraday::Request::UrlEncoded
19
- connection.use ::Faraday::Response::RaiseError
20
19
  connection.use ::Slack::Web::Faraday::Response::RaiseError
21
20
  connection.use ::FaradayMiddleware::ParseJson
22
- connection.adapter(::Faraday.default_adapter)
21
+ connection.use ::Faraday::Response::RaiseError
22
+ connection.response :logger, logger if logger
23
+ connection.adapter ::Faraday.default_adapter
23
24
  end
24
25
  end
25
26
  end
@@ -5,7 +5,8 @@ module Slack
5
5
  class RaiseError < ::Faraday::Response::Middleware
6
6
  def on_complete(env)
7
7
  body = env.body
8
- fail Slack::Web::Api::Error, body['error'] unless body['ok']
8
+ return if body['ok']
9
+ fail Slack::Web::Api::Error.new(body['error'], env.response)
9
10
  end
10
11
  end
11
12
  end
@@ -3,6 +3,8 @@ require 'slack/version'
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'slack-ruby-client'
6
+ s.bindir = 'bin'
7
+ s.executables << 'slack'
6
8
  s.version = Slack::VERSION
7
9
  s.authors = ['Daniel Doubrovkine']
8
10
  s.email = 'dblock@dblock.org'
@@ -16,9 +18,9 @@ Gem::Specification.new do |s|
16
18
  s.summary = 'Slack Web and RealTime API client.'
17
19
  s.add_dependency 'faraday'
18
20
  s.add_dependency 'faraday_middleware'
19
- s.add_dependency 'faye-websocket'
20
- s.add_dependency 'eventmachine'
21
21
  s.add_dependency 'json'
22
+ s.add_dependency 'websocket-driver'
23
+ s.add_dependency 'gli'
22
24
  s.add_development_dependency 'erubis'
23
25
  s.add_development_dependency 'json-schema'
24
26
  s.add_development_dependency 'rake'
@@ -0,0 +1,83 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://slack.com/api/auth.test
6
+ body:
7
+ encoding: UTF-8
8
+ string: token=
9
+ headers:
10
+ Accept:
11
+ - application/json; charset=utf-8
12
+ User-Agent:
13
+ - Slack Ruby Client 0.1.0
14
+ Content-Type:
15
+ - application/x-www-form-urlencoded
16
+ Accept-Encoding:
17
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
18
+ response:
19
+ status:
20
+ code: 429
21
+ message: OK
22
+ headers:
23
+ Access-Control-Allow-Origin:
24
+ - '*'
25
+ Date:
26
+ - Sat, 25 Jul 2015 14:42:07 GMT
27
+ Server:
28
+ - Apache
29
+ Connection:
30
+ - keep-alive
31
+ body:
32
+ encoding: US-ASCII
33
+ string: ''
34
+ http_version:
35
+ recorded_at: Sat, 25 Jul 2015 14:42:08 GMT
36
+ - request:
37
+ method: post
38
+ uri: https://slack.com/api/auth.test
39
+ body:
40
+ encoding: UTF-8
41
+ string: token
42
+ headers:
43
+ Accept:
44
+ - application/json; charset=utf-8
45
+ User-Agent:
46
+ - Slack Ruby Client/0.5.0
47
+ Content-Type:
48
+ - application/x-www-form-urlencoded
49
+ Accept-Encoding:
50
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
51
+ response:
52
+ status:
53
+ code: 200
54
+ message: OK
55
+ headers:
56
+ Access-Control-Allow-Origin:
57
+ - '*'
58
+ Content-Security-Policy:
59
+ - referrer no-referrer;
60
+ Content-Type:
61
+ - application/json; charset=utf-8
62
+ Date:
63
+ - Tue, 24 Nov 2015 20:03:05 GMT
64
+ Server:
65
+ - Apache
66
+ Strict-Transport-Security:
67
+ - max-age=31536000; includeSubDomains; preload
68
+ X-Accepted-Oauth-Scopes:
69
+ - identify
70
+ X-Content-Type-Options:
71
+ - nosniff
72
+ X-Xss-Protection:
73
+ - '0'
74
+ Content-Length:
75
+ - '33'
76
+ Connection:
77
+ - keep-alive
78
+ body:
79
+ encoding: UTF-8
80
+ string: '{"ok":false,"error":"not_authed"}'
81
+ http_version:
82
+ recorded_at: Tue, 24 Nov 2015 20:03:05 GMT
83
+ recorded_with: VCR 2.9.3
@@ -5,7 +5,7 @@ http_interactions:
5
5
  uri: https://slack.com/api/rtm.start
6
6
  body:
7
7
  encoding: UTF-8
8
- string: token=xoxb-7171717171-ABCDEFGhIJ2lZifrEaQP5vF4
8
+ string: token=token
9
9
  headers:
10
10
  Accept:
11
11
  - application/json; charset=utf-8
@@ -0,0 +1,72 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://slack.com/api/users.list
6
+ body:
7
+ encoding: UTF-8
8
+ string: presence=true&token=token
9
+ headers:
10
+ Accept:
11
+ - application/json; charset=utf-8
12
+ User-Agent:
13
+ - Slack Ruby Client/0.5.0
14
+ Content-Type:
15
+ - application/x-www-form-urlencoded
16
+ Accept-Encoding:
17
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Access-Control-Allow-Origin:
24
+ - "*"
25
+ Cache-Control:
26
+ - private, no-cache, no-store, must-revalidate
27
+ Content-Security-Policy:
28
+ - referrer no-referrer;
29
+ Content-Type:
30
+ - application/json; charset=utf-8
31
+ Date:
32
+ - Sun, 06 Dec 2015 20:18:45 GMT
33
+ Expires:
34
+ - Mon, 26 Jul 1997 05:00:00 GMT
35
+ Pragma:
36
+ - no-cache
37
+ Server:
38
+ - Apache
39
+ Strict-Transport-Security:
40
+ - max-age=31536000; includeSubDomains; preload
41
+ Vary:
42
+ - Accept-Encoding
43
+ X-Accepted-Oauth-Scopes:
44
+ - users:read,read
45
+ X-Content-Type-Options:
46
+ - nosniff
47
+ X-Oauth-Scopes:
48
+ - identify,read,post,client
49
+ X-Xss-Protection:
50
+ - '0'
51
+ Content-Length:
52
+ - '1450'
53
+ Connection:
54
+ - keep-alive
55
+ body:
56
+ encoding: ASCII-8BIT
57
+ string: '{"ok":true,"members":[{"id":"U092BDCLV","team_id":"T04KB5WQH","name":"artsy","deleted":false,"status":null,"color":"e0a729","real_name":"Artsy
58
+ Bot","tz":null,"tz_label":"Pacific Standard Time","tz_offset":-28800,"profile":{"bot_id":"B092B5DDG","image_24":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_48.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_48.jpg","image_512":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_48.jpg","image_1024":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_48.jpg","image_original":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_original.jpg","first_name":"Artsy","last_name":"Bot","title":"Searches
59
+ Artsy.","real_name":"Artsy Bot","real_name_normalized":"Artsy Bot"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"presence":"away"},{"id":"U07KECJ77","team_id":"T04KB5WQH","name":"aws","deleted":false,"status":null,"color":"e96699","real_name":"AWS
60
+ Cloud","tz":null,"tz_label":"Pacific Standard Time","tz_offset":-28800,"profile":{"bot_id":"B07KECJ6R","image_24":"https:\/\/avatars.slack-edge.com\/2015-07-14\/7660472085_4755a86e204c9706c84f_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2015-07-14\/7660472085_4755a86e204c9706c84f_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2015-07-14\/7660472085_4755a86e204c9706c84f_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2015-07-14\/7660472085_4755a86e204c9706c84f_48.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2015-07-14\/7660472085_4755a86e204c9706c84f_48.jpg","image_original":"https:\/\/avatars.slack-edge.com\/2015-07-14\/7660472085_4755a86e204c9706c84f_original.jpg","first_name":"AWS","last_name":"Cloud","real_name":"AWS
61
+ Cloud","real_name_normalized":"AWS Cloud"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"presence":"away"},{"id":"U0EA7TZJN","team_id":"T04KB5WQH","name":"bar","deleted":false,"status":null,"color":"5b89d5","real_name":"","tz":null,"tz_label":"Pacific
62
+ Standard Time","tz_offset":-28800,"profile":{"bot_id":"B0EA31LQM","image_24":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_72.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_192.jpg","image_512":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_512.jpg","image_1024":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_512.jpg","image_original":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_original.jpg","real_name":"","real_name_normalized":""},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"presence":"away"},{"id":"U092V4E9L","team_id":"T04KB5WQH","name":"broskoski","deleted":false,"status":null,"color":"684b6c","real_name":"Cab","tz":"America\/Indiana\/Indianapolis","tz_label":"Eastern
63
+ Standard Time","tz_offset":-18000,"profile":{"first_name":"Cab","real_name":"Cab","real_name_normalized":"Cab","email":"cab@artsymail.com","image_24":"https:\/\/secure.gravatar.com\/avatar\/99621cbca6ea94706a8f5dcdc5e8af4a.jpg?s=24&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0017-24.png","image_32":"https:\/\/secure.gravatar.com\/avatar\/99621cbca6ea94706a8f5dcdc5e8af4a.jpg?s=32&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0017-32.png","image_48":"https:\/\/secure.gravatar.com\/avatar\/99621cbca6ea94706a8f5dcdc5e8af4a.jpg?s=48&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0017-48.png","image_72":"https:\/\/secure.gravatar.com\/avatar\/99621cbca6ea94706a8f5dcdc5e8af4a.jpg?s=72&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0017-72.png","image_192":"https:\/\/secure.gravatar.com\/avatar\/99621cbca6ea94706a8f5dcdc5e8af4a.jpg?s=192&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F7fa9%2Fimg%2Favatars%2Fava_0017-192.png","image_512":"https:\/\/secure.gravatar.com\/avatar\/99621cbca6ea94706a8f5dcdc5e8af4a.jpg?s=512&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F7fa9%2Fimg%2Favatars%2Fava_0017-512.png"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":false,"presence":"away"},{"id":"U04KB5WQR","team_id":"T04KB5WQH","name":"example","deleted":false,"status":null,"color":"9f69e7","real_name":"","tz":"America\/Indiana\/Indianapolis","tz_label":"Eastern
64
+ Standard Time","tz_offset":-18000,"profile":{"real_name":"","real_name_normalized":"","email":"user@example.org","image_24":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=24&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0015-24.png","image_32":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=32&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0015-32.png","image_48":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=48&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0015-48.png","image_72":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=72&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0015-72.png","image_192":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=192&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F7fa9%2Fimg%2Favatars%2Fava_0015-192.png","image_512":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=512&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F7fa9%2Fimg%2Favatars%2Fava_0015-512.png"},"is_admin":true,"is_owner":true,"is_primary_owner":true,"is_restricted":false,"is_ultra_restricted":false,"is_bot":false,"presence":"active"},{"id":"U04JZBDQQ","team_id":"T04KB5WQH","name":"foo","deleted":true,"profile":{"bot_id":"B04JZBDQC","image_24":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4645387956_44604ca32e800d947f22_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4645387956_44604ca32e800d947f22_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4645387956_44604ca32e800d947f22_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4645387956_44604ca32e800d947f22_72.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4645387956_44604ca32e800d947f22_192.jpg","image_original":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4645387956_44604ca32e800d947f22_original.jpg","real_name":"","real_name_normalized":""},"is_bot":true,"presence":"away"},{"id":"U04JPQ0JS","team_id":"T04KB5WQH","name":"gamebot","deleted":false,"status":null,"color":"4bbe2e","real_name":"Game
65
+ Bot","tz":null,"tz_label":"Pacific Standard Time","tz_offset":-28800,"profile":{"bot_id":"B04JPQ0JE","image_24":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4635825662_28d3661bf00dc6013442_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4635825662_28d3661bf00dc6013442_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4635825662_28d3661bf00dc6013442_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4635825662_28d3661bf00dc6013442_48.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4635825662_28d3661bf00dc6013442_48.jpg","image_original":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4635825662_28d3661bf00dc6013442_original.jpg","first_name":"Game","last_name":"Bot","title":"Game
66
+ ons.","real_name":"Game Bot","real_name_normalized":"Game Bot"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"presence":"away"},{"id":"U06JGTU5V","team_id":"T04KB5WQH","name":"mathbot","deleted":false,"status":null,"color":"3c989f","real_name":"Math
67
+ Bot","tz":null,"tz_label":"Pacific Standard Time","tz_offset":-28800,"profile":{"bot_id":"B06JH1N93","image_24":"https:\/\/avatars.slack-edge.com\/2015-06-19\/6629501812_c507c80d735dfc75bbc8_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2015-06-19\/6629501812_c507c80d735dfc75bbc8_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2015-06-19\/6629501812_c507c80d735dfc75bbc8_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2015-06-19\/6629501812_c507c80d735dfc75bbc8_48.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2015-06-19\/6629501812_c507c80d735dfc75bbc8_48.jpg","image_original":"https:\/\/avatars.slack-edge.com\/2015-06-19\/6629501812_c507c80d735dfc75bbc8_original.jpg","first_name":"Math","last_name":"Bot","real_name":"Math
68
+ Bot","real_name_normalized":"Math Bot"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"presence":"away"},{"id":"U07518DTL","team_id":"T04KB5WQH","name":"rubybot","deleted":false,"status":null,"color":"674b1b","real_name":"","tz":null,"tz_label":"Pacific
69
+ Standard Time","tz_offset":-28800,"profile":{"bot_id":"B0751JU2H","image_24":"https:\/\/avatars.slack-edge.com\/2015-07-02\/7171641589_359bf095c1fe0841e582_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2015-07-02\/7171641589_359bf095c1fe0841e582_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2015-07-02\/7171641589_359bf095c1fe0841e582_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2015-07-02\/7171641589_359bf095c1fe0841e582_48.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2015-07-02\/7171641589_359bf095c1fe0841e582_48.jpg","image_original":"https:\/\/avatars.slack-edge.com\/2015-07-02\/7171641589_359bf095c1fe0841e582_original.jpg","real_name":"","real_name_normalized":""},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"presence":"away"}]}'
70
+ http_version:
71
+ recorded_at: Sun, 06 Dec 2015 20:18:46 GMT
72
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,88 @@
1
+ require 'slack'
2
+ require 'logger'
3
+
4
+ RSpec.describe 'integration test', skip: !ENV['SLACK_API_TOKEN'] && 'missing SLACK_API_TOKEN' do
5
+ before do
6
+ Thread.abort_on_exception = true
7
+ end
8
+
9
+ let(:logger) { Logger.new(STDOUT) }
10
+
11
+ let(:queue) { Queue.new }
12
+
13
+ let(:client) { Slack::RealTime::Client.new(token: ENV['SLACK_API_TOKEN']) }
14
+
15
+ let(:connection) do
16
+ # starts the client and pushes an item on a queue when connected
17
+ client.start_async do |driver|
18
+ driver.on :open do |data|
19
+ logger.debug "connection.on :open, data=#{data}"
20
+ queue.push nil
21
+ end
22
+ end
23
+ end
24
+
25
+ before do
26
+ client.on :hello do
27
+ logger.info "Successfully connected, welcome '#{client.self['name']}' to the '#{client.team['name']}' team at https://#{client.team['domain']}.slack.com."
28
+ end
29
+
30
+ client.on :close do
31
+ # pushes another item to the queue when disconnected
32
+ queue.push nil
33
+ end
34
+ end
35
+
36
+ def start_server
37
+ logger.debug '#start_server'
38
+ # start server and wait for on :open
39
+ c = connection
40
+ logger.debug "connection is #{c}"
41
+ queue.pop
42
+ end
43
+
44
+ def wait_for_server
45
+ logger.debug '#wait_for_server'
46
+ queue.pop
47
+ logger.debug '#wait_for_server, joined'
48
+ end
49
+
50
+ def stop_server
51
+ logger.debug '#stop_server'
52
+ client.stop!
53
+ logger.debug '#stop_server, stopped'
54
+ end
55
+
56
+ after do
57
+ wait_for_server
58
+ end
59
+
60
+ context 'client connected' do
61
+ before do
62
+ start_server
63
+ end
64
+
65
+ it 'responds to message' do
66
+ message = SecureRandom.hex
67
+
68
+ client.on :message do |data|
69
+ logger.debug data
70
+ expect(data).to include('text' => message, 'subtype' => 'bot_message')
71
+ logger.debug 'client.stop!'
72
+ client.stop!
73
+ end
74
+
75
+ logger.debug "chat_postMessage, channel=@#{client.self['name']}, message=#{message}"
76
+ client.web_client.chat_postMessage channel: "@#{client.self['name']}", text: message
77
+ end
78
+ end
79
+
80
+ it 'gets hello' do
81
+ client.on :hello do |data|
82
+ logger.debug "client.on :hello, data=#{data}"
83
+ client.stop!
84
+ end
85
+
86
+ start_server
87
+ end
88
+ end
@@ -1,10 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Slack::RealTime::Client, vcr: { cassette_name: 'web/rtm_start' } do
4
- let(:ws) { double(Faye::WebSocket::Client, on: true) }
4
+ let(:ws) { double(Slack::RealTime::Concurrency::Mock::WebSocket, on: true) }
5
5
  let(:url) { 'wss://ms173.slack-msgs.com/websocket/lqcUiAvrKTP-uuid=' }
6
6
  before do
7
- allow(EM).to receive(:run).and_yield
7
+ Slack::RealTime.configure do |config|
8
+ config.concurrency = Slack::RealTime::Concurrency::Mock
9
+ end
8
10
  end
9
11
  context 'token' do
10
12
  before do
@@ -42,7 +44,8 @@ RSpec.describe Slack::RealTime::Client, vcr: { cassette_name: 'web/rtm_start' }
42
44
  let(:socket) { double(Slack::RealTime::Socket, connected?: true) }
43
45
  before do
44
46
  allow(Slack::RealTime::Socket).to receive(:new).with(url, ping: 30).and_return(socket)
45
- allow(socket).to receive(:connect!).and_yield(ws)
47
+ allow(socket).to receive(:connect!)
48
+ allow(socket).to receive(:start_sync).and_yield
46
49
  client.start!
47
50
  end
48
51
  context 'properties provided upon connection' do
@@ -151,7 +154,7 @@ RSpec.describe Slack::RealTime::Client, vcr: { cassette_name: 'web/rtm_start' }
151
154
  expect(client.websocket_ping).to eq 15
152
155
  end
153
156
  it 'creates a connection with custom ping' do
154
- expect(Faye::WebSocket::Client).to receive(:new).with(url, nil, ping: 15).and_return(ws)
157
+ expect(Slack::RealTime::Concurrency::Mock::WebSocket).to receive(:new).with(url, nil, ping: 15).and_return(ws)
155
158
  client.start!
156
159
  end
157
160
  end
@@ -173,7 +176,7 @@ RSpec.describe Slack::RealTime::Client, vcr: { cassette_name: 'web/rtm_start' }
173
176
  )
174
177
  end
175
178
  it 'creates a connection with custom proxy' do
176
- expect(Faye::WebSocket::Client).to receive(:new).with(
179
+ expect(Slack::RealTime::Concurrency::Mock::WebSocket).to receive(:new).with(
177
180
  url,
178
181
  nil,
179
182
  ping: 30,