slack-messenger 2.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +7 -0
  2. data/lib/slack-messenger.rb +59 -0
  3. data/lib/slack-messenger/config.rb +43 -0
  4. data/lib/slack-messenger/payload_middleware.rb +24 -0
  5. data/lib/slack-messenger/payload_middleware/at.rb +36 -0
  6. data/lib/slack-messenger/payload_middleware/base.rb +34 -0
  7. data/lib/slack-messenger/payload_middleware/channels.rb +21 -0
  8. data/lib/slack-messenger/payload_middleware/format_attachments.rb +44 -0
  9. data/lib/slack-messenger/payload_middleware/format_message.rb +20 -0
  10. data/lib/slack-messenger/payload_middleware/stack.rb +50 -0
  11. data/lib/slack-messenger/util/escape.rb +16 -0
  12. data/lib/slack-messenger/util/http_client.rb +64 -0
  13. data/lib/slack-messenger/util/link_formatter.rb +81 -0
  14. data/lib/slack-messenger/version.rb +7 -0
  15. data/spec/end_to_end_spec.rb +95 -0
  16. data/spec/integration/ping_integration_test.rb +16 -0
  17. data/spec/lib/slack-messenger/config_spec.rb +71 -0
  18. data/spec/lib/slack-messenger/payload_middleware/at_spec.rb +25 -0
  19. data/spec/lib/slack-messenger/payload_middleware/base_spec.rb +76 -0
  20. data/spec/lib/slack-messenger/payload_middleware/channels_spec.rb +20 -0
  21. data/spec/lib/slack-messenger/payload_middleware/format_attachments_spec.rb +48 -0
  22. data/spec/lib/slack-messenger/payload_middleware/format_message_spec.rb +27 -0
  23. data/spec/lib/slack-messenger/payload_middleware/stack_spec.rb +119 -0
  24. data/spec/lib/slack-messenger/payload_middleware_spec.rb +33 -0
  25. data/spec/lib/slack-messenger/util/http_client_spec.rb +55 -0
  26. data/spec/lib/slack-messenger/util/link_formatter_spec.rb +155 -0
  27. data/spec/lib/slack-messenger_spec.rb +98 -0
  28. data/spec/spec_helper.rb +28 -0
  29. metadata +84 -0
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Slack::Messenger::PayloadMiddleware do
4
+ before(:each) do
5
+ @registry_backup = described_class.registry.dup
6
+ Slack::Messenger::PayloadMiddleware.send(:remove_instance_variable, :@registry)
7
+ end
8
+
9
+ after(:each) do
10
+ described_class.send(:remove_instance_variable, :@registry)
11
+ described_class.send(:instance_variable_set, :@registry, @registry_backup)
12
+ end
13
+
14
+ describe "::registry" do
15
+ it "returns a hash if nothing set" do
16
+ expect(described_class.registry).to eq({})
17
+ end
18
+
19
+ it "returns memoized version if already set" do
20
+ described_class.instance_variable_set(:@registry, "hodor")
21
+ expect(described_class.registry).to eq "hodor"
22
+ end
23
+ end
24
+
25
+ describe "::register" do
26
+ it "adds given class to key in registry" do
27
+ MyClass = Struct.new(:myclass)
28
+ described_class.register MyClass, :my_class
29
+
30
+ expect(described_class.registry[:my_class]).to eq MyClass
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Slack::Messenger::Util::HTTPClient do
4
+ describe "::post" do
5
+ it "initializes Util::HTTPClient with the given uri and params then calls" do
6
+ http_post_double = instance_double("Slack::Messenger::Util::HTTPClient")
7
+
8
+ expect(described_class)
9
+ .to receive(:new).with("uri", "params")
10
+ .and_return(http_post_double)
11
+ expect(http_post_double).to receive(:call)
12
+
13
+ described_class.post "uri", "params"
14
+ end
15
+
16
+ # http_post is really tested in the integration spec,
17
+ # where the internals are run through
18
+ end
19
+
20
+ describe "#initialize" do
21
+ it "allows setting of options for Net::HTTP" do
22
+ net_http_double = instance_double("Net::HTTP")
23
+ http_client = described_class.new URI.parse("http://example.com"),
24
+ http_options: { open_timeout: 5 }
25
+
26
+ allow(Net::HTTP).to receive(:new).and_return(net_http_double)
27
+ allow(net_http_double).to receive(:use_ssl=)
28
+ allow(net_http_double).to receive(:request).with(anything) do
29
+ Net::HTTPOK.new("GET", "200", "OK")
30
+ end
31
+
32
+ expect(net_http_double).to receive(:open_timeout=).with(5)
33
+
34
+ http_client.call
35
+ end
36
+ end
37
+
38
+ describe "#call" do
39
+ it "raises an error when the response is unsuccessful" do
40
+ net_http_double = instance_double("Net::HTTP")
41
+ http_client = described_class.new URI.parse("http://example.com"), {}
42
+ bad_request = Net::HTTPBadRequest.new("GET", "400", "Bad Request")
43
+
44
+ allow(bad_request).to receive(:body).and_return("something_bad")
45
+ allow(Net::HTTP).to receive(:new).and_return(net_http_double)
46
+ allow(net_http_double).to receive(:use_ssl=)
47
+ allow(net_http_double).to receive(:request).with(anything) do
48
+ bad_request
49
+ end
50
+
51
+ expect { http_client.call }.to raise_error(Slack::Messenger::APIError,
52
+ /something_bad \(HTTP Code 400\)/)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ # rubocop:disable Metrics/LineLength
5
+ RSpec.describe Slack::Messenger::Util::LinkFormatter do
6
+ describe "::format" do
7
+ it "formats html links" do
8
+ formatted = described_class.format("Hello World, enjoy <a href='http://example.com'>this</a>.")
9
+ expect(formatted).to include("<http://example.com|this>")
10
+ end
11
+
12
+ it "formats markdown links" do
13
+ formatted = described_class.format("Hello World, enjoy [this](http://example.com).")
14
+ expect(formatted).to include("<http://example.com|this>")
15
+ end
16
+
17
+ it "formats markdown links in brackets" do
18
+ formatted = described_class.format("Hello World, enjoy [[this](http://example.com) in brackets].")
19
+ expect(formatted).to eq("Hello World, enjoy [<http://example.com|this> in brackets].")
20
+ end
21
+
22
+ it "formats markdown links with no title" do
23
+ formatted = described_class.format("Hello World, enjoy [](http://example.com).")
24
+ expect(formatted).to include("<http://example.com>")
25
+ end
26
+
27
+ it "handles multiple html links" do
28
+ formatted = described_class.format("Hello World, enjoy <a href='http://example.com'>this</a><a href='http://example2.com'>this2</a>.")
29
+ expect(formatted).to include("<http://example.com|this>")
30
+ expect(formatted).to include("<http://example2.com|this2>")
31
+ end
32
+
33
+ it "handles multiple markdown links" do
34
+ formatted = described_class.format("Hello World, enjoy [this](http://example.com)[this2](http://example2.com).")
35
+ expect(formatted).to include("<http://example.com|this>")
36
+ expect(formatted).to include("<http://example2.com|this2>")
37
+ end
38
+
39
+ it "handles mixed html & markdown links" do
40
+ formatted = described_class.format("Hello World, enjoy [this](http://example.com)<a href='http://example2.com'>this2</a>.")
41
+ expect(formatted).to include("<http://example.com|this>")
42
+ expect(formatted).to include("<http://example2.com|this2>")
43
+ end
44
+
45
+ if "".respond_to? :scrub
46
+ context "when on ruby 2.1+ or have string-scrub installed" do
47
+ it "handles invalid unicode sequences" do
48
+ expect do
49
+ described_class.format("This sequence is invalid: \255")
50
+ end.not_to raise_error
51
+ end
52
+
53
+ it "replaces invalid unicode sequences with the unicode replacement character" do
54
+ formatted = described_class.format("\255")
55
+ expect(formatted).to eq "\uFFFD"
56
+ end
57
+ end
58
+ end
59
+
60
+ it "doesn't replace valid Japanese" do
61
+ formatted = described_class.format("こんにちは")
62
+ expect(formatted).to eq "こんにちは"
63
+ end
64
+
65
+ it "handles mailto links in markdown" do
66
+ formatted = described_class.format("[John](mailto:john@example.com)")
67
+ expect(formatted).to eq "<mailto:john@example.com|John>"
68
+ end
69
+
70
+ it "handles mailto links in html" do
71
+ formatted = described_class.format("<a href='mailto:john@example.com'>John</a>")
72
+ expect(formatted).to eq "<mailto:john@example.com|John>"
73
+ end
74
+
75
+ it "handles links with trailing parentheses" do
76
+ formatted = described_class.format("Hello World, enjoy [foo(bar)](http://example.com/foo(bar))<a href='http://example.com/bar(foo)'>bar(foo)</a>")
77
+ expect(formatted).to include("http://example.com/foo(bar)|foo(bar)")
78
+ expect(formatted).to include("http://example.com/bar(foo)|bar(foo)")
79
+ end
80
+
81
+ it "formats a number of differently formatted links" do
82
+ input_output = {
83
+ "Hello World, enjoy [this](http://example.com)." =>
84
+ "Hello World, enjoy <http://example.com|this>.",
85
+
86
+ "Hello World, enjoy [[this](http://example.com) in brackets]." =>
87
+ "Hello World, enjoy [<http://example.com|this> in brackets].",
88
+
89
+ "Hello World, enjoy ([this](http://example.com) in parens)." =>
90
+ "Hello World, enjoy (<http://example.com|this> in parens).",
91
+
92
+ "Hello World, enjoy ([this](http://example.com))." =>
93
+ "Hello World, enjoy (<http://example.com|this>).",
94
+
95
+ "Hello World, enjoy [](http://example.com)." =>
96
+ "Hello World, enjoy <http://example.com>.",
97
+
98
+ "Hello World, enjoy [link with query](http://example.com?foo=bar)." =>
99
+ "Hello World, enjoy <http://example.com?foo=bar|link with query>.",
100
+
101
+ "Hello World, enjoy [link with fragment](http://example.com/#foo-bar)." =>
102
+ "Hello World, enjoy <http://example.com/#foo-bar|link with fragment>.",
103
+
104
+ "Hello World, enjoy [link with parens](http://example.com/foo(bar)/baz)." =>
105
+ "Hello World, enjoy <http://example.com/foo(bar)/baz|link with parens>.",
106
+
107
+ "Hello World, enjoy [link with query](http://example.com/(parens)?foo=bar)." =>
108
+ "Hello World, enjoy <http://example.com/(parens)?foo=bar|link with query>.",
109
+
110
+ "Hello World, enjoy [link with parens](http://example.com/baz?bang=foo(bar))." =>
111
+ "Hello World, enjoy <http://example.com/baz?bang=foo(bar)|link with parens>.",
112
+
113
+ "Hello World, enjoy [link with fragment](http://example.com/(parens)#foo-bar)." =>
114
+ "Hello World, enjoy <http://example.com/(parens)#foo-bar|link with fragment>.",
115
+
116
+ "Hello World, enjoy [link with fragment](http://example.com/#foo-bar=(baz))." =>
117
+ "Hello World, enjoy <http://example.com/#foo-bar=(baz)|link with fragment>.",
118
+
119
+ "Hello World, enjoy [this](http://example.com?foo=bar)[this2](http://example2.com)." =>
120
+ "Hello World, enjoy <http://example.com?foo=bar|this><http://example2.com|this2>.",
121
+
122
+ "Hello World, enjoy [this](http://example.com?foo=bar) [this2](http://example2.com/#fragment)." =>
123
+ "Hello World, enjoy <http://example.com?foo=bar|this> <http://example2.com/#fragment|this2>.",
124
+
125
+ "Hello World, enjoy [this](http://example.com)<a href='http://example2.com'>this2</a>." =>
126
+ "Hello World, enjoy <http://example.com|this><http://example2.com|this2>.",
127
+
128
+ "Hello world, [John](mailto:john@example.com)." =>
129
+ "Hello world, <mailto:john@example.com|John>.",
130
+
131
+ "Hello World, enjoy [foo(bar)](http://example.com/foo(bar))<a href='http://example.com/bar(foo)'>bar(foo)</a>" =>
132
+ "Hello World, enjoy <http://example.com/foo(bar)|foo(bar)><http://example.com/bar(foo)|bar(foo)>"
133
+ }
134
+
135
+ input_output.each do |input, output|
136
+ expect(described_class.format(input)).to eq output
137
+ end
138
+ end
139
+
140
+ context "with a configured stack" do
141
+ it "only formats html if html is the only item in formats" do
142
+ formatted = described_class.format("Hello World, enjoy [this](http://example.com)<a href='http://example2.com'>this2</a>.", formats: [:html])
143
+ expect(formatted).to eq "Hello World, enjoy [this](http://example.com)<http://example2.com|this2>."
144
+ end
145
+ it "only formats markdown if markdown is the only item in formats" do
146
+ formatted = described_class.format("Hello World, enjoy [this](http://example.com)<a href='http://example2.com'>this2</a>.", formats: [:markdown])
147
+ expect(formatted).to eq "Hello World, enjoy <http://example.com|this><a href='http://example2.com'>this2</a>."
148
+ end
149
+ it "doesn't format if formats is empty" do
150
+ formatted = described_class.format("Hello World, enjoy [this](http://example.com)<a href='http://example2.com'>this2</a>.", formats: [])
151
+ expect(formatted).to eq "Hello World, enjoy [this](http://example.com)<a href='http://example2.com'>this2</a>."
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Slack::Messenger do
4
+ let(:mock_http) do
5
+ class_double("Slack::Messenger::Util::HTTPClient", post: :posted)
6
+ end
7
+
8
+ subject { described_class.new "http://example.com", http_client: mock_http }
9
+
10
+ describe "#initialize" do
11
+ it "sets the given hook_url to the endpoint URI" do
12
+ expect(subject.endpoint).to eq URI.parse("http://example.com")
13
+ end
14
+
15
+ it "sets the default_payload options" do
16
+ subject = described_class.new "http://example.com", channel: "foo"
17
+ expect(subject.config.defaults[:channel]).to eq "foo"
18
+ end
19
+
20
+ it "sets a custom http client" do
21
+ subject = described_class.new "http://example.com", http_client: mock_http
22
+ expect(subject.config.http_client).to eq mock_http
23
+ end
24
+
25
+ describe "when given a block" do
26
+ it "yields the config object" do
27
+ test_double = double("Slack::Messenger::Config", defaults: {}, middleware: [])
28
+ allow_any_instance_of(Slack::Messenger).to receive(:config).and_return(test_double)
29
+
30
+ expect(test_double).to receive(:test_init_method).with("foo")
31
+
32
+ described_class.new "http://example.com" do
33
+ test_init_method "foo"
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ describe "#ping" do
40
+ it "calls #post with the message as the text key in #post" do
41
+ subject = described_class.new "http://example.com"
42
+ expect(subject).to receive(:post).with text: "message"
43
+
44
+ subject.ping "message"
45
+ end
46
+ end
47
+
48
+ describe "#post" do
49
+ def messenger_with_defaults
50
+ mock_client = mock_http
51
+ described_class.new "http://example.com" do
52
+ defaults channel: "default",
53
+ user: "rocket"
54
+ http_client mock_client
55
+ end
56
+ end
57
+
58
+ it "uses the defaults set on initialization" do
59
+ subject = messenger_with_defaults
60
+
61
+ expect(mock_http).to receive(:post).with(
62
+ URI.parse("http://example.com"),
63
+ payload: '{"channel":"default","user":"rocket","text":"hello"}'
64
+ )
65
+
66
+ subject.post text: "hello"
67
+ end
68
+
69
+ it "allows overriding the set defaults" do
70
+ subject = messenger_with_defaults
71
+
72
+ expect(mock_http).to receive(:post).with(
73
+ URI.parse("http://example.com"),
74
+ payload: '{"channel":"new","user":"ship","text":"hello"}'
75
+ )
76
+
77
+ subject.post text: "hello", channel: "new", user: "ship"
78
+ end
79
+
80
+ it "calls the middleware stack with the payload" do
81
+ subject = messenger_with_defaults
82
+ stack = instance_double("Slack::Messenger::PayloadMiddleware::Stack")
83
+ subject.instance_variable_set(:@middleware, stack)
84
+
85
+ expect(stack).to receive(:call)
86
+ .with(channel: "default", user: "rocket")
87
+ .and_return([test: "stack"])
88
+
89
+ expect(mock_http).to receive(:post).with(
90
+ URI.parse("http://example.com"),
91
+ payload: '{"test":"stack"}'
92
+ )
93
+
94
+ responses = subject.post
95
+ expect(responses).to eq([:posted])
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rspec"
4
+ require "slack-messenger"
5
+ require "pry" if ENV["DEBUG"]
6
+
7
+ RSpec.configure do |config|
8
+ config.expect_with :rspec do |expectations|
9
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
10
+ end
11
+
12
+ config.mock_with :rspec do |mocks|
13
+ mocks.verify_doubled_constant_names = true
14
+ mocks.verify_partial_doubles = true
15
+ end
16
+
17
+ config.filter_run :focus
18
+ config.run_all_when_everything_filtered = true
19
+ config.disable_monkey_patching!
20
+
21
+ config.example_status_persistence_file_path = "spec/examples.txt"
22
+ config.warnings = ENV["DEBUG"] ? false : true
23
+
24
+ config.default_formatter = "doc" if config.files_to_run.one?
25
+
26
+ config.order = :random
27
+ Kernel.srand config.seed
28
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slack-messenger
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.3.3
5
+ platform: ruby
6
+ authors:
7
+ - Steven Sloan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-02-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: " A slim ruby wrapper for posting to slack webhooks "
14
+ email:
15
+ - stevenosloan@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/slack-messenger.rb
21
+ - lib/slack-messenger/config.rb
22
+ - lib/slack-messenger/payload_middleware.rb
23
+ - lib/slack-messenger/payload_middleware/at.rb
24
+ - lib/slack-messenger/payload_middleware/base.rb
25
+ - lib/slack-messenger/payload_middleware/channels.rb
26
+ - lib/slack-messenger/payload_middleware/format_attachments.rb
27
+ - lib/slack-messenger/payload_middleware/format_message.rb
28
+ - lib/slack-messenger/payload_middleware/stack.rb
29
+ - lib/slack-messenger/util/escape.rb
30
+ - lib/slack-messenger/util/http_client.rb
31
+ - lib/slack-messenger/util/link_formatter.rb
32
+ - lib/slack-messenger/version.rb
33
+ - spec/end_to_end_spec.rb
34
+ - spec/integration/ping_integration_test.rb
35
+ - spec/lib/slack-messenger/config_spec.rb
36
+ - spec/lib/slack-messenger/payload_middleware/at_spec.rb
37
+ - spec/lib/slack-messenger/payload_middleware/base_spec.rb
38
+ - spec/lib/slack-messenger/payload_middleware/channels_spec.rb
39
+ - spec/lib/slack-messenger/payload_middleware/format_attachments_spec.rb
40
+ - spec/lib/slack-messenger/payload_middleware/format_message_spec.rb
41
+ - spec/lib/slack-messenger/payload_middleware/stack_spec.rb
42
+ - spec/lib/slack-messenger/payload_middleware_spec.rb
43
+ - spec/lib/slack-messenger/util/http_client_spec.rb
44
+ - spec/lib/slack-messenger/util/link_formatter_spec.rb
45
+ - spec/lib/slack-messenger_spec.rb
46
+ - spec/spec_helper.rb
47
+ homepage: http://github.com/stevenosloan/slack-messenger
48
+ licenses:
49
+ - MIT
50
+ metadata: {}
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubygems_version: 3.0.3
67
+ signing_key:
68
+ specification_version: 4
69
+ summary: A slim ruby wrapper for posting to slack webhooks
70
+ test_files:
71
+ - spec/spec_helper.rb
72
+ - spec/integration/ping_integration_test.rb
73
+ - spec/lib/slack-messenger_spec.rb
74
+ - spec/lib/slack-messenger/config_spec.rb
75
+ - spec/lib/slack-messenger/util/http_client_spec.rb
76
+ - spec/lib/slack-messenger/util/link_formatter_spec.rb
77
+ - spec/lib/slack-messenger/payload_middleware/at_spec.rb
78
+ - spec/lib/slack-messenger/payload_middleware/format_attachments_spec.rb
79
+ - spec/lib/slack-messenger/payload_middleware/channels_spec.rb
80
+ - spec/lib/slack-messenger/payload_middleware/stack_spec.rb
81
+ - spec/lib/slack-messenger/payload_middleware/format_message_spec.rb
82
+ - spec/lib/slack-messenger/payload_middleware/base_spec.rb
83
+ - spec/lib/slack-messenger/payload_middleware_spec.rb
84
+ - spec/end_to_end_spec.rb