stenotype 0.1.15 → 0.1.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +42 -0
- data/lib/stenotype/adapters/test_adapter.rb +35 -0
- data/lib/stenotype/test/matchers.rb +145 -0
- data/lib/stenotype/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31a64803c8b2a343a441ce48a26d5b14e5aa55792d718fe2afb236f0589507ca
|
4
|
+
data.tar.gz: 999e4ae1554d49663ac4b8e8cecd94507cde51cfa494c28ebf21fab4240eb41a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a001057b435a76475cb49deb9a73601c2144a3468578d0a68f188ccad85598678a0b5909cd3f32f31b8b04bda42c284b8cb5d54b7423663a79beefb6afcaaf61
|
7
|
+
data.tar.gz: a3f20a7345504675073ad48b48fd3dfb73018bd3d65d1855a28e0224a61a1a9274aaf39bfa483de465b95a82915a616f7c9987986be28a7c3d1f2f1992f3c6d3
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -275,6 +275,48 @@ end
|
|
275
275
|
|
276
276
|
You do not have to manually register the context handler since it happens upon inheriting from `Stenotype::ContextHandlers::Base`
|
277
277
|
|
278
|
+
## Testing
|
279
|
+
|
280
|
+
Stenotype currently supports RSpec integration. To be able to test even emission you can use a predefined matcher by adding the following to spec helper:
|
281
|
+
|
282
|
+
```ruby
|
283
|
+
RSpec.configure do |config|
|
284
|
+
config.around(:each, type: :stenotype_event) do |example|
|
285
|
+
require 'stenotype/adapters/test_adapter'
|
286
|
+
|
287
|
+
config.include Stenotype::Test::Matchers
|
288
|
+
|
289
|
+
RSpec::Mocks.with_temporary_scope do
|
290
|
+
allow(Stenotype.config).to receive(:targets).and_return(Array.wrap(Stenotype::Adapters::TestAdapter.new))
|
291
|
+
example.run
|
292
|
+
allow(Stenotype.config).to receive(:targets).and_call_original
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
```
|
297
|
+
|
298
|
+
After adding the configuration you can use the matchers:
|
299
|
+
```ruby
|
300
|
+
class Example
|
301
|
+
include Stenotype::Emitter
|
302
|
+
|
303
|
+
def trigger
|
304
|
+
emit_event(:user_subscription)
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
RSpec.describe Stenotype::Emitter do
|
309
|
+
describe "POST #create" do
|
310
|
+
subject(:post) { Example.new.trigger }
|
311
|
+
|
312
|
+
it "emits a user_subscription event", type: :stenotype_event do
|
313
|
+
expect { post }.to emit_an_event(:user_subscription).
|
314
|
+
with_arguments_including({ uuid: "abcd" }).
|
315
|
+
exactly(1).times
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
```
|
278
320
|
|
279
321
|
## Development
|
280
322
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stenotype
|
4
|
+
module Adapters
|
5
|
+
class TestAdapter < Base
|
6
|
+
attr_reader :buffer
|
7
|
+
|
8
|
+
def initialize(*_)
|
9
|
+
@buffer = Array.new
|
10
|
+
super()
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# @param event_data {Sting} The data to be published
|
15
|
+
# @param additional_attrs {Hash} The list of additional event attributes
|
16
|
+
#
|
17
|
+
def publish(event_data, **additional_attrs)
|
18
|
+
buffer << parse(event_data)
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Clears the buffer
|
23
|
+
#
|
24
|
+
def flush!
|
25
|
+
buffer.clear
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def parse(event_data)
|
31
|
+
JSON.parse(event_data)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
module Stenotype
|
5
|
+
module Test
|
6
|
+
module Matchers
|
7
|
+
extend RSpec::Matchers::DSL
|
8
|
+
|
9
|
+
class DiffSizeMatchesExpectation
|
10
|
+
attr_reader :matching_events, :expected_count
|
11
|
+
|
12
|
+
def initialize(matching_events, expected_count)
|
13
|
+
@matching_events = matching_events
|
14
|
+
@expected_count = expected_count
|
15
|
+
end
|
16
|
+
|
17
|
+
def failure_message
|
18
|
+
"expected to see #{expected_count} event(s) but got #{matching_events.count} event(s)."
|
19
|
+
end
|
20
|
+
|
21
|
+
def matches?
|
22
|
+
matching_events.count == expected_count
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class EventHasExpectedArguments
|
27
|
+
attr_reader :matching_events, :expected_arguments
|
28
|
+
|
29
|
+
def initialize(matching_events, expected_arguments)
|
30
|
+
@matching_events = matching_events
|
31
|
+
@expected_arguments = stringify_keys(expected_arguments)
|
32
|
+
end
|
33
|
+
|
34
|
+
def matches?
|
35
|
+
return false if multiple_events?
|
36
|
+
|
37
|
+
(expected_arguments.to_a - matching_event.to_a).empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
def failure_message
|
41
|
+
if multiple_events?
|
42
|
+
"more than one event with given event name has been emitted. Can not match event arguments"
|
43
|
+
else
|
44
|
+
"expected to see all attributes from #{expected_arguments} to be included in event attributes but got #{matching_event}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def multiple_events?
|
51
|
+
matching_events.size > 1
|
52
|
+
end
|
53
|
+
|
54
|
+
def matching_event
|
55
|
+
matching_events.first
|
56
|
+
end
|
57
|
+
|
58
|
+
def stringify_keys(hash)
|
59
|
+
hash.transform_keys(&:to_s)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class EventEmitted
|
64
|
+
attr_reader :matching_events, :expected_event_name
|
65
|
+
|
66
|
+
def initialize(matching_events, expected_event_name)
|
67
|
+
@matching_events = matching_events
|
68
|
+
@expected_event_name = expected_event_name
|
69
|
+
end
|
70
|
+
|
71
|
+
def matches?
|
72
|
+
matching_events.any?
|
73
|
+
end
|
74
|
+
|
75
|
+
def failure_message
|
76
|
+
"expected to see a '#{expected_event_name}' event but got nothing"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
matcher :emit_an_event do |expected_event_name, *_|
|
81
|
+
supports_block_expectations
|
82
|
+
|
83
|
+
match do |emitting_event_block|
|
84
|
+
@emitting_event_block = emitting_event_block
|
85
|
+
|
86
|
+
partial_matchers << EventEmitted.new(matching_events, expected_event_name)
|
87
|
+
partial_matchers << EventHasExpectedArguments.new(matching_events, @arguments_should_include) if should_validate_events_count?
|
88
|
+
partial_matchers << DiffSizeMatchesExpectation.new(matching_events, @matching_events_count) if should_validate_attributes?
|
89
|
+
|
90
|
+
return first_failure.nil?
|
91
|
+
end
|
92
|
+
|
93
|
+
chain(:with_arguments_including) { |**args| @arguments_should_include = args }
|
94
|
+
chain(:exactly) { |times| @matching_events_count = times }
|
95
|
+
|
96
|
+
# noop for syntatic sugar
|
97
|
+
chain(:times) {}
|
98
|
+
chain(:time) {}
|
99
|
+
|
100
|
+
def matching_events
|
101
|
+
@matching_events ||= begin
|
102
|
+
buffer_before_emit = stenotype_event_buffer.dup
|
103
|
+
@emitting_event_block.call
|
104
|
+
buffer_after_emit = stenotype_event_buffer.dup
|
105
|
+
|
106
|
+
diff = buffer_after_emit - buffer_before_emit
|
107
|
+
diff.select { |event| event["name"] == expected_event_name.to_s }
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def partial_matchers
|
112
|
+
@partial_matchers ||= []
|
113
|
+
end
|
114
|
+
|
115
|
+
def first_failure
|
116
|
+
@first_failure ||= partial_matchers.detect { |matcher| !matcher.matches? }
|
117
|
+
end
|
118
|
+
|
119
|
+
failure_message do
|
120
|
+
return super() unless first_failure
|
121
|
+
|
122
|
+
first_failure.failure_message
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
def should_validate_events_count?
|
128
|
+
@matching_events_count.present?
|
129
|
+
end
|
130
|
+
|
131
|
+
def should_validate_attributes?
|
132
|
+
@arguments_should_include.present?
|
133
|
+
end
|
134
|
+
|
135
|
+
def stenotype_event_buffer
|
136
|
+
stenotype_event_target.buffer
|
137
|
+
end
|
138
|
+
|
139
|
+
def stenotype_event_target
|
140
|
+
Stenotype.config.targets.first
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/lib/stenotype/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stenotype
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.16
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roman Kapitonov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -268,6 +268,7 @@ files:
|
|
268
268
|
- lib/stenotype/adapters/base.rb
|
269
269
|
- lib/stenotype/adapters/google_cloud.rb
|
270
270
|
- lib/stenotype/adapters/stdout_adapter.rb
|
271
|
+
- lib/stenotype/adapters/test_adapter.rb
|
271
272
|
- lib/stenotype/at_exit.rb
|
272
273
|
- lib/stenotype/configuration.rb
|
273
274
|
- lib/stenotype/context_handlers.rb
|
@@ -283,6 +284,7 @@ files:
|
|
283
284
|
- lib/stenotype/frameworks/rails/action_controller.rb
|
284
285
|
- lib/stenotype/frameworks/rails/active_job.rb
|
285
286
|
- lib/stenotype/railtie.rb
|
287
|
+
- lib/stenotype/test/matchers.rb
|
286
288
|
- lib/stenotype/version.rb
|
287
289
|
- stenotype.gemspec
|
288
290
|
homepage: https://github.com/Freshly/stenotype
|