slack_message 1.7.1 → 1.8.0

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
  SHA256:
3
- metadata.gz: f3438c93abd1488bafc0ee9f33df94674290b68bd94110e8f2e601d95d3254bc
4
- data.tar.gz: 5eee7e715e66042ab6c3ccbc47eedba3e2ddddacd327e1096e3a2d3476b076b0
3
+ metadata.gz: 455886af2c6e775c37db510da7d5003abd131711107e9a18af2e10a714f9c154
4
+ data.tar.gz: '029d322491f3e63df60cd61eb2c6528132cce722a4ca0fa2db47fd790702fa04'
5
5
  SHA512:
6
- metadata.gz: ddc5ace3b66e6977b164accfeec16c67450ed8fbd182939e85aa1d56c251319f203c4527d75d410c2858bbfa7540889a83ed08aed12890488944077edf1867ed
7
- data.tar.gz: 16601f240ee826b8cadbd03429b5fd431ba21a5b159c1ca3c70932da362b54388c32115544bf782c45f9e2b1c603801d82e2fd6827e7020abfcaed18669601ee
6
+ metadata.gz: dd4bc35189956140e5409d1d2e325e2cb6b9423e23fbcb6f81399281b10e4447b8c1bed8e8447f7dac59b5282e9c39b4907231225f0858abe6116fe9419b9269
7
+ data.tar.gz: d91718d74c17d0b1c79485de6311a70a579b1f80916c4328afa813800735b12d29e1069cfdc1721f1954839a6b55d25c0fa292ed41d02350ac0c1665a3475aa2
data/CHANGELOG.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.8.0] - 2021-10-07
6
+ - Added the ability to test in RSpec
7
+
5
8
  ## [1.7.1] - 2021-10-06
6
9
  - Fixed literally a syntax issue.
7
10
  - Fixed specs.
data/README.md CHANGED
@@ -214,6 +214,36 @@ SlackMessage.post_to('#general') do
214
214
  end
