slack_message 2.4.0 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,6 +10,10 @@ module SlackMessage::Api
10
10
  raise ArgumentError, "Tried to find profile by invalid email address '#{email}'"
11
11
  end
12
12
 
13
+ if SlackMessage::Configuration.debugging?
14
+ warn [email, profile].inspect
15
+ end
16
+
13
17
  response = look_up_user_by_email(email, profile)
14
18
 
15
19
  if response.code != "200"
@@ -24,14 +28,7 @@ module SlackMessage::Api
24
28
  raise SlackMessage::ApiError, "Unable to parse JSON response from Slack API\n#{response.body}"
25
29
  end
26
30
 
27
- if payload.include?("error") && payload["error"] == "invalid_auth"
28
- raise SlackMessage::ApiError, "Received an error because your authentication token isn't properly configured."
29
- elsif payload.include?("error") && payload["error"] == "users_not_found"
30
- raise SlackMessage::ApiError, "Couldn't find a user with the email '#{email}'."
31
- elsif payload.include?("error")
32
- raise SlackMessage::ApiError, "Received error response from Slack during user lookup:\n#{response.body}"
33
- end
34
-
31
+ SlackMessage::ErrorHandling.raise_user_lookup_errors(response, target, profile)
35
32
  payload["user"]["id"]
36
33
  end
37
34
 
@@ -59,7 +56,7 @@ module SlackMessage::Api
59
56
  if !time.nil?
60
57
  params[:post_at] = time.to_i
61
58
 
62
- if params[:icon_url] || params[:icon_emoji]
59
+ if payload.custom_bot_name || payload.custom_bot_icon
63
60
  raise ArgumentError, "Sorry, setting an image / emoji icon for scheduled messages isn't supported."
64
61
  end
65
62
  end
@@ -69,24 +66,55 @@ module SlackMessage::Api
69
66
  end
70
67
 
71
68
  response = post_message(profile, params)
69
+
70
+ SlackMessage::ErrorHandling.raise_post_response_errors(response, params, profile)
71
+ SlackMessage::Response.new(response, profile[:handle])
72
+ end
73
+
74
+ def update(payload, message, profile)
75
+ params = {
76
+ channel: message.channel,
77
+ ts: message.timestamp,
78
+ blocks: payload.render,
79
+ text: payload.custom_notification
80
+ }
81
+
82
+ if params[:blocks].length == 0
83
+ raise ArgumentError, "Tried to send an entirely empty message."
84
+ end
85
+
86
+ if SlackMessage::Configuration.debugging?
87
+ warn params.inspect
88
+ end
89
+
90
+ response = update_message(profile, params)
72
91
  body = JSON.parse(response.body)
73
92
  error = body.fetch("error", "")
74
93
 
75
- # let's try to be helpful about error messages
76
- if ["token_revoked", "token_expired", "invalid_auth", "not_authed"].include?(error)
77
- raise SlackMessage::ApiError, "Couldn't send slack message because the API key for profile '#{profile[:handle]}' is wrong."
78
- elsif ["no_permission", "ekm_access_denied"].include?(error)
79
- raise SlackMessage::ApiError, "Couldn't send slack message because the API key for profile '#{profile[:handle]}' isn't allowed to post messages."
80
- elsif error == "channel_not_found"
81
- raise SlackMessage::ApiError, "Tried to send Slack message to non-existent channel or user '#{target}'"
82
- elsif error == "invalid_arguments"
83
- raise SlackMessage::ApiError, "Tried to send Slack message with invalid payload."
84
- elsif response.code == "302"
85
- raise SlackMessage::ApiError, "Got 302 response while posting to Slack. Check your API key for profile '#{profile[:handle]}'."
86
- elsif response.code != "200"
87
- raise SlackMessage::ApiError, "Got an error back from the Slack API (HTTP #{response.code}):\n#{response.body}"
94
+ SlackMessage::ErrorHandling.raise_post_response_errors(response, message, profile)
95
+ SlackMessage::Response.new(response, profile[:handle])
96
+ end
97
+
98
+ def delete(message, profile)
99
+ params = if message.scheduled?
100
+ {
101
+ channel: message.channel,
102
+ scheduled_message_id: message.scheduled_message_id,
103
+ }
104
+ else
105
+ {
106
+ channel: message.channel,
107
+ ts: message.timestamp,
108
+ }
109
+ end
110
+
111
+ if SlackMessage::Configuration.debugging?
112
+ warn params.inspect
88
113
  end
