rspec-twirp 0.1.0 → 0.3.0

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: c2f0ca51df29824ba1c1f2d1944ca94119501b3ec6366d09144f077bd99c92f2
4
- data.tar.gz: 513bdae144ce76ecec652954cff14d3f8467037f6ec706ab67181be0ac036d61
3
+ metadata.gz: 7a9027f86450d9e045705304d1d8e590b51a733269938e83ca5ae098a90018d4
4
+ data.tar.gz: dca42845c93b814878cf24842320583ddf6dbce3b0d266cd897a58500cf31a31
5
5
  SHA512:
6
- metadata.gz: 4a4ebdce6d3d96826eca31484d1d4c22dc5b9e07fb109bea659315c5cfc7265f497f8d0a0bb498115e654ee139b232d6c6eb74bfd6da03a325a44411e636486c
7
- data.tar.gz: 4342593db5f6e34db3fb0c3829a04ff1b8bc5806960e6b0efb144f650c38b80b08559b7f1f1a616a1c36712e2fb4a1c9cb963e457accd9451ac1ad3a6314096f
6
+ metadata.gz: 98d362457d71269cf64bffa1fe0b1fe00e173fe68df88e12cf0af20aa1030d518e031415d005050209b070095c36a6eac454e1bdba740661a090ce3be90cfa15
7
+ data.tar.gz: a0923b782b8568198fb267cd1e3bc6192bb032b0a7e746be478a4e8d66317ccc81652487f6f3b442847c6c2946b2e398f25b60682c0cc6b1c794c556837d0978
@@ -1,30 +1,59 @@
1
1
  RSpec::Matchers.define :be_a_twirp_error do |*matchers, **meta_matcher|
2
2
  match do |actual|
3
- @fail_msg = "Expected #{actual} to be a Twirp::Error, found #{actual.class}"
3
+ @fail_msg = "Expected `#{actual}` to be a Twirp::Error, found: #{actual.class}"
4
4
  return false unless actual.is_a?(Twirp::Error)
5
5
 
6
- matchers.each do |matcher|
6
+ @expected = {}
7
+ @actual = {}
8
+
9
+ matched = matchers.all? do |matcher|
7
10
  case matcher
8
11
  when Symbol
9
12
  # match code
13
+ @expected[:code] = matcher
14
+ @actual[:code] = actual.code
10
15
 
11
16
  unless Twirp::Error.valid_code?(matcher)
12
17
  raise ArgumentError, "invalid error code: #{matcher.inspect}"
13
18
  end
14
19
 
15
- @fail_msg = "Expected #{actual} to have code: #{matcher.inspect}, found #{actual.code}"
16
- return false unless actual.code == matcher
20
+ @fail_msg = "Expected #{actual} to have code `#{matcher.inspect}`, found: #{actual.code.inspect}"
21
+ actual.code == matcher
22
+ when Integer
23
+ # match http status code
24
+
25
+ if code = Twirp::ERROR_CODES_TO_HTTP_STATUS.key(matcher)
26
+ @expected[:code] = code
27
+ @actual[:code] = actual.code
28
+
29
+ actual_status = Twirp::ERROR_CODES_TO_HTTP_STATUS[actual.code]
30
+
31
+ @fail_msg = "Expected #{actual} to have status #{matcher} / #{code.inspect}, found: #{actual_status} / #{actual.code.inspect}"
32
+ actual.code == code
33
+ else
34
+ raise ArgumentError, "invalid error status code: #{matcher}"
35
+ end
36
+ when Twirp::Error
37
+ # match instance
38
+ @expected = matcher.to_h
39
+ @actual = actual.to_h
40
+
41
+ @fail_msg = "Expected #{actual} to equal #{matcher}"
42
+ values_match?(matcher.to_h, actual.to_h)
17
43
  else
18
44
  # match msg
45
+ @expected[:msg] = matcher
46
+ @actual[:msg] = actual.msg
19
47
 
20
- @fail_msg = "Expected #{actual} to have msg: #{matcher.inspect}, found #{actual.msg}"
21
- return false unless values_match?(matcher, actual.msg)
48
+ @fail_msg = "Expected #{actual} to have msg #{matcher.inspect}, found: #{actual.msg.inspect}"
49
+ values_match?(matcher, actual.msg)
22
50
  end
23
51
  end
24
52
 
25
53
  # match meta
