teams_connector 0.1.5 → 0.1.6

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: 9ed38230a562264b9117ecea0aef7cd66b1bb7d947056f5b892e88cfaed906af
4
- data.tar.gz: e3d01cfa5b8de620938e3f8bbd0c012591dc1ecbaf5b9dc742b03801b20c4d00
3
+ metadata.gz: ec351030eb8a9eb02df72d9807fec0ebb3040bb08fa2046182de96ccc01f0523
4
+ data.tar.gz: 54c5be1eeccab5fc6f0b34f0a226c896d1f96c9902d662c1c99cf88844216f4a
5
5
  SHA512:
6
- metadata.gz: 683b6a1095609d9f13263c71d7d17c4c466bd3041c334675985d13d4f2e9fd6f9b484354f21779c07b1ea4574fb11e3b10b6fae5e9d5f8fe9fdf2b34f72c27ea
7
- data.tar.gz: c0144642fff244b53410dc78f4f6f59570f6354af3f431c6d429878c2fd7c9af377edcafe55a020b08765e40db11bac5a64819321a350d4d1ed05d92379645f6
6
+ metadata.gz: b2e9831c57a4961021faae608a4e2ee0b1752ad4b2ca05adc974a8ac44421ae30175217bfc3705b0810918aef694b4ac1e1323a0ad7945b79bdb313c061b77c3
7
+ data.tar.gz: c6935973c88bbdf258dbbcda1f5341209eca6ce53738579f95d3da64cbe8cbc28e7c4a499f7e21f14109a6c53d3eadc8c44f4ce5ef9359809f92c0aa6d1d5e0b
@@ -15,21 +15,18 @@ on:
15
15
 
16
16
  jobs:
17
17
  test:
18
-
19
18
  runs-on: ubuntu-latest
19
+ name: Ruby ${{ matrix.ruby-version }}
20
20
  strategy:
21
21
  matrix:
22
- ruby-version: ['2.6', '2.7', '3.0']
22
+ ruby-version: ['2.6', '2.7', '3.0', '3.2']
23
23
 
24
24
  steps:
25
- - uses: actions/checkout@v2
26
- - name: Set up Ruby
27
- # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
28
- # change this to (see https://github.com/ruby/setup-ruby#versioning):
29
- # uses: ruby/setup-ruby@v1
30
- uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
31
- with:
32
- ruby-version: ${{ matrix.ruby-version }}
33
- bundler-cache: true # runs 'bundle install' and caches installed gems automatically
34
- - name: Run tests
35
- run: bundle exec rake
25
+ - uses: actions/checkout@v3
26
+ - name: Set up Ruby
27
+ uses: ruby/setup-ruby@v1
28
+ with:
29
+ ruby-version: ${{ matrix.ruby-version }}
30
+ bundler-cache: true
31
+ - name: Run the default task
32
+ run: bundle exec rake
data/.rubocop.yml ADDED
@@ -0,0 +1,19 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ TargetRubyVersion: 2.6
4
+
5
+ Layout/LineLength:
6
+ Exclude:
7
+ - spec/**/*
8
+
9
+ Metrics/BlockLength:
10
+ Exclude:
11
+ - spec/**/*
12
+ - '*.gemspec'
13
+
14
+ Style/CaseEquality:
15
+ Exclude:
16
+ - lib/teams_connector/matchers/have_sent_notification_to.rb
17
+
18
+ Style/Documentation:
19
+ Enabled: false
data/CHANGES.md CHANGED
@@ -1,26 +1,28 @@
1
1
  # Teams Connector Changelog
2
2
 