89
114
 
115
+ response = delete_message(profile, params)
116
+
117
+ SlackMessage::ErrorHandling.raise_delete_response_errors(response, message, profile)
90
118
  response
91
119
  end
92
120
 
@@ -108,7 +136,7 @@ module SlackMessage::Api
108
136
  end
109
137
 
110
138
  def post_message(profile, params)
111
- uri = if params[:post_at]
139
+ uri = if params.has_key?(:post_at)
112
140
  URI("https://slack.com/api/chat.scheduleMessage")
113
141
  else
114
142
  URI("https://slack.com/api/chat.postMessage")
@@ -124,4 +152,36 @@ module SlackMessage::Api
124
152
  http.request(request)
125
153
  end
126
154
  end
155
+
156
+ def update_message(profile, params)
157
+ uri = URI("https://slack.com/api/chat.update")
158
+
159
+ request = Net::HTTP::Post.new(uri).tap do |req|
160
+ req['Authorization'] = "Bearer #{profile[:api_token]}"
161
+ req['Content-type'] = "application/json; charset=utf-8"
162
+ req.body = params.to_json
163
+ end
164
+
165
+ Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
166
+ http.request(request)
167
+ end
168
+ end
169
+
170
+ def delete_message(profile, params)
171
+ uri = if params.has_key?(:scheduled_message_id)
172
+ URI("https://slack.com/api/chat.deleteScheduledMessage")
173
+ else
174
+ URI("https://slack.com/api/chat.delete")
175
+ end
176
+
177
+ request = Net::HTTP::Post.new(uri).tap do |req|
178
+ req['Authorization'] = "Bearer #{profile[:api_token]}"
179
+ req['Content-type'] = "application/json; charset=utf-8"
180
+ req.body = params.to_json
181
+ end
182
+
183
+ Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
184
+ http.request(request)
185
+ end
186
+ end
127
187
  end
@@ -63,6 +63,13 @@ class SlackMessage::Dsl
63
63
 
64
64
  text = self.enrich_text(text)
65
65
 
66
+
67
+ previous_context = @body.find { |element| element[:type] && element[:type] == "context" }
68
+ if previous_context
69
+ previous_text = previous_context[:elements].first[:text]
70
+ warn "WARNING: Overriding previous context in section: #{previous_text}"
71
+ end
72
+
66
73
  @body.push({ type: "context", elements: [{
67
74
  type: "mrkdwn", text: text
68
75
  }]})
@@ -94,6 +101,10 @@ class SlackMessage::Dsl
94
101
  end
95
102
 
96
103
  def notification_text(msg)
104
+ if @custom_notification
105
+ warn "WARNING: Overriding previous custom notification text: #{@custom_notification}"
106
+ end
107
+
97
108
  @custom_notification = msg
98
109
  end
99
110
 