26
54
  unless meta_matcher.empty?
27
- @cur_match = { meta: meta_matcher }
55
+ @expected[:meta] = meta_matcher
56
+ @actual[:meta] = actual.meta
28
57
 
29
58
  # sanity check...values must be Strings or Regexp
30
59
  discrete_attrs = meta_matcher.transform_values do |attr|
@@ -33,10 +62,10 @@ RSpec::Matchers.define :be_a_twirp_error do |*matchers, **meta_matcher|
33
62
  actual.send(:validate_meta, discrete_attrs)
34
63
 
35
64
  @fail_msg = "Expected #{actual} to have meta: #{meta_matcher.inspect}, found #{actual.meta}"
36
- return false unless values_match?(meta_matcher, actual.meta)
65
+ matched &= values_match?(meta_matcher, actual.meta)
37
66
  end
38
67
 
39
- true
68
+ matched
40
69
  end
41
70
 
42
71
  description do
@@ -44,6 +73,12 @@ RSpec::Matchers.define :be_a_twirp_error do |*matchers, **meta_matcher|
44
73
  end
45
74
 
46
75
  failure_message { @fail_msg }
76
+
77
+ diffable
78
+
79
+ def expected
80
+ @expected
81
+ end
47
82
  end
48
83
 
49
84
  RSpec::Matchers.alias_matcher :a_twirp_error, :be_a_twirp_error
@@ -0,0 +1,2 @@
1
+ RSpec::Matchers.alias_matcher :be_a_twirp_message, :be_a_protobuf
2
+ RSpec::Matchers.alias_matcher :a_twirp_message, :a_protobuf
@@ -1,34 +1,36 @@
1
- RSpec::Matchers.define :be_a_twirp_response do |type = nil, **attrs|
2
- match do |actual|
3
- # ensure type is a valid twirp response type
4
- if type && !(type < Google::Protobuf::MessageExts)
5
- raise ArgumentError, "Expected `type` to be a Twirp response, found: #{type}"
6
- end
7
-
8
- @fail_msg = "Expected a Twirp response, found #{actual}"
9
- return false unless actual.is_a?(Google::Protobuf::MessageExts)
1
+ RSpec::Matchers.define :be_a_twirp_response do |**attrs|
2
+ chain :with_error do |*matchers, **meta_matchers|
3
+ # code, msg, meta
4
+ @with_error = [ matchers, meta_matchers ]
5
+ end
10
6
 
11
- # match expected response type
12
- @fail_msg = "Expected a Twirp response of type #{type}, found #{actual.class}"
13
- return false if type && actual.class != type
7
+ match do |actual|
8
+ @fail_msg = "Expected a Twirp::ClientResp, found #{actual}"
9
+ return false unless actual.is_a?(Twirp::ClientResp)
14
10
 
15
- return true if attrs.empty?
11
+ if @with_error
12
+ unless attrs.empty?
13
+ raise ArgumentError, "match data attributes or error, but not both"
14
+ end
16
15
 
17
- RSpec::Twirp.validate_types(attrs, actual.class)
16
+ @fail_msg = "Expected #{actual} to have an error, but found none"
17
+ return false unless actual.error
18
18
 
19
- # match attributes which are present
20
- attrs.each do |attr_name, expected_attr|
21
- actual_attr = actual.send(attr_name)
19
+ matchers, meta_matchers = @with_error
20
+ expect(actual.error).to be_a_twirp_error(*matchers, **meta_matchers)
21
+ else
22
+ @fail_msg = "Expected #{actual} to have data, but found none"
23
+ return false unless actual.data
22
24
 
23
- @fail_msg = "Expected #{actual} to have #{attr_name}: #{expected_attr.inspect}, found #{actual_attr}"
24
- return false unless values_match?(expected_attr, actual_attr)
25
+ expect(actual.data).to be_a_twirp_message(**attrs)
25
26
  end
26
-
27
- true
27
+ rescue RSpec::Expectations::ExpectationNotMetError => err
28
+ @fail_msg = err.message
29
+ false
28
30
  end
29
31
 
30
32
  description do
31
- type ? "a #{type} Twirp response" : "a Twirp response"
33
+ "a Twirp response"
32
34
  end
33
35
 
34
36
  failure_message { @fail_msg }
@@ -1,5 +1,5 @@
1
1
  module RSpec
2
2
  module Twirp
