teams_connector 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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