@@ -0,0 +1,124 @@
1
+ class SlackMessage::ErrorHandling
2
+ PERMISSIONS_ERRORS = ["token_revoked", "token_expired", "invalid_auth", "not_authed",
3
+ "team_access_not_granted", "no_permission", "missing_scope",
4
+ "not_allowed_token_type", "ekm_access_denied"]
5
+
6
+ def self.raise_post_response_errors(response, params, profile)
7
+ body = JSON.parse(response.body)
8
+ error = body.fetch("error", "")
9
+
10
+ if ["invalid_blocks", "invalid_blocks_format"].include?(error)
11
+ raise SlackMessage::ApiError, "Couldn't send Slack message because the serialized message had an invalid format"
12
+ elsif error == "channel_not_found"
13
+ raise SlackMessage::ApiError, "Tried to send Slack message to non-existent channel or user '#{params[:channel]}'"
14
+
15
+ # scheduling messages
16
+ elsif error == "invalid_time"
17
+ raise SlackMessage::ApiError, "Couldn't schedule Slack message because you requested an invalid time '#{params[:post_at]}'"
18
+ elsif error == "time_in_past"
19
+ raise SlackMessage::ApiError, "Couldn't schedule Slack message because you requested a time in the past (or too close to now) '#{params[:post_at]}'"
20
+ elsif error == "time_too_far"
21
+ raise SlackMessage::ApiError, "Couldn't schedule Slack message because you requested a time more than 120 days in the future '#{params[:post_at]}'"
22
+
23
+
24
+ elsif PERMISSIONS_ERRORS.include?(error)
25
+ raise SlackMessage::ApiError, "Couldn't send Slack message because the API key for profile '#{profile[:handle]}' is wrong, or the app has insufficient permissions (#{error})"
26
+ elsif error == "message_too_long"
27
+ raise SlackMessage::ApiError, "Tried to send Slack message, but the message was too long"
28
+ elsif error == "invalid_arguments"
29
+ raise SlackMessage::ApiError, "Tried to send Slack message with invalid payload"
30
+ elsif ["rate_limited", "ratelimited"].include?(error)
31
+ raise SlackMessage::ApiError, "Couldn't send Slack message because you've reached your rate limit"
32
+ elsif response.code == "302"
33
+ raise SlackMessage::ApiError, "Got 302 response while posting to Slack. Check your API key for profile '#{profile[:handle]}'"
34
+ elsif response.code != "200"
35
+ raise SlackMessage::ApiError, "Got an error back from the Slack API (HTTP #{response.code}):\n#{response.body}"
36
+ elsif !(error.nil? || error == "")
37
+ raise SlackMessage::ApiError, "Received error response from Slack during message posting:\n#{response.body}"
38
+ end
39
+ end
40
+
41
+ def self.raise_update_response_errors(response, message, profile)
42
+ body = JSON.parse(response.body)
43
+ error = body.fetch("error", "")
44
+
45
+ if ["invalid_blocks", "invalid_blocks_format"].include?(error)
46
+ raise SlackMessage::ApiError, "Couldn't update Slack message because the serialized message had an invalid format"
47
+ elsif error == "channel_not_found"
48
+ raise SlackMessage::ApiError, "Tried to update Slack message to non-existent channel or user '#{message.channel}'"
49
+
50
+ elsif error == "message_not_found"
51
+ raise SlackMessage::ApiError, "Tried to update Slack message, but the message wasn't found (timestamp '#{message.timestamp}' for channel '#{message.channel}'"
52
+ elsif error == "cant_update_message"
53
+ raise SlackMessage::ApiError, "Couldn't update message because the message type isn't able to be updated, or #{profile[:handle]} isn't allowed to update it"
54
+ elsif error == "edit_window_closed"
55
+ raise SlackMessage::ApiError, "Couldn't update message because it's too old"
56
+
57
+
58
+ elsif PERMISSIONS_ERRORS.include?(error)
59
+ raise SlackMessage::ApiError, "Couldn't update Slack message because the API key for profile '#{profile[:handle]}' is wrong, or the app has insufficient permissions (#{error})"
60
+ elsif error == "message_too_long"
61
+ raise SlackMessage::ApiError, "Tried to update Slack message, but the message was too long"
62
+ elsif error == "invalid_arguments"
63
+ raise SlackMessage::ApiError, "Tried to update Slack message with invalid payload"
64
+ elsif ["rate_limited", "ratelimited"].include?(error)
65
+ raise SlackMessage::ApiError, "Couldn't update Slack message because you've reached your rate limit"
66
+ elsif response.code == "302"
67
+ raise SlackMessage::ApiError, "Got 302 response while updating a message. Check your API key for profile '#{profile[:handle]}'"
68
+ elsif response.code != "200"
69
+ raise SlackMessage::ApiError, "Got an error back from the Slack API (HTTP #{response.code}):\n#{response.body}"
70
+ elsif !(error.nil? || error == "")
71
+ raise SlackMessage::ApiError, "Received error response from Slack during message update:\n#{response.body}"
72
+ end
73
+ end
74
+
75
+ def self.raise_delete_response_errors(response, message, profile)
76
+ body = JSON.parse(response.body)
77
+ error = body.fetch("error", "")
78
+
79
+ if error == "channel_not_found"
80
+ raise SlackMessage::ApiError, "Tried to delete Slack message in non-existent channel '#{message.channel}'"
81
+
82
+ elsif error == "invalid_scheduled_message_id"
83
+ raise SlackMessage::ApiError, "Can't delete message because the ID was invalid, or the message has already posted (#{message.scheduled_message_id})"
84
+ elsif error == "message_not_found"
85
+ raise SlackMessage::ApiError, "Tried to delete Slack message, but the message wasn't found (timestamp '#{message.timestamp}' for channel '#{message.channel}')"
86
+ elsif error == "cant_delete_message"
87
+ raise SlackMessage::ApiError, "Can't delete message because '#{profile[:handle]}' doesn't have permission to"
88
+ elsif error == "compliance_exports_prevent_deletion"
89
+ raise SlackMessage::ApiError, "Can't delete message because team compliance settings prevent it"
90
+
91
+
92
+ elsif PERMISSIONS_ERRORS.include?(error)
93
+ raise SlackMessage::ApiError, "Couldn't delete Slack message because the API key for profile '#{profile[:handle]}' is wrong, or the app has insufficient permissions (#{error})"
94
+ elsif ["rate_limited", "ratelimited"].include?(error)
95
+ raise SlackMessage::ApiError, "Couldn't delete Slack message because you've reached your rate limit"
96
+ elsif response.code == "302"
97
+ raise SlackMessage::ApiError, "Got 302 response while deleting a message. Check your API key for profile '#{profile[:handle]}'"
98
+ elsif response.code != "200"
99
+ raise SlackMessage::ApiError, "Got an error back from the Slack API (HTTP #{response.code}):\n#{response.body}"
100
+ elsif !(error.nil? || error == "")
101
+ raise SlackMessage::ApiError, "Received error response from Slack during message delete:\n#{response.body}"
102
+ end
103
+ end
104
+
105
+ def self.raise_user_lookup_response_errors(payload)
106
+ error = payload["error"]
107
+
108
+ if error == "users_not_found"
109
+ raise SlackMessage::ApiError, "Couldn't find a user with the email '#{email}'"
110
+
111
+
112
+ elsif PERMISSIONS_ERRORS.include?(error)
113
+ raise SlackMessage::ApiError, "Couldn't look up users because the API key for profile '#{profile[:handle]}' is wrong, or the app has insufficient permissions (#{error})"
114
+ elsif error
115
+ raise SlackMessage::ApiError, "Received error response from Slack during user lookup:\n#{response.body}"
116
+ elsif response.code == "302"
117
+ raise SlackMessage::ApiError, "Got 302 response during user lookup. Check your API key for profile '#{profile[:handle]}'"
118
+ elsif response.code != "200"
119
+ raise SlackMessage::ApiError, "Got an error back from the Slack API (HTTP #{response.code}):\n#{response.body}"
120
+ elsif !(error.nil? || error == "")
121
+ raise SlackMessage::ApiError, "Received error response from Slack during user lookup:\n#{response.body}"
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,42 @@
1
+ class SlackMessage::Response
2
+ attr_reader :channel, :timestamp, :profile_handle, :scheduled_message_id, :original_response
3
+
4
+ def initialize(api_response, profile_handle)
5
+ @original_response = JSON.parse(api_response.body)
6
+ @ok = @original_response["ok"]
7
+ @channel = @original_response["channel"]
8
+
9
+ @timestamp = @original_response["ts"]
10
+ @scheduled_message_id = @original_response["scheduled_message_id"]
11
+
12
+ @profile_handle = profile_handle
13
+ end
14
+
15
+ def marshal_dump
16
+ [ @profile_handle, @channel, @timestamp, @original_response, @ok, @original_response ]
17
+ end
18
+
19
+ def marshal_load(data)
20
+ @profile_handle, @channel, @timestamp, @original_response, @ok, @original_response = data
21
+ end
22
+
23
+ def sent_to_user?
24
+ channel =~ /^D.*/ # users are D for DM, channels start w/ C
25
+ end
26
+
27
+ def scheduled?
28
+ !!scheduled_message_id
29
+ end
30
+
31
+ def inspect
32
+ identifier = if scheduled?
33
+ "scheduled_message_id=#{scheduled_message_id}"
34
+ else
35
+ "timestamp=#{timestamp}"
36
+ end
37
+
38
+ ok_msg = @ok ? "ok" : "error"
39
+
40
+ "<SlackMessage::Response #{ok_msg} profile_handle=:#{profile_handle} channel=#{channel} #{identifier}>"
41
+ end
42
+ end
@@ -14,10 +14,15 @@ require 'rspec/mocks'
14
14
  # it can be cleaned up properly.