3
- VERSION = "0.1.0"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
data/lib/rspec/twirp.rb CHANGED
@@ -1,32 +1,9 @@
1
- require "rspec/expectations"
2
- require "rspec/twirp/client_response_matcher"
1
+ require "google/protobuf"
2
+ require "rspec"
3
+ require "rspec/protobuf"
4
+ require "twirp"
5
+
3
6
  require "rspec/twirp/error_matcher"
4
- require "rspec/twirp/request_matcher"
7
+ require "rspec/twirp/message_matcher"
5
8
  require "rspec/twirp/response_matcher"
6
-
7
- module RSpec
8
- module Twirp
9
- extend self
10
-
11
- def validate_types(attrs, klass)
12
- # sanity check type and names of attrs by constructing an actual
13
- # proto object
14
- discrete_attrs = attrs.transform_values do |attr|
15
- case attr
16
- when Regexp
17
- attr.inspect
18
- when Range
19
- attr.first
20
- when RSpec::Matchers::BuiltIn::BaseMatcher
21
- nil
22
- else
23
- attr
24
- end
25
- end.compact
26
-
27
- klass.new(**discrete_attrs)
28
- rescue Google::Protobuf::TypeError => e
29
- raise TypeError, e.message
30
- end
31
- end
32
- end
9
+ require "rspec/twirp/version"
data/spec/error_spec.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  describe "be_a_twirp_error" do
2
- subject { Twirp::Error.new(code, msg, meta) }
2
+ subject(:error) { Twirp::Error.new(code, msg, meta) }
3
3
 
4
4
  let(:code) { :not_found }
5
5
  let(:msg) { "Not Found" }
@@ -7,16 +7,54 @@ describe "be_a_twirp_error" do
7
7
 
8
8
  it { is_expected.to be_a_twirp_error }
9
9
 
10
+ it "is composable" do
11
+ expect(e: error).to include(e: a_twirp_error)
12
+ end
13
+
10
14
  it "catches type mismatches" do
11
15
  expect {
12
16
  expect(Object).to be_a_twirp_error
13
17
  }.to fail_with /to be a Twirp::Error/
14
18
  end
15
19
 
20
+ describe "status matches" do
21
+ it { is_expected.to be_a_twirp_error(404) }
22
+
23
+ it "catches mismatches" do
24
+ expect {
25
+ is_expected.to be_a_twirp_error(400)
26
+ }.to fail_including(
27
+ "to have status 400",
28
+ "found: 404",
29
+
30
+ # diff
31
+ "-:code => :invalid_argument,",
32
+ "+:code => :not_found,",
33
+ )
34
+ end
35
+
36
+ it "catches erroneous codes" do
37
+ expect {
38
+ is_expected.to be_a_twirp_error(123)
39
+ }.to raise_error(ArgumentError, /invalid error/)
40
+ end
41
+ end
42
+
16
43
  describe "code matches" do
17
44
  it { is_expected.to be_a_twirp_error(:not_found) }
18
45
 
19
- it { expect { is_expected.to be_a_twirp_error(:unknown) }.to fail }
46
+ it "catches mismatches" do
47
+ expect {
48
+ is_expected.to be_a_twirp_error(:unknown)
49
+ }.to fail_including(
50
+ "to have code `:unknown`",
51
+ "found: :not_found",
52
+
53
+ # diff
54
+ "-:code => :unknown,",
55
+ "+:code => :not_found,",
56
+ )
57
+ end
20
58
 
21
59
  it "catches erroneous codes" do
22
60
  expect {
@@ -35,11 +73,22 @@ describe "be_a_twirp_error" do
35
73
  it "catches mismatches" do
36
74
  expect {
37
75
  is_expected.to be_a_twirp_error("Not")
38
- }.to fail_with /to have msg: "Not"/
76
+ }.to fail_including(
77
+ 'to have msg "Not"',
78
+ 'found: "Not Found"',
79
+
80
+ # diff
81
+ '-:msg => "Not",',
82
+ '+:msg => "Not Found",',
83
+ )
39
84
 
40
85
  expect {
41
86
  is_expected.to be_a_twirp_error(/Nope/)
42
- }.to fail_with /to have msg: \/Nope\//
87
+ }.to fail_including(
88
+ # diff
89
+ '-:msg => /Nope/,',
90
+ '+:msg => "Not Found",',
91
+ )
43
92
  end