3
- 0.1.5
4
- ---
3
+ ## 0.1.6
4
+ - Enable Github actions for ruby 3
5
+ - Enable Rubocop linting
6
+ - Bump compatibility to sidekiq 7
7
+ - More stringent RuboCop tests
8
+ - Enable RubyGems MFA required
9
+
10
+ ## 0.1.5
5
11
  - RSpec Matchers for testing, thanks to [rspec-rails](https://github.com/rspec/rspec-rails) for their ActionCable `have_broadcasted_to` matcher as reference
6
12
  - README update for testing
7
13
  - Sometimes use testing mode internally
8
14
  - Fixed code smells
9
15
 
10
- 0.1.4
11
- ---
16
+ ## 0.1.4
12
17
  - Add rudimentary testing method
13
18
 
14
- 0.1.3
15
- ---
19
+ ## 0.1.3
16
20
  - Allow sending a notification to multiple channels at the same time
17
21
 
18
- 0.1.2
19
- ---
22
+ ## 0.1.2
20
23
  - Use `TeamsConnector::Configuration#load_from_rails_credentials` to load encrypted channel URLs in your Rails environment
21
24
 
22
- 0.1.1
23
- ---
25
+ ## 0.1.1
24
26
  - Adaptive Card Notification
25
27
  - Send a more complex Adaptive Card instead of the basic Message Card
26
28
  - Builder
@@ -35,7 +37,6 @@
35
37
  - Change constructor from numbered to named parameters
36
38
  - Pretty print JSON to STDOUT with #pretty_print
37
39
 
38
- 0.1.0
39
- ---
40
+ ## 0.1.0
40
41
  - Initial commit of the Teams Connector gem
41
42
  - Send messages as cards defined by JSON templates to configured Microsoft Teams channels
data/Gemfile CHANGED
@@ -1,6 +1,14 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ source 'https://rubygems.org'
4
4
 
5
5
  # Specify your gem's dependencies in teams_connector.gemspec
6
6
  gemspec
7
+
8
+ gem 'bundler', '>= 1.17'
9
+ gem 'rake', '>= 10.0'
10
+ gem 'rspec', '>= 3.0'
11
+ gem 'rubocop'
12
+ gem 'sidekiq', '< 8'
13
+ gem 'simplecov'
14
+ gem 'webmock'
data/README.md CHANGED
@@ -81,11 +81,11 @@ The default templates will be still available so you can mix and match.
81
81
 
82
82
  #### Default templates
83
83
 
84
- Template name | Description
85
- -----|-------
86
- :adaptive_card | A card with the body of an adaptive card for more complex scenarios
87
- :facts_card | A card with title, subtitle and a list of facts
88
- :test_card | A simple text message without any configurable content for testing
84
+ | Template name | Description |
85
+ |----------------|---------------------------------------------------------------------|
86
+ | :adaptive_card | A card with the body of an adaptive card for more complex scenarios |
87
+ | :facts_card | A card with title, subtitle and a list of facts |
88
+ | :test_card | A simple text message without any configurable content for testing |
89
89
 
90
90
  #### Custom Templates
91
91
 
@@ -125,25 +125,25 @@ The request elements have the following structure:
125
125
  ```
126
126
 
127
127
  ### RSpec Matcher
128
- TeamsConnector provides the `have_sent_notification_to(channel = nil, template = nil)` matcher for RSpec.
128
+ TeamsConnector provides the `sent_notification_to?(channel = nil, template = nil)` matcher for RSpec.
129
129
  It is available by adding `require "teams_connector/rspec"` to your `spec_helper.rb`.
130
130
  The matcher supports filtering notifications by channel and template. If one is not given, it does not filter the notifications by it.
131
- There exists the alias `send_notification_to` for `have_sent_notification_to`.
131
+ There exists the alias `send_notification_to` and `have_sent_notification_to` for `sent_notification_to?`.
132
132
 
133
133
  ```ruby
134
134
  it "has sent exactly one notification to the channel" do
135
- expect { notification.deliver_later }.to have_sent_notification_to(:channel)
135
+ expect { notification.deliver_later }.to sent_notification_to?(:channel)
136
136
  end
137
137
  ```
138
138
 
139
139
  #### Expecting number of notifications
140
- By default `have_sent_notification_to` expects exactly one matching notification.
140
+ By default `sent_notification_to?` expects exactly one matching notification.
141
141
  You can change the expected amount by chaining `exactly`, `at_least` or `at_most`.
142
142
 
143
143
  Example:
144
144
  ```ruby
145
145
  it "has sent less than 10 notifications to the channel" do
146
- expect { notification.deliver_later }.to have_sent_notification_to(:channel).at_most(10)
146
+ expect { notification.deliver_later }.to sent_notification_to?(:channel).at_most(10)
147
147
  end
148
148
  ```
149
149
 
@@ -163,7 +163,7 @@ Example:
163
163
  ```ruby
164
164
  expect {
165
165
  notification(:default, :test_card).deliver_later
166
- }.to have_sent_notification_to(:default).with { |content, notification|
166
+ }.to sent_notification_to?(:default).with { |content, notification|
167
167
  expect(notification[:channel]).to eq :default
168
168
  expect(notification[:template]).to eq :test_card
169
169
  expect(content["sections"]).to include(hash_including("activityTitle", "activitySubtitle", "facts", "markdown" => true))
data/Rakefile CHANGED
@@ -1,6 +1,12 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ require 'rubocop/rake_task'
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
data/bin/console CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "teams_connector"
4
+ require 'bundler/setup'
5
+ require 'teams_connector'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
@@ -11,26 +12,26 @@ require "teams_connector"
11
12
  # Pry.start
12
13
 
13
14
  TeamsConnector.configure do |config|
14
- if File.exist?("channels.yml")
15
+ if File.exist?('channels.yml')
15
16
  # NOTE(Keune): The channels available in the console can be set in the file channels.yml. It contains a simple
16
17
  # mapping of channel identifiers to webhook URLs. The channel identifier is loaded as a symbol.
17
18
  #
18
19
  # Example: default: "<INSERT YOUR WEBHOOK URL HERE>"
19
- puts "Load channels specified by file"
20
+ puts 'Load channels specified by file'
20
21
 
21
- require "yaml"
22
- channels = YAML.load_file "channels.yml"
22
+ require 'yaml'
23
+ channels = YAML.load_file 'channels.yml'
23
24
  channels.each do |k, v|
24
25
  config.channel k.to_sym, v
25
26
  end
26
27
  else
27
28
  # NOTE(Keune): Specify the channels you want to have available in the console
28
- config.channel :default, "<INSERT YOUR WEBHOOK URL HERE>"
29
+ config.channel :default, '<INSERT YOUR WEBHOOK URL HERE>'
29
30
  end
30
31
  config.default = :default
31
32
  config.always_use_default = true
32
33
  config.method = :direct
33
34
  end
34
35
 
35
- require "irb"
36
+ require 'irb'
36
37
  IRB.start(__FILE__)
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # NOTE(Keune): This core extension is taken directly from rails to support a single usage of #present?
4
+ # See rails/activesupport/lib/active_support/core_ext/object/blank.rb
5
+ class Object
6
+ # An object is blank if it's false, empty, or a whitespace string.
7
+ # For example, +nil+, '', ' ', [], {}, and +false+ are all blank.
8
+ #
9
+ # This simplifies
10
+ #
11
+ # !address || address.empty?
12
+ #
13
+ # to
14
+ #
15
+ # address.blank?
16
+ #
17
+ # @return [true, false]
18
+ def blank?
19
+ respond_to?(:empty?) ? !!empty? : false
20
+ end
21
+
22
+ # An object is present if it's not blank.
23
+ #
24
+ # @return [true, false]
25
+ def present?
26
+ !blank?
27
+ end
28
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TeamsConnector
2
4
  class Builder
3
5
  attr_accessor :type, :content
@@ -15,8 +17,8 @@ module TeamsConnector
15
17
  @content = text
16
18
  end
17
19
 
18
- def self.container
19
- TeamsConnector::Builder.new { |entry| entry.container { |items| yield items } }
20
+ def self.container(&block)
21
+ TeamsConnector::Builder.new { |entry| entry.container(&block) }
20
22
  end
21
23
 
22
24
  def container
@@ -25,8 +27,8 @@ module TeamsConnector
25
27
  yield @content
26
28
  end
27
29
 
28
- def self.facts
29
- TeamsConnector::Builder.new { |entry| entry.facts { |facts| yield facts } }
30
+ def self.facts(&block)
31
+ TeamsConnector::Builder.new { |entry| entry.facts(&block) }
30
32
  end
31
33
 
32
34
  def facts
@@ -38,23 +40,37 @@ module TeamsConnector
38
40
  def result
39
41
  case @type
40
42
  when :container
41
- {
42
- type: "Container",
43
- items: @content.map { |element| element.result }
44
- }
43
+ result_container
45
44
  when :facts
46
- {
47
- type: "FactSet",
48
- facts: @content.map { |fact| { title: fact[0], value: fact[1] } }
49
- }
45
+ result_facts
50
46
  when :text
51
- {
52
- type: "TextBlock",
53
- text: @content
54
- }
47
+ result_text
55
48
  else
56
49
  raise TypeError, "The type #{@type} is not supported by the TeamsConnector::Builder"
57
50
  end
58
51
  end
52
+
53
+ private
54
+
55
+ def result_container
56
+ {
57
+ type: 'Container',
58
+ items: @content.map(&:result)
59
+ }
60
+ end
61
+
62
+ def result_facts
63
+ {
64
+ type: 'FactSet',
65
+ facts: @content.map { |fact| { title: fact[0], value: fact[1] } }
66
+ }
67
+ end
68
+
69
+ def result_text
70
+ {
71
+ type: 'TextBlock',
72
+ text: @content
73
+ }
74
+ end
59
75
  end
60
76
  end
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TeamsConnector
2
4
  class Configuration
3
- DEFAULT_TEMPLATE_DIR = %w[templates teams_connector]
5
+ DEFAULT_TEMPLATE_DIR = %w[templates teams_connector].freeze
4
6
 
5
- attr_accessor :default, :channels, :always_use_default, :method, :template_dir, :color
7
+ attr_reader :default, :method
8
+ attr_accessor :channels, :always_use_default, :template_dir, :color
6
9
 
7
10
  def initialize
8
11
  @default = nil
@@ -10,28 +13,28 @@ module TeamsConnector
10
13
  @always_use_default = false
11
14
  @method = :direct
12
15
  @template_dir = DEFAULT_TEMPLATE_DIR
13
- @color = "3f95b5"
16
+ @color = '3f95b5'
14
17
  end
15
18
 
16
19
  def default=(channel)
17
20
  raise ArgumentError, "Desired default channel '#{channel}' is not configured" unless @channels.key?(channel)
21
+
18
22
  @default = channel
19
23
  end
20
24
 
21
25
  def method=(method)
22
- raise ArgumentError, "Method '#{method.to_s}' is not supported" unless [:direct, :sidekiq, :testing].include? method
23
- raise ArgumentError, "Sidekiq is not available" if method == :sidekiq && !defined? Sidekiq
26
+ raise ArgumentError, "Method '#{method}' is not supported" unless %i[direct sidekiq testing].include? method
27
+ raise ArgumentError, 'Sidekiq is not available' if method == :sidekiq && !defined? Sidekiq
28
+
24
29
  @method = method
25
30
  end
26
31
 
27
32
  def channel(name, url)
28
- @channels[name] = url;
33
+ @channels[name] = url
29
34
  end
30
35
 
31
36
  def load_from_rails_credentials
32
- unless defined? Rails
33
- raise RuntimeError, "This method is only available in Ruby on Rails."
34
- end
37
+ raise 'This method is only available in Ruby on Rails.' unless defined? Rails
35
38
 
36
39
  webhook_urls = Rails.application.credentials.teams_connector!
37
40
  webhook_urls.each do |entry|
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TeamsConnector
4
+ module Matchers
5
+ module ExpectedNumber
6
+ def exactly(count)
7
+ set_expected_number(:exactly, count)
8
+ self
9
+ end
10
+
11
+ def at_least(count)
12
+ set_expected_number(:at_least, count)
13
+ self
14
+ end
15
+
16
+ def at_most(count)
17
+ set_expected_number(:at_most, count)
18
+ self
19
+ end
20
+
21
+ def times
22
+ self
23
+ end
24
+
25
+ def once
26
+ exactly(:once)
27
+ end
28
+
29
+ def twice
30
+ exactly(:twice)
31
+ end
32
+
33
+ def thrice
34
+ exactly(:thrice)
35
+ end
36
+
37
+ private
38
+
39
+ def set_expected_number(relativity, count)
40
+ @expectation_type = relativity
41
+ @expected_number =
42
+ case count
43
+ when :once then 1
44
+ when :twice then 2
45
+ when :thrice then 3
46
+ else Integer(count)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,7 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'expected_number'
4
+ require_relative 'with'
5
+
1
6
  module TeamsConnector
2
7
  module Matchers
3
8
  class HaveSentNotificationTo
4
9
  include RSpec::Matchers::Composable
10
+ include TeamsConnector::Matchers::ExpectedNumber
11
+ include TeamsConnector::Matchers::With
12
+
13
+ class RelativityNotSupported < StandardError; end
5
14
 
6
15
  def initialize(channel, template)
7
16
  @filter = {
@@ -14,60 +23,17 @@ module TeamsConnector
14
23
  set_expected_number(:exactly, 1)
15
24
  end
16
25
 
17
- def with(data = nil, &block)
18
- @data = data
19
- @block = block if block
20
- self
21
- end
22
-
23
- def with_template(template = nil)
24
- @template_data = template
25
- self
26
- end
27
-
28
- def exactly(count)
29
- set_expected_number(:exactly, count)
30
- self
31
- end
32
-
33
- def at_least(count)
34
- set_expected_number(:at_least, count)
35
- self
36
- end
37
-
38
- def at_most(count)
39
- set_expected_number(:at_most, count)
40
- self
41
- end
42
-
43
- def times
44
- self
45
- end
46
-
47
- def once
48
- exactly(:once)
49
- end
50
-
51
- def twice
52
- exactly(:twice)
53
- end
54
-
55
- def thrice
56
- exactly(:thrice)
57
- end
58
-
59
26
  def failure_message
60
- "expected to send #{base_message}".tap do |msg|
61
- if @unmatching_ntfcts.any?
62
- msg << "\nSent notifications"
63
- msg << " to #{@filter[:channel]}" if @filter[:channel]
64
- msg << " of #{@filter[:template]}" if @filter[:template]
65
- msg << ":"
66
- @unmatching_ntfcts.each do |data|
67
- msg << "\n #{data}"
68
- end
69
- end
27
+ msg = "expected to send #{base_message}"
28
+ if @unmatching_ntfcts.any?
29
+ msg += "\nSent notifications"
30
+ msg += " to #{@filter[:channel]}" if @filter[:channel]
31
+ msg += " of #{@filter[:template]}" if @filter[:template]
32
+ msg += ':'
33
+ @unmatching_ntfcts.each { |data| msg += "\n #{data}" }
70
34
  end
35
+
36
+ msg
71
37
  end
72
38
 
73
39
  def failure_message_when_negated
@@ -75,19 +41,11 @@ module TeamsConnector
75
41
  end
76
42
 
77
43
  def matches?(expectation)
78
- if Proc === expectation
79
- original_count = TeamsConnector.testing.requests.size
80
- expectation.call
81
- in_block_notifications = TeamsConnector.testing.requests.drop(original_count)
82
- else
83
- in_block_notifications = expectation
44
+ matching_notifications = in_block_notifications(expectation).select do |msg|
45
+ @filter.map { |k, v| msg[k] == v unless v.nil? }.compact.all?
84
46
  end
85
47
 
86
- in_block_notifications = in_block_notifications.select { |msg|
87
- @filter.map { |k, v| msg[k] === v unless v.nil? }.compact.all?
88
- }
89
-
90
- check(in_block_notifications)
48
+ check(matching_notifications)
91
49
  end
92
50
 
93
51
  def supports_block_expectations?
@@ -98,56 +56,64 @@ module TeamsConnector
98
56
 
99
57
  def check(notifications)
100
58
  @matching_ntfcts, @unmatching_ntfcts = notifications.partition do |ntfct|
101
- result = true
59
+ check_partition(ntfct)
60
+ end
102
61
 
103
- result &= ntfct[:template] == @template_data unless @template_data.nil?
62
+ @matching_count = @matching_ntfcts.size
104
63
 
105
- decoded = JSON.parse(ntfct[:content])
106
- if @data.nil? || @data === decoded
107
- @block.call(decoded, ntfct)
108
- result &= true
109
- else
110
- result = false
111
- end
64
+ check_result
65
+ end
112
66
 
113
- result
114
- end
67
+ def check_partition(ntfct)
68
+ result = true
115
69
 
116
- @matching_count = @matching_ntfcts.size
70
+ result &= ntfct[:template] == @template_data unless @template_data.nil?
117
71
 
72
+ decoded = JSON.parse(ntfct[:content])
73
+ if @data.nil? || @data === decoded
74
+ @block.call(decoded, ntfct)
75
+ result & true
76
+ else
77
+ false
78
+ end
79
+ end
80
+
81
+ def check_result
118
82
  case @expectation_type
119
83
  when :exactly then @expected_number == @matching_count
120
84
  when :at_most then @expected_number >= @matching_count
121
85
  when :at_least then @expected_number <= @matching_count
86
+ else
87
+ raise RelativityNotSupported
122
88
  end
123
89
  end
124
90
 
125
- def set_expected_number(relativity, count)
126
- @expectation_type = relativity
127
- @expected_number =
128
- case count
129
- when :once then 1
130
- when :twice then 2
131
- when :thrice then 3
132
- else Integer(count)
133
- end
91
+ def in_block_notifications(expectation)
92
+ if expectation.is_a? Proc
93
+ original_count = TeamsConnector.testing.requests.size
94
+ expectation.call
95
+ TeamsConnector.testing.requests.drop(original_count)
96
+ else
97
+ expectation
98
+ end
134
99
  end
135
100
 
136
101
  def base_message
137
- "#{message_expectation_modifier} #{@expected_number} notifications".tap do |msg|
138
- msg << " to #{@filter[:channel]}" if @filter[:channel]
139
- msg << " of #{@filter[:template]}" if @filter[:template]
140
- msg << " with template #{@template_data}" if @template_data
141
- msg << " with content #{data_description(@data)}" if @data
142
- msg << ", but sent #{@matching_count}"
143
- end
102
+ msg = String("#{message_expectation_modifier} #{@expected_number} notifications")
103
+ msg += " to #{@filter[:channel]}" if @filter[:channel]
104
+ msg += " of #{@filter[:template]}" if @filter[:template]
105
+ msg += " with template #{@template_data}" if @template_data
106
+ msg += " with content #{data_description(@data)}" if @data
107
+ msg + ", but sent #{@matching_count}"
144
108
  end
145
109
 
146
110
  def message_expectation_modifier
147
111
  case @expectation_type
148
- when :exactly then "exactly"
149
- when :at_most then "at most"
150
- when :at_least then "at least"
112
+ when :exactly then 'exactly'
113
+ when :at_most then 'at most'
114
+ when :at_least then 'at least'
115
+ else
116
+ raise RelativityNotSupported
151
117
  end
152
118
  end
153
119
 
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TeamsConnector
4
+ module Matchers
5
+ module With
6
+ def with(data = nil, &block)
7
+ @data = data
8
+ @block = block if block
9
+ self
10
+ end
11
+
12
+ def with_template(template = nil)
13
+ @template_data = template
14
+ self
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,11 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'teams_connector/matchers/have_sent_notification_to'
2
4
 
3
5
  module TeamsConnector
4
6
  module Matchers
5
- def have_sent_notification_to(channel = nil, template = nil)
7
+ def sent_notification_to?(channel = nil, template = nil)
6
8
  HaveSentNotificationTo.new(channel, template)
7
9
  end
8
10
 
9
- alias_method :send_notification_to, :have_sent_notification_to
11
+ alias have_sent_notification_to sent_notification_to?
12
+ alias send_notification_to have_sent_notification_to
10
13
  end
11
14
  end
@@ -1,15 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TeamsConnector
2
- class Notification::AdaptiveCard < Notification
3
- attr_accessor :content
4
+ class Notification
5
+ class AdaptiveCard < Notification
6
+ attr_accessor :content
4
7
 
5
- def initialize(template: :adaptive_card, content: {}, channel: TeamsConnector.configuration.default)
6
- super(template: template, channels: channel)
7
- if content.instance_of? TeamsConnector::Builder
8
- @content = {
9
- card: [content.result]
10
- }
11
- else
12
- @content = content
8
+ def initialize(template: :adaptive_card, content: {}, channel: TeamsConnector.configuration.default)
9
+ super(template: template, channels: channel)
10
+ @content =
11
+ if content.instance_of? TeamsConnector::Builder
12
+ {
13
+ card: [content.result]
14
+ }
15
+ else
16
+ content
17
+ end
13
18
  end
14
19
  end
15
20
  end
@@ -1,11 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TeamsConnector
2
- class Notification::Message < Notification
3
- attr_accessor :summary, :content
4
+ class Notification
5
+ class Message < Notification
6
+ attr_accessor :summary, :content
4
7
 
5
- def initialize(template, summary, content = {}, channel = TeamsConnector.configuration.default)
6
- super(template: template, channels: channel)
7
- @summary = summary
8
- @content = content
8
+ def initialize(template, summary, content = {}, channel = TeamsConnector.configuration.default)
9
+ super(template: template, channels: channel)
10
+ @summary = summary
11
+ @content = content
12
+ end
9
13
  end
10
14
  end
11
15
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'erb'
2
4
  require 'json'
3
5
  require 'net/http'
4
- require 'teams_connector/post_worker' if defined? Sidekiq
6
+ require 'teams_connector/post_job' if defined? Sidekiq
5
7
 
6
8
  module TeamsConnector
7
9
  class Notification
@@ -22,17 +24,7 @@ module TeamsConnector
22
24
 
23
25
  channels = TeamsConnector.configuration.always_use_default ? [TeamsConnector.configuration.default] : @channels
24
26
  channels.each do |channel|
25
- url = TeamsConnector.configuration.channels[channel]
26
- raise ArgumentError, "The Teams channel '#{channel}' is not available in the configuration." if url.nil?
27
-
28
- if TeamsConnector.configuration.method == :sidekiq
29
- TeamsConnector::PostWorker.perform_async(url, content)
30
- elsif TeamsConnector.configuration.method == :testing
31
- TeamsConnector.testing.perform_request channel, @template, content
32
- else
33
- response = Net::HTTP.post(URI(url), content, { "Content-Type" => "application/json" })
34
- response.value
35
- end
27
+ deliver_channel(channel, content)
36
28
  end
37
29
  end
38
30
 
@@ -48,11 +40,26 @@ module TeamsConnector
48
40
 
49
41
  private
50
42
 
51
- def find_template
52
- path = File.join(TeamsConnector::project_root, *TeamsConnector.configuration.template_dir, "#{@template.to_s}.json.erb")
53
- unless File.exist? path
54
- path = File.join(TeamsConnector::gem_root, *TeamsConnector::Configuration::DEFAULT_TEMPLATE_DIR, "#{@template.to_s}.json.erb")
43
+ def deliver_channel(channel, content)
44
+ url = TeamsConnector.configuration.channels[channel]
45
+ raise ArgumentError, "The Teams channel '#{channel}' is not available in the configuration." if url.nil?
46
+
47
+ case TeamsConnector.configuration.method
48
+ when :sidekiq then TeamsConnector::PostJob.perform_async(url, content)
49
+ when :testing then TeamsConnector.testing.perform_request channel, @template, content
50
+ else
51
+ response = Net::HTTP.post(URI(url), content, { 'Content-Type' => 'application/json' })
52
+ response.value
55
53
  end
54
+ end
55
+
56
+ def find_template
57
+ path = File.join(TeamsConnector.project_root, *TeamsConnector.configuration.template_dir, "#{@template}.json.erb")
58
+ return path if File.exist? path
59
+
60
+ path = File.join(TeamsConnector.gem_root,
61
+ *TeamsConnector::Configuration::DEFAULT_TEMPLATE_DIR,
62
+ "#{@template}.json.erb")
56
63
  raise ArgumentError, "The template '#{@template}' is not available." unless File.exist? path
57
64
 
58
65
  path
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'sidekiq/job'
5
+
6
+ module TeamsConnector
7
+ class PostJob
8
+ # === Includes ===
9
+ include Sidekiq::Job
10
+
11
+ def perform(url, content)
12
+ response = Net::HTTP.post(URI(url), content, { 'Content-Type' => 'application/json' })
13
+ response.value
14
+ end
15
+ end
16
+ end
@@ -1,4 +1,6 @@
1
- require "teams_connector/matchers"
1
+ # frozen_string_literal: true
2
+
3
+ require 'teams_connector/matchers'
2
4
 
3
5
  RSpec.configure do |config|
4
6
  config.include TeamsConnector::Matchers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TeamsConnector
2
4
  class Testing
3
5
  attr_reader :requests
@@ -7,7 +9,7 @@ module TeamsConnector
7
9
  end
8
10
 
9
11
  def perform_request(channel, template, content)
10
- @requests.push({channel: channel, content: content, template: template, time: Time.now})
12
+ @requests.push({ channel: channel, content: content, template: template, time: Time.now })
11
13
  end
12
14
  end
13
15
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TeamsConnector
2
- VERSION = "0.1.5"
4
+ VERSION = '0.1.6'
3
5
  end
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'core_ext/object'
1
4
  require 'teams_connector/configuration'
2
5
  require 'teams_connector/version'
3
6
  require 'teams_connector/notification'
@@ -7,7 +10,7 @@ require 'teams_connector/builder'
7
10
 
8
11
  module TeamsConnector
9
12
  class << self
10
- attr_accessor :configuration, :testing
13
+ attr_writer :configuration, :testing
11
14
  end
12
15
 
13
16
  def self.configuration
@@ -33,19 +36,18 @@ module TeamsConnector
33
36
  end
34
37
 
35
38
  def self.project_root
36
- if defined?(Rails)
37
- return Rails.root
38
- end
39
-
40
- if defined?(Bundler)
41
- return Bundler.root
42
- end
39
+ return Rails.root if defined?(Rails)
40
+ return Bundler.root if defined?(Bundler)
43
41
 
44
42
  Dir.pwd
45
43
  end
46
44
 
47
45
  def self.gem_root
48
- spec = Gem::Specification.find_by_name("teams_connector")
49
- spec.gem_dir rescue project_root
46
+ spec = Gem::Specification.find_by_name('teams_connector')
47
+ begin
48
+ spec.gem_dir
49
+ rescue NoMethodError
50
+ project_root
51
+ end
50
52
  end
51
53
  end
@@ -1,42 +1,30 @@
1
+ # frozen_string_literal: true
1
2
 
2
- lib = File.expand_path("../lib", __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "teams_connector/version"
3
+ require_relative 'lib/teams_connector/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "teams_connector"
6
+ spec.name = 'teams_connector'
8
7
  spec.version = TeamsConnector::VERSION
9
- spec.authors = ["Lucas Keune"]
10
- spec.email = ["lucas.keune@qurasoft.de"]
8
+ spec.required_ruby_version = '>= 2.6'
9
+ spec.authors = ['Lucas Keune']
10
+ spec.email = ['lucas.keune@qurasoft.de']
11
11
 
12
- spec.summary = %q{Simple connector to send messages and cards to Microsoft Teams channels}
13
- spec.description = %q{Send templated messages or adaptive cards to Microsoft Teams channels}
14
- spec.homepage = "https://github.com/Qurasoft/teams_connector"
15
- spec.license = "MIT"
12
+ spec.summary = 'Simple connector to send messages and cards to Microsoft Teams channels'
13
+ spec.description = 'Send templated messages or adaptive cards to Microsoft Teams channels'
14
+ spec.homepage = 'https://github.com/Qurasoft/teams_connector'
15
+ spec.license = 'MIT'
16
16
 
17
- # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
- # to allow pushing to a single host or delete this section to allow pushing to any host.
19
- if spec.respond_to?(:metadata)
20
- spec.metadata["homepage_uri"] = spec.homepage
21
- spec.metadata["source_code_uri"] = "https://github.com/Qurasoft/teams_connector"
22
- spec.metadata["changelog_uri"] = "https://github.com/Qurasoft/teams_connector/blob/main/CHANGES.md"
23
- else
24
- raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
25
- end
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+ spec.metadata['source_code_uri'] = 'https://github.com/Qurasoft/teams_connector'
19
+ spec.metadata['changelog_uri'] = 'https://github.com/Qurasoft/teams_connector/blob/main/CHANGES.md'
20
+ spec.metadata['rubygems_mfa_required'] = 'true'
26
21
 
27
22
  # Specify which files should be added to the gem when it is released.
28
23
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
29
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
24
+ spec.files = Dir.chdir(__dir__) do
30
25
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
31
26
  end
32
- spec.bindir = "exe"
33
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
34
- spec.require_paths = ["lib"]
35
-
36
- spec.add_development_dependency "bundler", ">= 1.17"
37
- spec.add_development_dependency "rake", ">= 10.0"
38
- spec.add_development_dependency "rspec", ">= 3.0"
39
- spec.add_development_dependency "webmock"
40
- spec.add_development_dependency "sidekiq"
41
- spec.add_development_dependency "simplecov"
27
+ spec.bindir = 'bin'
28
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
29
+ spec.require_paths = ['lib']
42
30
  end
metadata CHANGED
@@ -1,103 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: teams_connector
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucas Keune
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-08 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '1.17'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '1.17'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '10.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '10.0'
41
- - !ruby/object:Gem::Dependency
42
- name: rspec
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '3.0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '3.0'
55
- - !ruby/object:Gem::Dependency
56
- name: webmock
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: sidekiq
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: simplecov
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
11
+ date: 2023-12-01 00:00:00.000000000 Z
12
+ dependencies: []
97
13
  description: Send templated messages or adaptive cards to Microsoft Teams channels
98
14
  email:
99
15
  - lucas.keune@qurasoft.de
100
- executables: []
16
+ executables:
17
+ - ".gitignore"
18
+ - console
19
+ - setup
101
20
  extensions: []
102
21
  extra_rdoc_files: []
103
22
  files:
@@ -105,6 +24,7 @@ files:
105
24
  - ".github/workflows/ruby.yml"
106
25
  - ".gitignore"
107
26
  - ".rspec"
27
+ - ".rubocop.yml"
108
28
  - ".travis.yml"
109
29
  - CHANGES.md
110
30
  - Gemfile
@@ -114,15 +34,18 @@ files:
114
34
  - bin/.gitignore
115
35
  - bin/console
116
36
  - bin/setup
37
+ - lib/core_ext/object.rb
117
38
  - lib/teams_connector.rb
118
39
  - lib/teams_connector/builder.rb
119
40
  - lib/teams_connector/configuration.rb
120
41
  - lib/teams_connector/matchers.rb
42
+ - lib/teams_connector/matchers/expected_number.rb
121
43
  - lib/teams_connector/matchers/have_sent_notification_to.rb
44
+ - lib/teams_connector/matchers/with.rb
122
45
  - lib/teams_connector/notification.rb
123
46
  - lib/teams_connector/notification/adaptive_card.rb
124
47
  - lib/teams_connector/notification/message.rb
125
- - lib/teams_connector/post_worker.rb
48
+ - lib/teams_connector/post_job.rb
126
49
  - lib/teams_connector/rspec.rb
127
50
  - lib/teams_connector/testing.rb
128
51
  - lib/teams_connector/version.rb
@@ -137,6 +60,7 @@ metadata:
137
60
  homepage_uri: https://github.com/Qurasoft/teams_connector
138
61
  source_code_uri: https://github.com/Qurasoft/teams_connector
139
62
  changelog_uri: https://github.com/Qurasoft/teams_connector/blob/main/CHANGES.md
63
+ rubygems_mfa_required: 'true'
140
64
  post_install_message:
141
65
  rdoc_options: []
142
66
  require_paths:
@@ -145,14 +69,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
145
69
  requirements:
146
70
  - - ">="
147
71
  - !ruby/object:Gem::Version
148
- version: '0'
72
+ version: '2.6'
149
73
  required_rubygems_version: !ruby/object:Gem::Requirement
150
74
  requirements:
151
75
  - - ">="
152
76
  - !ruby/object:Gem::Version
153
77
  version: '0'
154
78
  requirements: []
155
- rubygems_version: 3.0.9
79
+ rubygems_version: 3.4.21
156
80
  signing_key:
157
81
  specification_version: 4
158
82
  summary: Simple connector to send messages and cards to Microsoft Teams channels
@@ -1,14 +0,0 @@
1
- require 'net/http'
2
- require 'sidekiq/worker'
3
-
4
- module TeamsConnector
5
- class PostWorker
6
- # === Includes ===
7
- include Sidekiq::Worker
8
-
9
- def perform(url, content)
10
- response = Net::HTTP.post(URI(url), content, { "Content-Type": "application/json" })
11
- response.value
12
- end
13
- end
14
- end