15
15
  #
16
16
 
17
+ # TODO: test helpers for scheduled messages, editing and deleting, and
18
+ # notification text. And realistically, overhaul all this.
19
+
17
20
  module SlackMessage::RSpec
18
21
  extend RSpec::Matchers::DSL
19
22
 
20
23
  @@listeners = []
24
+ @@custom_response = {}
25
+ @@response_code = '200'
21
26
 
22
27
  def self.register_expectation_listener(expectation_instance)
23
28
  @@listeners << expectation_instance
@@ -27,6 +32,11 @@ module SlackMessage::RSpec
27
32
  @@listeners.delete(expectation_instance)
28
33
  end
29
34
 
35
+ def self.reset_custom_responses
36
+ @@custom_response = {}
37
+ @@response_code = '200'
38
+ end
39
+
30
40
  FauxResponse = Struct.new(:code, :body)
31
41
 
32
42
  def self.included(_)
@@ -36,22 +46,24 @@ module SlackMessage::RSpec
36
46
  listener.record_call(params.merge(profile: profile))
37
47
  end
38
48
 
39
- response = {"ok"=>true,
40
- "channel"=>"D12345678",
41
- "ts"=>"1635863996.002300",
42
- "message"=>
43
- {"type"=>"message", "subtype"=>"bot_message",
44
- "text"=>"foo",
45
- "ts"=>"1635863996.002300",
46
- "username"=>"SlackMessage",
47
- "icons"=>{"emoji"=>":successkid:"},
48
- "bot_id"=>"B1234567890",
49
- "blocks"=>
50
- [{"type"=>"section",
51
- "block_id"=>"hAh7",
52
- "text"=>{"type"=>"mrkdwn", "text"=>"foo", "verbatim"=>false}}]}}
53
-
54
- return FauxResponse.new('200', response.to_json)
49
+ response = {
50
+ "ok" => true,
51
+ "channel" => "C12345678",
52
+ "ts" => "1635863996.002300",
53
+ "message" => { "type"=>"message", "subtype"=>"bot_message",
54
+ "text"=>"foo",
55
+ "ts"=>"1635863996.002300",
56
+ "username"=>"SlackMessage",
57
+ "icons"=>{"emoji"=>":successkid:"},
58
+ "bot_id"=>"B1234567890",
59
+ "blocks"=> [{"type"=>"section",
60
+ "block_id"=>"hAh7",
61
+ "text"=>{"type"=>"mrkdwn", "text"=>"foo", "verbatim"=>false}}
62
+ ]
63
+ }
64
+ }.merge(@@custom_response).to_json
65
+
66
+ return FauxResponse.new(@@response_code, response)
55
67
  end