44
93
  end
45
94
 
@@ -50,7 +99,13 @@ describe "be_a_twirp_error" do
50
99
  it "catches mismatches" do
51
100
  expect {
52
101
  is_expected.to be_a_twirp_error(is_meta: "false")
53
- }.to fail_with /to have meta.*is_meta/
102
+ }.to fail_including(
103
+ "to have meta",
104
+
105
+ # diff
106
+ '-:meta => {:is_meta=>"false"},',
107
+ '+:meta => {:is_meta=>"true"},',
108
+ )
54
109
 
55
110
  expect {
56
111
  is_expected.to be_a_twirp_error(not_meta: "")
@@ -64,6 +119,24 @@ describe "be_a_twirp_error" do
64
119
  end
65
120
  end
66
121
 
122
+ describe "instance matches" do
123
+ it "matches similar looking instances" do
124
+ error = Twirp::Error.new(code, msg, meta)
125
+ is_expected.to be_a_twirp_error(error)
126
+ end
127
+
128
+ it "catches mismatches" do
129
+ # no meta
130
+ expect {
131
+ is_expected.to be_a_twirp_error(Twirp::Error.not_found("Not Found"))
132
+ }.to fail
133
+
134
+ expect {
135
+ is_expected.to be_a_twirp_error(Twirp::Error.internal("boom"))
136
+ }.to fail
137
+ end
138
+ end
139
+
67
140
  describe "multi matches" do
68
141
  it { is_expected.to be_a_twirp_error(:not_found, "Not Found") }
69
142
  it { is_expected.to be_a_twirp_error(:not_found, /Not/) }
@@ -0,0 +1,69 @@
1
+ describe "be_a_twirp_message" do
2
+ subject(:request) { HelloRequest.new(**attrs) }
3
+
4
+ let(:attrs) { {} }
5
+
6
+ it { is_expected.to be_a_twirp_message }
7
+
8
+ it "works with responses also" do
9
+ expect(HelloResponse.new).to be_a_twirp_message
10
+ end
11
+
12
+ it "supports compound matchers" do
13
+ expect([ request ]).to include(a_twirp_message)
14
+ end
15
+
16
+ it "does not match non-twirp subjects" do
17
+ expect(Object).not_to be_a_twirp_message
18
+ end
19
+
20
+ it "matches a specific message type" do
21
+ is_expected.to be_a_twirp_message(HelloRequest)
22
+ end
23
+
24
+ it "catches type mismatches" do
25
+ is_expected.not_to be_a_twirp_message(GoodbyeRequest)
26
+ end
27
+
28
+ it "catches erroneous message types" do
29
+ expect {
30
+ is_expected.to be_a_twirp_message(Object)
31
+ }.to raise_error(TypeError, /Object/)
32
+ end
33
+
34
+ context "with attributes" do
35
+ let(:attrs) { { name: "Bob", count: 3 } }
36
+
37
+ it "can match attributes" do
38
+ is_expected.to be_a_twirp_message(HelloRequest, **attrs)
39
+ end
40
+
41
+ it "supports regex matches" do
42
+ is_expected.to be_a_twirp_message(name: /^B/)
43
+ end
44
+
45
+ it "supports range matches" do
46
+ is_expected.to be_a_twirp_message(count: 1..5)
47
+ end
48
+
49
+ it "catches mismatches" do
50
+ expect {
51
+ is_expected.to be_a_twirp_message(GoodbyeRequest, name: "Bob")
52
+ }.to fail_with /message of type/
53
+
54
+ is_expected.not_to be_a_twirp_message(name: "nope")
55
+
56
+ is_expected.not_to be_a_twirp_message(name: /no/)
57
+
58
+ is_expected.not_to be_a_twirp_message(count: 1)
59
+ end
60
+
61
+ it "catches erroneous attribute matches" do
62
+ is_expected.not_to be_a_twirp_message(namezzz: "Bob")
63
+ end
64
+
65
+ it "handles type mismatches" do
66
+ is_expected.not_to be_a_twirp_message(name: 123)
67
+ end
68
+ end
69
+ end
@@ -1,56 +1,89 @@
1
1
  describe "be_a_twirp_response" do
2
- subject { HelloResponse.new(**attrs) }
2
+ context "with a response" do
3
+ subject { Twirp::ClientResp.new(response, nil) }
3
4
 
4
- let(:attrs) { {} }
5
+ let(:response) { GoodbyeResponse.new }
5
6
 
6
- it { is_expected.to be_a_twirp_response }
7
+ it { is_expected.to be_a_twirp_response }
7
8
 
8
- it "catches non-twirp response" do
9
- expect {
10
- expect(Object).to be_a_twirp_response
11
- }.to fail_with /Expected a Twirp response, found Object/
12
- end
9
+ it "handles non-twirp response" do
10
+ expect(Object).not_to be_a_twirp_response
11
+ end
13
12
 
14
- it "matches a specific response type" do
15
- is_expected.to be_a_twirp_request(HelloResponse)
16
- end
13
+ context "with attributes" do
14
+ let(:response) { GoodbyeResponse.new(**attrs) }
15
+ let(:attrs) { { message: "bye", name: "Bob" } }
17
16
 
18
- it "catches type mismatches" do
19
- expect {
20
- is_expected.to be_a_twirp_request(GoodbyeResponse)
21
- }.to fail_with /request of type GoodbyeResponse/
22
- end
17
+ it "can match attributes" do
18
+ is_expected.to be_a_twirp_response(**attrs)
19
+ end
23
20
 
24
- context "with attributes" do
25
- let(:attrs) { { message: msg } }
26
- let(:msg) { [ "Hello World" ] }
21
+ it "supports regex matches" do
22
+ is_expected.to be_a_twirp_response(name: /^B/)
23
+ end
27
24
 
28
- it { is_expected.to be_a_twirp_response(**attrs) }
25
+ it "catches mismatches" do
26
+ expect {
27
+ is_expected.to be_a_twirp_response(name: "nope")
28
+ }.to fail_including(
29
+ '-:name => "nope",',
30
+ '+:name => "Bob",',
31
+ )
29
32
 
30
- it "supports regex matches" do
31
- is_expected.to be_a_twirp_response(message: include(/Hello/))
33
+ expect {
34
+ is_expected.to be_a_twirp_response(name: /no/)
35
+ }.to fail_including(
36
+ '-:name => /no/,',
37
+ '+:name => "Bob",',
38
+ )
39
+ end
32
40
  end
41
+ end
42
+
43
+ context "with error" do
44
+ subject { Twirp::ClientResp.new(nil, error) }
45
+
46
+ let(:error) { Twirp::Error.new(code, msg, meta) }
47
+ let(:code) { :not_found }
48
+ let(:msg) { "Not Found" }
49
+ let(:meta) { { is_meta: "true" } }
50
+
51
+ it { is_expected.to be_a_twirp_response.with_error }
52
+ it { is_expected.to be_a_twirp_response.with_error(code) }
53
+ it { is_expected.to be_a_twirp_response.with_error(msg) }
54
+ it { is_expected.to be_a_twirp_response.with_error(**meta) }
55
+ it { is_expected.to be_a_twirp_response.with_error(/Not/) }
33
56
 
34
57
  it "catches mismatches" do
35
58
  expect {
36
- is_expected.to be_a_twirp_response(message: [ "" ])
37
- }.to fail_with /to have message/
59
+ is_expected.to be_a_twirp_response.with_error(:internal)
60
+ }.to fail_with /to have code `:internal`/
61
+ end
62
+ end
38
63
 
