karafka-testing 2.2.1 → 2.3.0

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: 073f7b386365e017596e6ad5d8c1f5753d72dab2eaf90c46504a4676f2690066
4
- data.tar.gz: c64a949126353354af0218ed81fc2ee0229fea1edbc3dacf08d129f495053929
3
+ metadata.gz: 7234ba09684afa8617cf8c3f335462e418dbe1369792949d189029f9ec22e40c
4
+ data.tar.gz: '0861af20657686d3f7b3b0f99453959df567eb2b91f5ba1e60c23416e272633a'
5
5
  SHA512:
6
- metadata.gz: eedf2b5d5ac5c5507f0e5ddf7c3a1f24efb729966c7de9e5f1ecc785f27a08a8fa16d38b8cd12aa5446ed3e5f94d2a3db3e71b675ce1ca250cad7b28635937b3
7
- data.tar.gz: 709de9d3f9f6d4351c5abd33c4c0a1888d680fb8159ca07f643bfe4153860e6ed290272cd7545a697b7eeaef4b754f446c945f40cef872413831aefa444c33ec
6
+ metadata.gz: a210c2545d78aa92c4b9fd554f7d9687268d39e9ccd86ca5ebe8f94de55a295226e5c10126e948b11a769695baecbfaee183aa2318a1ce9a3e8aa4f0e8136791
7
+ data.tar.gz: 1f6365ee9adec3023b077c073c74ed10e66271d00ebd656eeb54bc12f912a981583f3e10e113bff530fa3a4dc3994ee95d4b95e93347f7576d6efa186ee0ff7b
checksums.yaml.gz.sig CHANGED
Binary file
@@ -1,6 +1,8 @@
1
1
  name: ci
2
2
 
3
- concurrency: ci-${{ github.ref }}
3
+ concurrency:
4
+ group: ${{ github.workflow }}-${{ github.ref }}
5
+ cancel-in-progress: true
4
6
 
5
7
  on:
6
8
  pull_request:
@@ -16,28 +18,46 @@ jobs:
16
18
  fail-fast: false
17
19
  matrix:
18
20
  ruby:
19
- - '3.3.0-preview2'
21
+ - '3.3'
20
22
  - '3.2'
21
23
  - '3.1'
22
24
  - '3.0'
23
25
  - '2.7'
24
26
  include:
25
- - ruby: '3.2'
27
+ - ruby: '3.3'
26
28
  coverage: 'true'
27
29
  steps:
28
30
  - uses: actions/checkout@v4
31
+
29
32
  - name: Install package dependencies
30
33
  run: "[ -e $APT_DEPS ] || sudo apt-get install -y --no-install-recommends $APT_DEPS"
34
+
31
35
  - name: Set up Ruby
32
36
  uses: ruby/setup-ruby@v1
33
37
  with:
34
38
  ruby-version: ${{matrix.ruby}}
39
+ bundler: 'latest'
40
+
35
41
  - name: Install latest bundler
36
42
  run: |
37
- gem install bundler --no-document
43
+ if [[ "$(ruby -v | awk '{print $2}')" == 2.7.8* ]]; then
44
+ gem install bundler -v 2.4.22 --no-document
45
+ bundle config set version 2.4.22
46
+ gem update --system 3.4.22 --no-document
47
+ else
48
+ gem install bundler --no-document
49
+ gem update --system --no-document
50
+ fi
51
+
52
+ bundle config set without 'tools benchmarks docs'
53
+
38
54
  - name: Bundle install
39
55
  run: |
40
- bundle install --jobs 4 --retry 3
56
+ if [[ "$(ruby -v | awk '{print $2}')" == 2.7.8* ]]; then
57
+ BUNDLER_VERSION=2.4.22 bundle install --jobs 4 --retry 3
58
+ else
59
+ bundle install --jobs 4 --retry 3
60
+ fi
41
61
 
42
62
  diffend:
43
63
  runs-on: ubuntu-latest
@@ -47,14 +67,18 @@ jobs:
47
67
  - uses: actions/checkout@v4
48
68
  with:
49
69
  fetch-depth: 0
70
+
50
71
  - name: Set up Ruby