56
68
 
57
69
  SlackMessage::Api.undef_method(:look_up_user_by_email)
@@ -61,6 +73,18 @@ module SlackMessage::RSpec
61
73
  end
62
74
  end
63
75
 
76
+ def self.respond_with(response = {}, code: '200')
77
+ raise ArgumentError, "custom response must be a hash" unless response.is_a? Hash
78
+
79
+ @@custom_response = response
80
+ @@response_code = code
81
+ end
82
+
83
+ def self.reset_mock_response
84
+ @@custom_response = {}
85
+ @@response_code = '200'
86
+ end
87
+
64
88
  # w/ channel
65
89
  matcher :post_slack_message_to do |expected|
66
90
  match do |actual|
data/lib/slack_message.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  module SlackMessage
2
+ require 'slack_message/response'
2
3
  require 'slack_message/dsl'
4
+ require 'slack_message/error_handling'
3
5
  require 'slack_message/api'
4
6
  require 'slack_message/configuration'
5
7
 
@@ -39,16 +41,46 @@ module SlackMessage
39
41
  raise ArgumentError, "Sorry, you need to specify a default_channel for profile #{profile_name} to use post_as"
40
42
  end
41
43
 
44
+ target = profile[:default_channel]
42
45
  payload = Dsl.new(block, profile).tap do |instance|