64
+ context "with neither response nor error" do
65
+ subject { Twirp::ClientResp.new(nil, nil) }
66
+
67
+ it "fails the response match" do
39
68
  expect {
40
- is_expected.to be_a_twirp_response(message: [ "Hello" ])
41
- }.to fail_with /to have message/
69
+ is_expected.to be_a_twirp_response
70
+ }.to fail_with /to have data/
42
71
  end
43
72
 
44
- it "catches the erroneous attributes" do
73
+ it "fails the error match" do
45
74
  expect {
46
- is_expected.to be_a_twirp_response(msg: [])
47
- }.to raise_error(ArgumentError, /msg/)
75
+ is_expected.to be_a_twirp_response.with_error
76
+ }.to fail_with /to have an error/
48
77
  end
78
+ end
79
+
80
+ context "with both response and error" do
81
+ subject { Twirp::ClientResp.new(GoodbyeResponse.new, Twirp::Error.not_found("Not Found")) }
49
82
 
50
- it "catches type mismatches" do
83
+ it "does not permit both attr and error matching" do
51
84
  expect {
52
- is_expected.to be_a_twirp_response(message: "Hello World")
53
- }.to raise_error(ArgumentError, /Expected array/)
85
+ is_expected.to be_a_twirp_response(name: "Bob").with_error
86
+ }.to raise_error(ArgumentError, /but not both/)
54
87
  end