51
72
  uses: ruby/setup-ruby@v1
52
73
  with:
53
- ruby-version: 3.2
74
+ ruby-version: 3.3
75
+
54
76
  - name: Install latest bundler
55
77
  run: gem install bundler --no-document
78
+
56
79
  - name: Install Diffend plugin
57
80
  run: bundle plugin install diffend
81
+
58
82
  - name: Bundle Secure
59
83
  run: bundle secure
60
84
 
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.2
1
+ 3.3.0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Karafka Test gem changelog
2
2
 
3
+ ## 2.3.0 (2024-01-26)
4
+ - [Maintenance] Release matching Karafka `2.3.0` release.
5
+
6
+ ## 2.2.2 (2023-11-16)
7
+ - [**Feature**] Provide support for Minitest (ValentinoRusconi-EH)
8
+
3
9
  ## 2.2.1 (2023-10-26)
4
10
  - [Enhancement] Support patterns in `#consumer_for` consumer builder.
5
11
 
data/Gemfile.lock CHANGED
@@ -1,41 +1,37 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- karafka-testing (2.2.1)
5
- karafka (>= 2.2.0, < 3.0.0)
6
- waterdrop (>= 2.6.6)
4
+ karafka-testing (2.3.0)
5
+ karafka (>= 2.3.0, < 2.4.0)
6
+ waterdrop (>= 2.6.12)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- concurrent-ruby (1.2.2)
12
- ffi (1.15.5)
13
- karafka (2.2.0)
14
- karafka-core (>= 2.1.1, < 2.2.0)
15
- thor (>= 0.20)
16
- waterdrop (>= 2.6.6, < 3.0.0)
11
+ ffi (1.16.3)
12
+ karafka (2.3.0)
13
+ karafka-core (>= 2.3.0, < 2.4.0)
14
+ waterdrop (>= 2.6.12, < 3.0.0)
17
15
  zeitwerk (~> 2.3)
18
- karafka-core (2.1.1)
19
- concurrent-ruby (>= 1.1)
20
- karafka-rdkafka (>= 0.13.1, < 0.14.0)
21
- karafka-rdkafka (0.13.3)
16
+ karafka-core (2.3.0)
17
+ karafka-rdkafka (>= 0.14.8, < 0.15.0)
18
+ karafka-rdkafka (0.14.8)
22
19
  ffi (~> 1.15)
23
20
  mini_portile2 (~> 2.6)
24
21
  rake (> 12)
25
- mini_portile2 (2.8.1)
26
- rake (13.0.6)
27
- thor (1.2.1)
28
- waterdrop (2.6.6)
29
- karafka-core (>= 2.1.1, < 3.0.0)
22
+ mini_portile2 (2.8.5)
23
+ rake (13.1.0)
24
+ waterdrop (2.6.12)
25
+ karafka-core (>= 2.2.3, < 3.0.0)
30
26
  zeitwerk (~> 2.3)
31
- zeitwerk (2.6.7)
27
+ zeitwerk (2.6.12)
32
28
 
33
29
  PLATFORMS
34
- arm64-darwin
30
+ ruby
35
31
  x86_64-linux
36
32
 
37
33
  DEPENDENCIES
38
34
  karafka-testing!
39
35
 
40
36
  BUNDLED WITH
41
- 2.4.12
37
+ 2.5.5
@@ -24,8 +24,8 @@ Gem::Specification.new do |spec|
24
24
  spec.signing_key = File.expand_path('~/.ssh/gem-private_key.pem')
25
25
  end
26
26
 
27
- spec.add_dependency 'karafka', '>= 2.2.0', '< 3.0.0'
28
- spec.add_dependency 'waterdrop', '>= 2.6.6'
27
+ spec.add_dependency 'karafka', '>= 2.3.0', '< 2.4.0'
28
+ spec.add_dependency 'waterdrop', '>= 2.6.12'
29
29
 