43
46
  instance.instance_eval(&block)
44
47
  end
45
48
 
46
- target = profile[:default_channel]
47
49
  target = Api::user_id_for(target, profile) if target =~ EMAIL_PATTERN
48
50
 
49
51
  Api.post(payload, target, profile, at)
50
52
  end
51
53
 
54
+ def self.update(message, &block)
55
+ unless message.is_a?(SlackMessage::Response)
56
+ raise ArgumentError, "You must pass in a SlackMessage::Response to update a message"
57
+ end
58
+
59
+ if message.scheduled?
60
+ raise ArgumentError, "Sorry, scheduled messages cannot be updated. You will need to delete the message and schedule a new one."
61
+ end
62
+
63
+ profile = Configuration.profile(message.profile_handle)
64
+ payload = Dsl.new(block, profile).tap do |instance|
65
+ instance.instance_eval(&block)
66
+ end
67
+
68
+ Api.update(payload, message, profile)
69
+ end
70
+
71
+ def self.delete(message)
72
+ unless message.is_a?(SlackMessage::Response)
73
+ raise ArgumentError, "You must pass in a SlackMessage::Response to delete a message"
74
+ end
75
+
76
+ if message.sent_to_user?
77
+ raise ArgumentError, "It's not possible to delete messages sent directly to users."
78
+ end
79
+
80
+ profile = Configuration.profile(message.profile_handle)
81
+ Api.delete(message, profile)
82
+ end
83
+
52
84
  def self.build(profile_name = :default, &block)
53
85
  profile = Configuration.profile(profile_name)
54
86
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = 'slack_message'
3
- gem.version = "2.4.0"
3
+ gem.version = "3.0.2"
4
4
  gem.summary = "A nice DSL for composing rich messages in Slack"
5
5
  gem.authors = ["Joe Mastey"]
6
6
  gem.email = 'hello@joemastey.com'
@@ -1,6 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe SlackMessage do
4
+
4
5
  describe "DSL" do
5
6
  describe "#build" do
6
7
  it "renders some JSON" do
@@ -49,6 +50,13 @@ RSpec.describe SlackMessage do
49
50
  end
50
51
  end
51
52
 
53
+ fit do
54
+ SlackMessage.build do
55
+ notification_text 'one'
56
+ notification_text 'two'
57
+ end
58
+ end
59
+
52
60
  it "can assert expectations against posts" do
53
61
  expect {
54
62
  SlackMessage.post_to('#lieutenant') { text "foo" }
@@ -111,10 +119,6 @@ RSpec.describe SlackMessage do
111
119
  }.to post_slack_message_with_icon_matching(/thisperson/)
112
120
  end
113
121
 