55
88
  end
56
89
  end
metadata CHANGED
@@ -1,31 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-twirp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Pepper
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-25 00:00:00.000000000 Z
11
+ date: 2022-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: twirp
14
+ name: google-protobuf
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '3'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '3'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rspec-expectations
28
+ name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,21 +39,35 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3'
41
41
  - !ruby/object:Gem::Dependency
42
- name: byebug
42
+ name: rspec-protobuf
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
47
+ version: '0.2'
48
+ type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '0.2'
55
55
  - !ruby/object:Gem::Dependency
56
- name: codecov
56
+ name: twirp
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '1'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: byebug
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - ">="
@@ -67,7 +81,7 @@ dependencies:
67
81
  - !ruby/object:Gem::Version
68
82
  version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
- name: rspec
84
+ name: codecov
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - ">="
@@ -94,7 +108,7 @@ dependencies:
94
108
  - - ">="
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0'
97
- description: "..."
111
+ description: Twirp RSpec matchers
98
112
  email:
99
113
  executables: []
100
114
  extensions: []
@@ -102,14 +116,12 @@ extra_rdoc_files: []
102
116
  files:
103
117
  - lib/rspec-twirp.rb
104
118
  - lib/rspec/twirp.rb
105
- - lib/rspec/twirp/client_response_matcher.rb
106
119
  - lib/rspec/twirp/error_matcher.rb
107
- - lib/rspec/twirp/request_matcher.rb
120
+ - lib/rspec/twirp/message_matcher.rb
108
121
  - lib/rspec/twirp/response_matcher.rb
109
122
  - lib/rspec/twirp/version.rb
110
- - spec/client_response_spec.rb
111
123
  - spec/error_spec.rb
112
- - spec/request_spec.rb
124
+ - spec/message_spec.rb
113
125
  - spec/response_spec.rb
114
126
  homepage: https://github.com/dpep/rspec-twirp_rb
115
127
  licenses:
@@ -130,12 +142,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
142
  - !ruby/object:Gem::Version
131
143
  version: '0'
132
144
  requirements: []
133
- rubygems_version: 3.1.6
145
+ rubygems_version: 3.3.7
134
146
  signing_key:
135
147
  specification_version: 4
136
148
  summary: Gem::Specification::RSpec::Twirp
137
149
  test_files:
138
150
  - spec/error_spec.rb
139
- - spec/request_spec.rb
151
+ - spec/message_spec.rb
140
152
  - spec/response_spec.rb