30
30
  spec.metadata = {
31
31
  'funding_uri' => 'https://karafka.io/#become-pro',
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'karafka/testing/errors'
4
+ require 'karafka/testing/spec_consumer_client'
5
+ require 'karafka/testing/spec_producer_client'
6
+ require 'karafka/testing/minitest/proxy'
7
+
8
+ module Karafka
9
+ module Testing
10
+ # All the things related to extra functionalities needed to easier spec out
11
+ # Karafka things using Minitest
12
+ module Minitest
13
+ # Minitest helpers module that needs to be included
14
+ module Helpers
15
+ class << self
16
+ # Adds all the needed extra functionalities to the minitest group
17
+ # @param base [Class] Minitest example group we want to extend
18
+ def included(base)
19
+ base.class_eval do
20
+ setup do
21
+ @karafka = Karafka::Testing::Minitest::Proxy.new(self)
22
+ @_karafka_consumer_messages = []
23
+ @_karafka_consumer_client = Karafka::Testing::SpecConsumerClient.new
24
+ @_karafka_producer_client = Karafka::Testing::SpecProducerClient.new(self)
25
+
26
+ @_karafka_consumer_messages.clear
27
+ @_karafka_producer_client.reset
28
+
29
+ Karafka.producer.stubs(:client).returns(@_karafka_producer_client)
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ # Creates a consumer instance for a given topic
36
+ #
37
+ # @param requested_topic [String, Symbol] name of the topic for which we want to
38
+ # create a consumer instance
39
+ # @param requested_consumer_group [String, Symbol, nil] optional name of the consumer group
40
+ # if we have multiple consumer groups listening on the same topic
41
+ # @return [Object] Karafka consumer instance
42
+ # @raise [Karafka::Testing::Errors::TopicNotFoundError] raised when we're unable to find
43
+ # topic that was requested
44
+ #
45
+ # @example Creates a consumer instance with settings for `my_requested_topic`
46
+ # consumer = @karafka.consumer_for(:my_requested_topic)
47
+ def _karafka_consumer_for(requested_topic, requested_consumer_group = nil)
48
+ selected_topics = _karafka_consumer_find_candidate_topics(
49
+ requested_topic.to_s,
50
+ requested_consumer_group.to_s
51
+ )
52
+
53
+ raise Errors::TopicInManyConsumerGroupsError, requested_topic if selected_topics.size > 1
54
+ raise Errors::TopicNotFoundError, requested_topic if selected_topics.empty?
55
+
56
+ _karafka_build_consumer_for(selected_topics.first)
57
+ end
58
+
59
+ # Adds a new Karafka message instance if needed with given payload and options into an
60
+ # internal consumer buffer that will be used to simulate messages delivery to the consumer
61
+ #
62
+ # @param message [Hash] message that was sent to Kafka
63
+ #
64
+ # @example Send a json message to consumer
65
+ # @karafka.produce({ 'hello' => 'world' }.to_json)
66
+ #
67
+ # @example Send a json message to consumer and simulate, that it is partition 6
68
+ # @karafka.produce({ 'hello' => 'world' }.to_json, 'partition' => 6)
69
+ def _karafka_add_message_to_consumer_if_needed(message)
70
+ # Consumer needs to be defined in order to pass messages to it
71
+ return unless defined?(@consumer)
72
+ # We're interested in adding message to consumer only when it is a Karafka consumer
73
+ # Users may want to test other things (models producing messages for example) and in
74
+ # their case consumer will not be a consumer
75
+ return unless @consumer.is_a?(Karafka::BaseConsumer)
76
+ # We target to the consumer only messages that were produced to it, since specs may also
77
+ # produce other messages targeting other topics
78
+ return unless message[:topic] == @consumer.topic.name
79
+
80
+ # Build message metadata and copy any metadata that would come from the message
81
+ metadata = _karafka_message_metadata_defaults
82
+
83
+ metadata.keys.each do |key|
84
+ next unless message.key?(key)
85
+
86
+ metadata[key] = message.fetch(key)
87
+ end
88
+ # Add this message to previously produced messages
89
+ @_karafka_consumer_messages << Karafka::Messages::Message.new(
90
+ message[:payload],
91
+ Karafka::Messages::Metadata.new(metadata).freeze
92
+ )
93
+ # Update batch metadata
94
+ batch_metadata = Karafka::Messages::Builders::BatchMetadata.call(
95
+ @_karafka_consumer_messages,
96
+ @consumer.topic,
97
+ 0,
98
+ Time.now
99
+ )
100
+
101
+ # Update consumer messages batch
102
+ @consumer.messages = Karafka::Messages::Messages.new(
103
+ @_karafka_consumer_messages,
104
+ batch_metadata
105
+ )
106
+ end
107
+
108
+ # Produces message with a given payload to the consumer matching topic
109
+ # @param payload [String] payload we want to dispatch
110
+ # @param metadata [Hash] any metadata we want to dispatch alongside the payload
111
+ def _karafka_produce(payload, metadata = {})
112
+ Karafka.producer.produce_sync(
113
+ {
114
+ topic: @consumer.topic.name,
115
+ payload: payload
116
+ }.merge(metadata)
117
+ )
118
+ end
119
+
120
+ # @return [Array<Hash>] messages that were produced
121
+ def _karafka_produced_messages
122
+ @_karafka_producer_client.messages
123
+ end
124
+
125
+ private
126
+
127
+ # @return [Hash] message default options
128
+ def _karafka_message_metadata_defaults
129
+ {
130
+ deserializer: @consumer.topic.deserializer,
131
+ timestamp: Time.now,
132
+ headers: {},
133
+ key: nil,
134
+ offset: @_karafka_consumer_messages.size,
135
+ partition: 0,
136
+ received_at: Time.now,
137
+ topic: @consumer.topic.name
138
+ }
139
+ end
140
+
141
+ # Builds the consumer instance based on the provided topic
142
+ #
143
+ # @param topic [Karafka::Routing::Topic] topic for which we want to build the consumer
144
+ # @return [Object] karafka consumer
145
+ def _karafka_build_consumer_for(topic)
146
+ coordinators = Karafka::Processing::CoordinatorsBuffer.new(
147
+ Karafka::Routing::Topics.new([topic])
148
+ )
149
+ @consumer = topic.consumer.new
150
+ @consumer.producer = Karafka::App.producer
151
+ # Inject appropriate strategy so needed options and components are available
152
+ strategy = Karafka::App.config.internal.processing.strategy_selector.find(topic)
153
+ @consumer.singleton_class.include(strategy)
154
+ @consumer.client = @karafka_consumer_client
155
+ @consumer.coordinator = coordinators.find_or_create(topic.name, 0)
156
+ @consumer.coordinator.seek_offset = 0
157
+ # Indicate usage as for tests no direct enqueuing happens
158
+ @consumer.instance_variable_set('@used', true)
159
+ @consumer
160
+ end
161
+
162
+ # Finds all the routing topics matching requested topic within all topics or within
163
+ # provided consumer group based on name
164
+ #
165
+ # @param requested_topic [String] requested topic name
166
+ # @param requested_consumer_group [String] requested consumer group or nil to look in all
167
+ # @return [Array<Karafka::Routing::Topic>] all matching topics
168
+ #
169
+ # @note Since we run the lookup on subscription groups, the search will automatically
170
+ # expand with matching patterns
171
+ def _karafka_consumer_find_candidate_topics(requested_topic, requested_consumer_group)
172
+ _karafka_consumer_find_subscription_groups(requested_consumer_group)
173
+ .map(&:topics)
174
+ .filter_map do |topics|
175
+ topics.find(requested_topic.to_s)
176
+ rescue Karafka::Errors::TopicNotFoundError
177
+ nil
178
+ end
179
+ end
180
+
181
+ # Finds subscription groups from the requested consumer group or selects all if no
182
+ # consumer group specified
183
+ # @param requested_consumer_group [String] requested consumer group or nil to look in all
184
+ # @return [Array<Karafka::Routing::SubscriptionGroup>] requested subscription groups
185
+ def _karafka_consumer_find_subscription_groups(requested_consumer_group)
186
+ if requested_consumer_group && !requested_consumer_group.empty?
187
+ ::Karafka::App
188
+ .subscription_groups
189
+ # Find matching consumer group
190
+ .find { |cg, _sgs| cg.name == requested_consumer_group.to_s }
191
+ # Raise error if not found
192
+ .tap { |cg| cg || raise(Errors::ConsumerGroupNotFound, requested_consumer_group) }
193
+ # Since lookup was on a hash, get the value, that is subscription groups
194
+ .last
195
+ else
196
+ ::Karafka::App
197
+ .subscription_groups
198
+ .values
199
+ .flatten
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Testing
5
+ module Minitest
6
+ # Proxy object for a nicer `karafka.` API within Minitest
7
+ # None other should be used by the end users
8
+ class Proxy
9
+ # @param minitest_example [Minitest::Test] minitest context
10
+ def initialize(minitest_example)
11
+ @minitest_example = minitest_example
12
+ end
13
+
14
+ # @param args Anything that the `#_karafka_consumer_for` accepts
15
+ def consumer_for(*args)
16
+ @minitest_example._karafka_consumer_for(*args)
17
+ end
18
+
19
+ # @param args Anything that `#_karafka_produce` accepts
20
+ def produce(*args)
21
+ @minitest_example._karafka_produce(*args)
22
+ end
23
+
24
+ # @return [Array<Hash>] messages produced via `Karafka#producer`
25
+ def produced_messages
26
+ @minitest_example._karafka_produced_messages
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -4,6 +4,6 @@
4
4
  module Karafka
5
5
  module Testing
6
6
  # Current version of gem. It should match Karafka framework version
7
- VERSION = '2.2.1'
7
+ VERSION = '2.3.0'
8
8
  end
9
9
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: karafka-testing
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
@@ -35,7 +35,7 @@ cert_chain:
35
35
  AnG1dJU+yL2BK7vaVytLTstJME5mepSZ46qqIJXMuWob/YPDmVaBF39TDSG9e34s
36
36
  msG3BiCqgOgHAnL23+CN3Rt8MsuRfEtoTKpJVcCfoEoNHOkc
37
37
  -----END CERTIFICATE-----
38
- date: 2023-10-26 00:00:00.000000000 Z
38
+ date: 2024-01-26 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: karafka
@@ -43,34 +43,34 @@ dependencies:
43
43
  requirements:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: 2.2.0
46
+ version: 2.3.0
47
47
  - - "<"
48
48
  - !ruby/object:Gem::Version
49
- version: 3.0.0
49
+ version: 2.4.0
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
54
  - - ">="
55
55
  - !ruby/object:Gem::Version
56
- version: 2.2.0
56
+ version: 2.3.0
57
57
  - - "<"
58
58
  - !ruby/object:Gem::Version
59
- version: 3.0.0
59
+ version: 2.4.0
60
60
  - !ruby/object:Gem::Dependency
61
61
  name: waterdrop
62
62
  requirement: !ruby/object:Gem::Requirement
63
63
  requirements:
64
64
  - - ">="
65
65
  - !ruby/object:Gem::Version
66
- version: 2.6.6
66
+ version: 2.6.12
67
67
  type: :runtime
68
68
  prerelease: false
69
69
  version_requirements: !ruby/object:Gem::Requirement
70
70
  requirements:
71
71
  - - ">="
72
72
  - !ruby/object:Gem::Version
73
- version: 2.6.6
73
+ version: 2.6.12
74
74
  description: Library which provides helpers for easier Karafka consumers tests
75
75
  email:
76
76
  - contact@karafka.io
@@ -97,6 +97,8 @@ files:
97
97
  - lib/karafka-testing.rb
98
98
  - lib/karafka/testing.rb
99
99
  - lib/karafka/testing/errors.rb
100
+ - lib/karafka/testing/minitest/helpers.rb
101
+ - lib/karafka/testing/minitest/proxy.rb
100
102
  - lib/karafka/testing/rspec/helpers.rb
101
103
  - lib/karafka/testing/rspec/proxy.rb
102
104
  - lib/karafka/testing/spec_consumer_client.rb
@@ -129,7 +131,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
131
  - !ruby/object:Gem::Version
130
132
  version: '0'
131
133
  requirements: []
132
- rubygems_version: 3.4.19
134
+ rubygems_version: 3.5.3
133
135
  signing_key:
134
136
  specification_version: 4
135
137
  summary: Library which provides helpers for easier Karafka consumers tests
metadata.gz.sig CHANGED
Binary file