114
- it "lets you assert notification text" do
115
- # TODO :|
116
- end
117
-
118
122
  it "can assert more generally too tbh" do
119
123
  expect {
120
124
  SlackMessage.post_to('#general') { text "foo" }
@@ -123,8 +127,6 @@ RSpec.describe SlackMessage do
123
127
  end
124
128
 
125
129
  describe "API convenience" do
126
- let(:profile) { SlackMessage::Configuration.profile(:default) }
127
-
128
130
  before do
129
131
  SlackMessage.configure do |config|
130
132
  config.clear_profiles!
@@ -157,4 +159,58 @@ RSpec.describe SlackMessage do
157
159
  }.to post_to_slack.with_content_matching(/ABC123/)
158
160
  end
159
161
  end
162
+
163
+ describe "error handling" do
164
+ before do
165
+ SlackMessage.configure do |config|
166
+ config.clear_profiles!
167
+ config.add_profile(name: 'default profile', api_token: 'abc123')
168
+ config.add_profile(:schmoebot, name: 'Schmoe', api_token: 'abc123', icon: ':schmoebot:', default_channel: '#schmoes')
169
+ end
170
+ end
171
+
172
+ after do
173
+ SlackMessage::RSpec.reset_mock_response
174
+ end
175
+
176
+ it "raises nice error messages when API methods return errors" do
177
+ SlackMessage::RSpec.respond_with({'error' => 'nuffin'})
178
+
179
+ expect {
180
+ SlackMessage.post_to('#general') { text 'nuh uh' }
181
+ }.to raise_error(SlackMessage::ApiError)
182
+
183
+ expect {
184
+ SlackMessage.post_as(:schmoebot) { text 'nuh uh' }
185
+ }.to raise_error(SlackMessage::ApiError)
186
+ end
187
+
188
+ it "raises for redirects" do
189
+ SlackMessage::RSpec.respond_with(code: '302')
190
+
191
+ expect {
192
+ SlackMessage.post_to('#general') { text 'nuh uh' }
193
+ }.to raise_error(SlackMessage::ApiError)
194
+ end
195
+
196
+ it "raises errors w/ updates too" do
197
+ message = SlackMessage.post_to('#general') { text 'nuh uh' }
198
+
199
+ SlackMessage::RSpec.respond_with({'error' => 'bad choice'})
200
+
201
+ expect {
202
+ SlackMessage.update(message) { text 'nuh uh' }
203
+ }.to raise_error(SlackMessage::ApiError)
204
+ end
205
+
206
+ it "even raises errors during deletes" do
207
+ message = SlackMessage.post_to('#general') { text 'nuh uh' }
208
+
209
+ SlackMessage::RSpec.respond_with({'error' => 'bad choice'})
210
+
211
+ expect {
212
+ SlackMessage.delete(message) { text 'nuh uh' }
213
+ }.to raise_error(SlackMessage::ApiError)
214
+ end
215
+ end
160
216
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slack_message
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 3.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Mastey
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-13 00:00:00.000000000 Z
11
+ date: 2022-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -66,10 +66,21 @@ files:
66
66
  - Gemfile
67
67
  - MIT-LICENSE
68
68
  - README.md
69
+ - docs/01_configuration.md
70
+ - docs/02_posting_a_message.md
71
+ - docs/03_message_dsl.md
72
+ - docs/04_editing_messages.md
73
+ - docs/05_deleting_messages.md
74
+ - docs/06_notifying_users.md
75
+ - docs/07_testing.md
76
+ - docs/_config.yml
77
+ - docs/index.md
69
78
  - lib/slack_message.rb
70
79
  - lib/slack_message/api.rb
71
80
  - lib/slack_message/configuration.rb
72
81
  - lib/slack_message/dsl.rb
82
+ - lib/slack_message/error_handling.rb
83
+ - lib/slack_message/response.rb
73
84
  - lib/slack_message/rspec.rb
74
85
  - slack_message.gemspec
75
86
  - spec/slack_message_spec.rb