141
- - spec/client_response_spec.rb
@@ -1,48 +0,0 @@
1
- RSpec::Matchers.define :be_a_twirp_client_response do |type = nil, **attrs|
2
- chain :with_error do |*matchers, **meta_matchers|
3
- # code, msg, meta
4
- @with_error = [ matchers, meta_matchers ]
5
- end
6
-
7
- match do |actual|
8
- # ensure type is a valid twirp request type
9
- if type && !(type < Google::Protobuf::MessageExts)
10
- raise ArgumentError, "Expected `type` to be a Twirp response, found: #{type}"
11
- end
12
-
13
- @fail_msg = "Expected a Twirp::ClientResp, found #{actual}"
14
- return false unless actual.is_a?(Twirp::ClientResp)
15
-
16
- # match expected response type
17
- @fail_msg = "Expected a Twirp::ClientResp of type #{type}, found #{actual.data&.class}"
18
- return false if type && actual.data&.class != type
19
-
20
- if @with_error
21
- unless attrs.empty?
22
- raise ArgumentError, "match data attributes or error, but not both"
23
- end
24
-
25
- @fail_msg = "Expected #{actual} to have an error"
26
- return false unless actual.error
27
-
28
- matchers, meta_matchers = @with_error
29
- expect(actual.error).to be_a_twirp_error(*matchers, **meta_matchers)
30
- else
31
- @fail_msg = "Expected #{actual} to have data"
32
- return false unless actual.data
33
-
34
- expect(actual.data).to be_a_twirp_response(**attrs)
35
- end
36
- rescue RSpec::Expectations::ExpectationNotMetError => err
37
- @fail_msg = err.message
38
- false
39
- end
40
-
41
- description do
42
- type ? "a #{type} Twirp response" : "a Twirp response"
43
- end
44
-
45
- failure_message { @fail_msg }
46
- end
47
-
48
- RSpec::Matchers.alias_matcher :a_twirp_client_response, :be_a_twirp_client_response
@@ -1,37 +0,0 @@
1
- RSpec::Matchers.define :be_a_twirp_request do |type = nil, **attrs|
2
- match do |actual|
3
- # ensure type is a valid twirp request type
4
- if type && !(type < Google::Protobuf::MessageExts)
5
- raise ArgumentError, "Expected `type` to be a Twirp request, found: #{type}"
6
- end
7
-
8
- @fail_msg = "Expected a Twirp request, found #{actual}"
9
- return false unless actual.is_a?(Google::Protobuf::MessageExts)
10
-
11
- # match expected request type
12
- @fail_msg = "Expected a Twirp request of type #{type}, found #{actual.class}"
13
- return false if type && actual.class != type
14
-
15
- return true if attrs.empty?
16
-
17
- RSpec::Twirp.validate_types(attrs, actual.class)
18
-
19
- # match attributes which are present
20
- attrs.each do |attr_name, expected_attr|
21
- actual_attr = actual.send(attr_name)
22
-
23
- @fail_msg = "Expected #{actual} to have #{attr_name}: #{expected_attr.inspect}, found #{actual_attr}"
24
- return false unless values_match?(expected_attr, actual_attr)
25
- end
26
-
27
- true
28
- end
29
-
30
- description do
31
- type ? "a #{type} Twirp request" : "a Twirp request"
32
- end
33
-
34
- failure_message { @fail_msg }
35
- end
36
-
37
- RSpec::Matchers.alias_matcher :a_twirp_request, :be_a_twirp_request
@@ -1,112 +0,0 @@
1
- describe "be_a_twirp_client_response" do
2
- context "with a response" do
3
- subject { Twirp::ClientResp.new(GoodbyeResponse.new, nil) }
4
-
5
- it { is_expected.to be_a_twirp_client_response }
6
-
7
- it "catches non-twirp response" do
8
- expect {
9
- expect(Object).to be_a_twirp_client_response
10
- }.to fail_with /found Object/
11
- end
12
-
13
- it "matches a specific response type" do
14
- is_expected.to be_a_twirp_client_response(GoodbyeResponse)
15
- end
16
-
17
- it "catches type mismatches" do
18
- expect {
19
- is_expected.to be_a_twirp_client_response(HelloResponse)
20
- }.to fail_with /of type HelloResponse/
21
- end
22
-
23
- it "catches erroneous response types" do
24
- expect {
25
- is_expected.to be_a_twirp_client_response(Object)
26
- }.to raise_error(ArgumentError, /Object/)
27
- end
28
-
29
- context "with attributes" do
30
- subject { Twirp::ClientResp.new(GoodbyeResponse.new(**attrs), nil) }
31
-
32
- let(:attrs) { { message: "bye", name: "Bob" } }
33
-
34
- it "can match attributes" do
35
- is_expected.to be_a_twirp_client_response(GoodbyeResponse, **attrs)
36
- end
37
-
38
- it "supports regex matches" do
39
- is_expected.to be_a_twirp_client_response(name: /^B/)
40
- end
41
-
42
- it "catches mismatches" do
43
- expect {
44
- is_expected.to be_a_twirp_client_response(name: "nope")
45
- }.to fail_with /to have name: "nope"/
46
-
47
- expect {
48
- is_expected.to be_a_twirp_client_response(name: /no/)
49
- }.to fail_with /to have name: \/no\//
50
- end
51
-
52
- it "catches the erroneous attributes" do
53
- expect {
54
- is_expected.to be_a_twirp_client_response(namezzz: "Bob")
55
- }.to raise_error(ArgumentError, /namezzz/)
56
- end
57
-
58
- it "catches type mismatches" do
59
- expect {
60
- is_expected.to be_a_twirp_client_response(name: 123)
61
- }.to raise_error(TypeError, /string field.*given Integer/)
62
- end
63
- end
64
- end
65
-
66
- context "with error" do
67
- subject { Twirp::ClientResp.new(nil, error) }
68
-
69
- let(:error) { Twirp::Error.new(code, msg, meta) }
70
- let(:code) { :not_found }
71
- let(:msg) { "Not Found" }
72
- let(:meta) { { is_meta: "true" } }
73
-
74
- it { is_expected.to be_a_twirp_client_response.with_error }
75
- it { is_expected.to be_a_twirp_client_response.with_error(code) }
76
- it { is_expected.to be_a_twirp_client_response.with_error(msg) }
77
- it { is_expected.to be_a_twirp_client_response.with_error(**meta) }
78
- it { is_expected.to be_a_twirp_client_response.with_error(/Not/) }
79
-
80
- it "catches mismatches" do
81
- expect {
82
- is_expected.to be_a_twirp_client_response.with_error(:internal)
83
- }.to fail_with /code: :internal/
84
- end
85
- end
86
-
87
- context "with neither response nor error" do
88
- subject { Twirp::ClientResp.new(nil, nil) }
89
-
90
- it "fails the response match" do
91
- expect {
92
- is_expected.to be_a_twirp_client_response
93
- }.to fail_with /to have data/
94
- end
95
-
96
- it "fails the error match" do
97
- expect {
98
- is_expected.to be_a_twirp_client_response.with_error
99
- }.to fail_with /to have an error/
100
- end
101
- end
102
-
103
- context "with both response and error" do
104
- subject { Twirp::ClientResp.new(GoodbyeResponse.new, Twirp::Error.not_found("Not Found")) }
105
-
106
- it "fails" do
107
- expect {
108
- is_expected.to be_a_twirp_client_response(name: "Bob").with_error
109
- }.to raise_error(ArgumentError, /but not both/)
110
- end
111
- end
112
- end
data/spec/request_spec.rb DELETED
@@ -1,75 +0,0 @@
1
- describe "be_a_twirp_request" do
2
- subject { HelloRequest.new(**attrs) }
3
-
4
- let(:attrs) { {} }
5
-
6
- it { is_expected.to be_a_twirp_request }
7
-
8
- it "catches non-twirp requests" do
9
- expect {
10
- expect(Object).to be_a_twirp_request
11
- }.to fail_with /Expected a Twirp request, found Object/
12
- end
13
-
14
- it "matches a specific request type" do
15
- is_expected.to be_a_twirp_request(HelloRequest)
16
- end
17
-
18
- it "catches type mismatches" do
19
- expect {
20
- is_expected.to be_a_twirp_request(GoodbyeRequest)
21
- }.to fail_with /request of type GoodbyeRequest/
22
- end
23
-
24
- it "catches erroneous request types" do
25
- expect {
26
- is_expected.to be_a_twirp_request(Object)
27
- }.to raise_error(ArgumentError, /Object/)
28
- end
29
-
30
- context "with attributes" do
31
- let(:attrs) { { name: "Bob", count: 3 } }
32
-
33
- it "can match attributes" do
34
- is_expected.to be_a_twirp_request(HelloRequest, **attrs)
35
- end
36
-
37
- it "supports regex matches" do
38
- is_expected.to be_a_twirp_request(name: /^B/)
39
- end
40
-
41
- it "supports range matches" do
42
- is_expected.to be_a_twirp_request(count: 1..5)
43
- end
44
-
45
- it "catches mismatches" do
46
- expect {
47
- is_expected.to be_a_twirp_request(GoodbyeRequest, name: "Bob")
48
- }.to fail_with /request of type/
49
-
50
- expect {
51
- is_expected.to be_a_twirp_request(name: "nope")
52
- }.to fail_with /to have name: "nope"/
53
-
54
- expect {
55
- is_expected.to be_a_twirp_request(name: /no/)
56
- }.to fail_with /to have name: \/no\//
57
-
58
- expect {
59
- is_expected.to be_a_twirp_request(count: 1)
60
- }.to fail_with /to have count: 1/
61
- end
62
-
63
- it "catches the erroneous attribute matches" do
64
- expect {
65
- is_expected.to be_a_twirp_request(namezzz: "Bob")
66
- }.to raise_error(ArgumentError, /namezzz/)
67
- end
68
-
69
- it "catches type mismatches" do
70
- expect {
71
- is_expected.to be_a_twirp_request(name: 123)
72
- }.to raise_error(TypeError, /string field.*given Integer/)
73
- end
74
- end
75
- end