215
215
  ```
216
216
 
217
+ ### Testing
218
+
219
+ You can do some basic testing against SlackMessage, at least if you use RSpec!
220
+ You'll need to require and include the testing behavior like this, in your
221
+ spec_helper file:
222
+
223
+ ```ruby
224
+ require 'slack_message/rspec'
225
+
226
+ RSpec.configure do |config|
227
+ include SlackMessage::RSpec
228
+
229
+ # your other config
230
+ end
231
+ ```
232
+
233
+ This will stop API calls for posting messages, and will allow you access to
234
+ some custom matchers:
235
+
236
+ ```ruby
237
+ expect {
238
+ SlackMessage.post_to('#general') { text "foo" }
239
+ }.to post_slack_message_to('#general').with_content_matching(/foo/)
240
+ ```
241
+
242
+ Be forewarned, I'm frankly not that great at more complicated RSpec matchers,
243
+ so I'm guessing there are some bugs. Also, because the content of a message
244
+ gets turned into a complex JSON object, matching against content isn't capable
245
+ of very complicated regexes.
246
+
217
247
  Opinionated Stances
218
248
  ------------
219
249
 
@@ -45,9 +45,9 @@ class SlackMessage::Api
45
45
  channel: target,
46
46
  username: profile[:name],
47
47
  blocks: payload
48
- }.to_json
48
+ }
49
49
 
50
- response = Net::HTTP.post_form uri, { payload: params }
50
+ response = execute_post_form(uri, params, profile[:handle])
51
51
 
52
52
  # let's try to be helpful about error messages
53
53
  if response.body == "invalid_token"
@@ -64,4 +64,8 @@ class SlackMessage::Api
64
64
 
65
65
  response
66
66
  end
67
+
68
+ def self.execute_post_form(uri, params, _profile)
69
+ Net::HTTP.post_form uri, { payload: params.to_json }
70
+ end
67
71
  end
@@ -27,6 +27,10 @@ module SlackMessage::Configuration
27
27
 
28
28
  ###
29
29
 
30
+ def self.clear_profiles! # test harness, mainly
31
+ @@profiles = {}
32
+ end
33
+
30
34
  def self.add_profile(handle = :default, name:, url:, default_channel: nil)
31
35
  if @@profiles.include?(handle)
32
36
  warn "WARNING: Overriding profile '#{handle}' in SlackMessage config"
@@ -0,0 +1,108 @@
1
+ require 'rspec/expectations'
2
+ require 'rspec/mocks'
3
+
4
+ # Honestly, this code is what happens when you do not understand the RSpec
5
+ # custom expectation API really at all, but you really want to create your
6
+ # matcher. This code is soo baaad.
7
+
8
+ module SlackMessage::RSpec
9
+ extend RSpec::Matchers::DSL
10
+
11
+ @@listeners = []
12
+
13
+ def self.register_expectation_listener(expectation_instance)
14
+ @@listeners << expectation_instance
15
+ end
16
+
17
+ def self.unregister_expectation_listener(expectation_instance)
18
+ @@listeners.delete(expectation_instance)
19
+ end
20
+
21
+ FauxResponse = Struct.new(:code, :body)
22
+
23
+ def self.included(_)
24
+ SlackMessage::Api.singleton_class.undef_method(:execute_post_form)
25
+ SlackMessage::Api.define_singleton_method(:execute_post_form) do |uri, params, profile|
26
+ @@listeners.each do |listener|
27
+ listener.record_call(params.merge(profile: profile, uri: uri))
28
+ end
29
+
30
+ return FauxResponse.new('200', 'ok')
31
+ end
32
+ end
33
+
34
+ matcher :post_slack_message_to do |expected|
35
+ match do |actual|
36
+ @instance ||= PostTo.new
37
+ @instance.with_channel(expected)
38
+
39
+ actual.call
40
+ @instance.enforce_expectations
41
+ end
42
+
43
+ chain :with_content_matching do |content_expectation|
44
+ @instance ||= PostTo.new
45
+ @instance.with_content_matching(content_expectation)
46
+ end
47
+
48
+ failure_message { @instance.failure_message }
49
+ failure_message_when_negated { @instance.failure_message_when_negated }
50
+
51
+ supports_block_expectations
52
+ end
53
+
54
+ class PostTo
55
+ def initialize
56
+ @captured_calls = []
57
+ @content_expectation = nil
58
+ @channel = nil
59
+
60
+ SlackMessage::RSpec.register_expectation_listener(self)
61
+ end
62
+
63
+ def record_call(deets)
64
+ @captured_calls.push(deets)
65
+ end
66
+
67
+ def with_channel(channel)
68
+ @channel = channel
69
+ end
70
+
71
+ def with_content_matching(content_expectation)
72
+ raise ArgumentError unless content_expectation.is_a? Regexp
73
+ @content_expectation = content_expectation
74
+ end
75
+
76
+ def enforce_expectations
77
+ SlackMessage::RSpec.unregister_expectation_listener(self)
78
+ matching_messages.any? { |msg| body_matches_expectation?(msg.fetch(:blocks)) }
79
+ end
80
+
81
+ def matching_messages
82
+ @captured_calls.select { |c| c[:channel] == @channel }
83
+ end
84
+
85
+ def body_matches_expectation?(sent)
86
+ return true unless @content_expectation
87
+
88
+ sent.to_s =~ @content_expectation
89
+ end
90
+
91
+ def failure_message
92
+ if @content_expectation
93
+ "expected block to post slack message to '#{@channel}' with content matching #{@content_expectation.inspect}"
94
+ else
95
+ "expected block to post slack message to '#{@channel}'"
96
+ end
97
+ end
98
+
99
+ # TODO: does content_matching even make sense for negated test?
100
+ def failure_message_when_negated
101
+ if @content_expectation
102
+ "expected block not to post slack message to '#{@channel}' with content matching #{@content_expectation.inspect}"
103
+ else
104
+ "expected block not to post slack message to '#{@channel}'"
105
+ end
106
+ end
107
+ end
108
+ end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = 'slack_message'
3
- gem.version = "1.7.1"
3
+ gem.version = "1.8.0"
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,10 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe SlackMessage do
4
- it "includes a bunch of stuff" do
5
- expect(SlackMessage).to respond_to(:post_to)
6
- end
7
-
8
4
  describe "API convenience" do
9
5
  it "can grab user IDs" do
10
6
  SlackMessage.configure { |c| c.api_token = "asdf" }
@@ -72,4 +68,31 @@ RSpec.describe SlackMessage do
72
68
  }.to raise_error(ArgumentError)
73
69
  end
74
70
  end
71
+
72
+ describe "custom expectations" do
73
+ before do
74
+ SlackMessage.configure do |config|
75
+ config.clear_profiles!
76
+ config.add_profile(name: 'default profile', url: 'http://hooks.slack.com/1234/')
77
+ end
78
+ end
79
+
80
+ it "can assert expectations against posts" do
81
+ expect {
82
+ SlackMessage.post_to('#lieutenant') { text "foo" }
83
+ }.not_to post_slack_message_to('#general')
84
+
85
+ expect {
86
+ SlackMessage.post_to('#general') { text "foo" }
87
+ }.to post_slack_message_to('#general').with_content_matching(/foo/)
88
+ end
89
+
90
+ it "is not stateful" do
91
+ expect {
92
+ SlackMessage.post_to('#general') { text "foo" }
93
+ }.to post_slack_message_to('#general')
94
+
95
+ expect { }.not_to post_slack_message_to('#general')
96
+ end
97
+ end
75
98
  end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require_relative '../lib/slack_message'
2
+ require_relative '../lib/slack_message/rspec'
2
3
 
3
4
  # This file was generated by the `rspec --init` command. Conventionally, all
4
5
  # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
@@ -49,4 +50,6 @@ RSpec.configure do |config|
49
50
  # test failures related to randomization by passing the same `--seed` value
50
51
  # as the one that triggered the failure.
51
52
  Kernel.srand config.seed
53
+
54
+ include SlackMessage::RSpec
52
55
  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: 1.7.1
4
+ version: 1.8.0
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-10-06 00:00:00.000000000 Z
11
+ date: 2021-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -70,6 +70,7 @@ files:
70
70
  - lib/slack_message/api.rb
71
71
  - lib/slack_message/configuration.rb
72
72
  - lib/slack_message/dsl.rb
73
+ - lib/slack_message/rspec.rb
73
74
  - slack_message.gemspec
74
75
  - spec/slack_message_spec.rb
75
76
  - spec/spec_helper.rb