rspec-twirp 0.2.0 → 0.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 +4 -4
- data/lib/rspec/twirp/error_matcher.rb +34 -12
- data/lib/rspec/twirp/message_matcher.rb +2 -61
- data/lib/rspec/twirp/response_matcher.rb +2 -20
- data/lib/rspec/twirp/version.rb +1 -1
- data/lib/rspec/twirp.rb +2 -47
- data/spec/error_spec.rb +49 -6
- data/spec/message_spec.rb +12 -26
- data/spec/response_spec.rb +14 -49
- metadata +17 -11
- data/lib/rspec/twirp/helpers.rb +0 -16
- data/lib/rspec/twirp/make_request_matcher.rb +0 -169
- data/lib/rspec/twirp/mock_client.rb +0 -59
- data/lib/rspec/twirp/mock_connection.rb +0 -54
- data/spec/make_request_spec.rb +0 -181
- data/spec/mock_connection_spec.rb +0 -103
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a9027f86450d9e045705304d1d8e590b51a733269938e83ca5ae098a90018d4
|
4
|
+
data.tar.gz: dca42845c93b814878cf24842320583ddf6dbce3b0d266cd897a58500cf31a31
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98d362457d71269cf64bffa1fe0b1fe00e173fe68df88e12cf0af20aa1030d518e031415d005050209b070095c36a6eac454e1bdba740661a090ce3be90cfa15
|
7
|
+
data.tar.gz: a0923b782b8568198fb267cd1e3bc6192bb032b0a7e746be478a4e8d66317ccc81652487f6f3b442847c6c2946b2e398f25b60682c0cc6b1c794c556837d0978
|
@@ -1,43 +1,59 @@
|
|
1
1
|
RSpec::Matchers.define :be_a_twirp_error do |*matchers, **meta_matcher|
|
2
2
|
match do |actual|
|
3
|
-
@fail_msg = "Expected
|
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
|
-
|
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
|
16
|
-
|
20
|
+
@fail_msg = "Expected #{actual} to have code `#{matcher.inspect}`, found: #{actual.code.inspect}"
|
21
|
+
actual.code == matcher
|
17
22
|
when Integer
|
18
23
|
# match http status code
|
19
24
|
|
20
25
|
if code = Twirp::ERROR_CODES_TO_HTTP_STATUS.key(matcher)
|
21
|
-
@
|
22
|
-
|
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
|
23
33
|
else
|
24
34
|
raise ArgumentError, "invalid error status code: #{matcher}"
|
25
35
|
end
|
26
36
|
when Twirp::Error
|
27
37
|
# match instance
|
38
|
+
@expected = matcher.to_h
|
39
|
+
@actual = actual.to_h
|
28
40
|
|
29
41
|
@fail_msg = "Expected #{actual} to equal #{matcher}"
|
30
|
-
|
42
|
+
values_match?(matcher.to_h, actual.to_h)
|
31
43
|
else
|
32
44
|
# match msg
|
33
|
-
@
|
34
|
-
|
45
|
+
@expected[:msg] = matcher
|
46
|
+
@actual[:msg] = actual.msg
|
47
|
+
|
48
|
+
@fail_msg = "Expected #{actual} to have msg #{matcher.inspect}, found: #{actual.msg.inspect}"
|
49
|
+
values_match?(matcher, actual.msg)
|
35
50
|
end
|
36
51
|
end
|
37
52
|
|
38
53
|
# match meta
|
39
54
|
unless meta_matcher.empty?
|
40
|
-
@
|
55
|
+
@expected[:meta] = meta_matcher
|
56
|
+
@actual[:meta] = actual.meta
|
41
57
|
|
42
58
|
# sanity check...values must be Strings or Regexp
|
43
59
|
discrete_attrs = meta_matcher.transform_values do |attr|
|
@@ -46,10 +62,10 @@ RSpec::Matchers.define :be_a_twirp_error do |*matchers, **meta_matcher|
|
|
46
62
|
actual.send(:validate_meta, discrete_attrs)
|
47
63
|
|
48
64
|
@fail_msg = "Expected #{actual} to have meta: #{meta_matcher.inspect}, found #{actual.meta}"
|
49
|
-
|
65
|
+
matched &= values_match?(meta_matcher, actual.meta)
|
50
66
|
end
|
51
67
|
|
52
|
-
|
68
|
+
matched
|
53
69
|
end
|
54
70
|
|
55
71
|
description do
|
@@ -57,6 +73,12 @@ RSpec::Matchers.define :be_a_twirp_error do |*matchers, **meta_matcher|
|
|
57
73
|
end
|
58
74
|
|
59
75
|
failure_message { @fail_msg }
|
76
|
+
|
77
|
+
diffable
|
78
|
+
|
79
|
+
def expected
|
80
|
+
@expected
|
81
|
+
end
|
60
82
|
end
|
61
83
|
|
62
84
|
RSpec::Matchers.alias_matcher :a_twirp_error, :be_a_twirp_error
|
@@ -1,61 +1,2 @@
|
|
1
|
-
RSpec::Matchers.
|
2
|
-
|
3
|
-
# ensure type is a valid twirp message type
|
4
|
-
if type && !(type < Google::Protobuf::MessageExts)
|
5
|
-
raise TypeError, "Expected `type` to be a Google::Protobuf::MessageExts, found: #{type}"
|
6
|
-
end
|
7
|
-
|
8
|
-
@fail_msg = "Expected a Twirp message, found #{actual}"
|
9
|
-
return false unless actual.is_a?(Google::Protobuf::MessageExts)
|
10
|
-
|
11
|
-
# match expected message type
|
12
|
-
@fail_msg = "Expected a Twirp message of type #{type}, found #{actual.class}"
|
13
|
-
return false if type && actual.class != type
|
14
|
-
|
15
|
-
return true if attrs.empty?
|
16
|
-
|
17
|
-
# sanity check inputs
|
18
|
-
validate_types(attrs, actual.class)
|
19
|
-
|
20
|
-
# match attributes which are present
|
21
|
-
attrs.each do |attr_name, expected_attr|
|
22
|
-
actual_attr = actual.send(attr_name)
|
23
|
-
|
24
|
-
@fail_msg = "Expected #{actual} to have #{attr_name}: #{expected_attr.inspect}, found #{actual_attr}"
|
25
|
-
return false unless values_match?(expected_attr, actual_attr)
|
26
|
-
end
|
27
|
-
|
28
|
-
true
|
29
|
-
end
|
30
|
-
|
31
|
-
description do
|
32
|
-
type ? "a #{type} Twirp message" : "a Twirp message"
|
33
|
-
end
|
34
|
-
|
35
|
-
failure_message { @fail_msg }
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def validate_types(attrs, klass)
|
40
|
-
# check names and types of attrs by constructing an actual proto object
|
41
|
-
discrete_attrs = attrs.transform_values do |attr|
|
42
|
-
case attr
|
43
|
-
when Regexp
|
44
|
-
attr.inspect
|
45
|
-
when Range
|
46
|
-
attr.first
|
47
|
-
when RSpec::Matchers::BuiltIn::BaseMatcher
|
48
|
-
# no good substitute, so skip attr and hope for the best
|
49
|
-
nil
|
50
|
-
else
|
51
|
-
attr
|
52
|
-
end
|
53
|
-
end.compact
|
54
|
-
|
55
|
-
klass.new(**discrete_attrs)
|
56
|
-
rescue Google::Protobuf::TypeError => e
|
57
|
-
raise TypeError, e.message
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
RSpec::Matchers.alias_matcher :a_twirp_message, :be_a_twirp_message
|
1
|
+
RSpec::Matchers.alias_matcher :be_a_twirp_message, :be_a_protobuf
|
2
|
+
RSpec::Matchers.alias_matcher :a_twirp_message, :a_protobuf
|
@@ -1,31 +1,13 @@
|
|
1
|
-
RSpec::Matchers.define :be_a_twirp_response do
|
1
|
+
RSpec::Matchers.define :be_a_twirp_response do |**attrs|
|
2
2
|
chain :with_error do |*matchers, **meta_matchers|
|
3
3
|
# code, msg, meta
|
4
4
|
@with_error = [ matchers, meta_matchers ]
|
5
5
|
end
|
6
6
|
|
7
7
|
match do |actual|
|
8
|
-
# ensure type is a valid twirp request type
|
9
|
-
if type
|
10
|
-
if type.is_a?(Google::Protobuf::MessageExts)
|
11
|
-
unless attrs.empty?
|
12
|
-
raise ArgumentError, "Expected Google::Protobuf::MessageExts instance or attrs, but not both"
|
13
|
-
end
|
14
|
-
|
15
|
-
attrs = type.to_h
|
16
|
-
type = type.class
|
17
|
-
elsif !(type < Google::Protobuf::MessageExts)
|
18
|
-
raise ArgumentError, "Expected `type` to be a Google::Protobuf::MessageExts, found: #{type}"
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
8
|
@fail_msg = "Expected a Twirp::ClientResp, found #{actual}"
|
23
9
|
return false unless actual.is_a?(Twirp::ClientResp)
|
24
10
|
|
25
|
-
# match expected response type
|
26
|
-
@fail_msg = "Expected a Twirp::ClientResp of type #{type}, found #{actual.data&.class}"
|
27
|
-
return false if type && actual.data&.class != type
|
28
|
-
|
29
11
|
if @with_error
|
30
12
|
unless attrs.empty?
|
31
13
|
raise ArgumentError, "match data attributes or error, but not both"
|
@@ -48,7 +30,7 @@ RSpec::Matchers.define :be_a_twirp_response do |type = nil, **attrs|
|
|
48
30
|
end
|
49
31
|
|
50
32
|
description do
|
51
|
-
|
33
|
+
"a Twirp response"
|
52
34
|
end
|
53
35
|
|
54
36
|
failure_message { @fail_msg }
|
data/lib/rspec/twirp/version.rb
CHANGED
data/lib/rspec/twirp.rb
CHANGED
@@ -1,54 +1,9 @@
|
|
1
1
|
require "google/protobuf"
|
2
2
|
require "rspec"
|
3
|
+
require "rspec/protobuf"
|
3
4
|
require "twirp"
|
4
5
|
|
5
|
-
require "rspec/twirp/helpers"
|
6
|
-
require "rspec/twirp/make_request_matcher"
|
7
6
|
require "rspec/twirp/error_matcher"
|
8
7
|
require "rspec/twirp/message_matcher"
|
9
8
|
require "rspec/twirp/response_matcher"
|
10
|
-
|
11
|
-
module RSpec
|
12
|
-
module Twirp
|
13
|
-
extend RSpec::Mocks::ExampleMethods
|
14
|
-
|
15
|
-
# private
|
16
|
-
|
17
|
-
def generate_client_response(arg)
|
18
|
-
res = case arg
|
19
|
-
when Google::Protobuf::MessageExts, ::Twirp::Error
|
20
|
-
arg
|
21
|
-
when Class
|
22
|
-
if arg < Google::Protobuf::MessageExts
|
23
|
-
arg.new
|
24
|
-
else
|
25
|
-
raise TypeError, "Expected type `Google::Protobuf::MessageExts`, found: #{arg}"
|
26
|
-
end
|
27
|
-
when Symbol
|
28
|
-
if ::Twirp::Error.valid_code?(arg)
|
29
|
-
::Twirp::Error.new(arg, arg)
|
30
|
-
else
|
31
|
-
raise ArgumentError, "invalid error code: #{arg}"
|
32
|
-
end
|
33
|
-
when Integer
|
34
|
-
if code = ::Twirp::ERROR_CODES_TO_HTTP_STATUS.key(arg)
|
35
|
-
::Twirp::Error.new(code, code)
|
36
|
-
else
|
37
|
-
raise ArgumentError, "invalid error code: #{arg}"
|
38
|
-
end
|
39
|
-
else
|
40
|
-
raise NotImplementedError
|
41
|
-
end
|
42
|
-
|
43
|
-
if res.is_a?(Google::Protobuf::MessageExts)
|
44
|
-
::Twirp::ClientResp.new(res, nil)
|
45
|
-
else
|
46
|
-
::Twirp::ClientResp.new(nil, res)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
RSpec.configure do |config|
|
53
|
-
config.include(RSpec::Twirp::Helpers)
|
54
|
-
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,6 +7,10 @@ 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
|
@@ -16,7 +20,18 @@ describe "be_a_twirp_error" do
|
|
16
20
|
describe "status matches" do
|
17
21
|
it { is_expected.to be_a_twirp_error(404) }
|
18
22
|
|
19
|
-
it
|
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
|
20
35
|
|
21
36
|
it "catches erroneous codes" do
|
22
37
|
expect {
|
@@ -28,7 +43,18 @@ describe "be_a_twirp_error" do
|
|
28
43
|
describe "code matches" do
|
29
44
|
it { is_expected.to be_a_twirp_error(:not_found) }
|
30
45
|
|
31
|
-
it
|
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
|
32
58
|
|
33
59
|
it "catches erroneous codes" do
|
34
60
|
expect {
|
@@ -47,11 +73,22 @@ describe "be_a_twirp_error" do
|
|
47
73
|
it "catches mismatches" do
|
48
74
|
expect {
|
49
75
|
is_expected.to be_a_twirp_error("Not")
|
50
|
-
}.to
|
76
|
+
}.to fail_including(
|
77
|
+
'to have msg "Not"',
|
78
|
+
'found: "Not Found"',
|
79
|
+
|
80
|
+
# diff
|
81
|
+
'-:msg => "Not",',
|
82
|
+
'+:msg => "Not Found",',
|
83
|
+
)
|
51
84
|
|
52
85
|
expect {
|
53
86
|
is_expected.to be_a_twirp_error(/Nope/)
|
54
|
-
}.to
|
87
|
+
}.to fail_including(
|
88
|
+
# diff
|
89
|
+
'-:msg => /Nope/,',
|
90
|
+
'+:msg => "Not Found",',
|
91
|
+
)
|
55
92
|
end
|
56
93
|
end
|
57
94
|
|
@@ -62,7 +99,13 @@ describe "be_a_twirp_error" do
|
|
62
99
|
it "catches mismatches" do
|
63
100
|
expect {
|
64
101
|
is_expected.to be_a_twirp_error(is_meta: "false")
|
65
|
-
}.to
|
102
|
+
}.to fail_including(
|
103
|
+
"to have meta",
|
104
|
+
|
105
|
+
# diff
|
106
|
+
'-:meta => {:is_meta=>"false"},',
|
107
|
+
'+:meta => {:is_meta=>"true"},',
|
108
|
+
)
|
66
109
|
|
67
110
|
expect {
|
68
111
|
is_expected.to be_a_twirp_error(not_meta: "")
|
data/spec/message_spec.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
describe "be_a_twirp_message" do
|
2
|
-
subject { HelloRequest.new(**attrs) }
|
2
|
+
subject(:request) { HelloRequest.new(**attrs) }
|
3
3
|
|
4
4
|
let(:attrs) { {} }
|
5
5
|
|
@@ -10,13 +10,11 @@ describe "be_a_twirp_message" do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
it "supports compound matchers" do
|
13
|
-
expect([
|
13
|
+
expect([ request ]).to include(a_twirp_message)
|
14
14
|
end
|
15
15
|
|
16
|
-
it "
|
17
|
-
expect
|
18
|
-
expect(Object).to be_a_twirp_message
|
19
|
-
}.to fail_with /Expected a Twirp message, found Object/
|
16
|
+
it "does not match non-twirp subjects" do
|
17
|
+
expect(Object).not_to be_a_twirp_message
|
20
18
|
end
|
21
19
|
|
22
20
|
it "matches a specific message type" do
|
@@ -24,9 +22,7 @@ describe "be_a_twirp_message" do
|
|
24
22
|
end
|
25
23
|
|
26
24
|
it "catches type mismatches" do
|
27
|
-
|
28
|
-
is_expected.to be_a_twirp_message(GoodbyeRequest)
|
29
|
-
}.to fail_with /message of type GoodbyeRequest/
|
25
|
+
is_expected.not_to be_a_twirp_message(GoodbyeRequest)
|
30
26
|
end
|
31
27
|
|
32
28
|
it "catches erroneous message types" do
|
@@ -55,29 +51,19 @@ describe "be_a_twirp_message" do
|
|
55
51
|
is_expected.to be_a_twirp_message(GoodbyeRequest, name: "Bob")
|
56
52
|
}.to fail_with /message of type/
|
57
53
|
|
58
|
-
|
59
|
-
is_expected.to be_a_twirp_message(name: "nope")
|
60
|
-
}.to fail_with /to have name: "nope"/
|
54
|
+
is_expected.not_to be_a_twirp_message(name: "nope")
|
61
55
|
|
62
|
-
|
63
|
-
is_expected.to be_a_twirp_message(name: /no/)
|
64
|
-
}.to fail_with /to have name: \/no\//
|
56
|
+
is_expected.not_to be_a_twirp_message(name: /no/)
|
65
57
|
|
66
|
-
|
67
|
-
is_expected.to be_a_twirp_message(count: 1)
|
68
|
-
}.to fail_with /to have count: 1/
|
58
|
+
is_expected.not_to be_a_twirp_message(count: 1)
|
69
59
|
end
|
70
60
|
|
71
|
-
it "catches
|
72
|
-
|
73
|
-
is_expected.to be_a_twirp_message(namezzz: "Bob")
|
74
|
-
}.to raise_error(ArgumentError, /namezzz/)
|
61
|
+
it "catches erroneous attribute matches" do
|
62
|
+
is_expected.not_to be_a_twirp_message(namezzz: "Bob")
|
75
63
|
end
|
76
64
|
|
77
|
-
it "
|
78
|
-
|
79
|
-
is_expected.to be_a_twirp_message(name: 123)
|
80
|
-
}.to raise_error(TypeError, /string field.*given Integer/)
|
65
|
+
it "handles type mismatches" do
|
66
|
+
is_expected.not_to be_a_twirp_message(name: 123)
|
81
67
|
end
|
82
68
|
end
|
83
69
|
end
|
data/spec/response_spec.rb
CHANGED
@@ -6,39 +6,16 @@ describe "be_a_twirp_response" do
|
|
6
6
|
|
7
7
|
it { is_expected.to be_a_twirp_response }
|
8
8
|
|
9
|
-
it "
|
10
|
-
expect
|
11
|
-
expect(Object).to be_a_twirp_response
|
12
|
-
}.to fail_with /found Object/
|
13
|
-
end
|
14
|
-
|
15
|
-
it "matches a specific response type" do
|
16
|
-
is_expected.to be_a_twirp_response(GoodbyeResponse)
|
17
|
-
end
|
18
|
-
|
19
|
-
it "matches a specific response" do
|
20
|
-
is_expected.to be_a_twirp_response(response)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "catches type mismatches" do
|
24
|
-
expect {
|
25
|
-
is_expected.to be_a_twirp_response(HelloResponse)
|
26
|
-
}.to fail_with /of type HelloResponse/
|
27
|
-
end
|
28
|
-
|
29
|
-
it "catches erroneous response types" do
|
30
|
-
expect {
|
31
|
-
is_expected.to be_a_twirp_response(Object)
|
32
|
-
}.to raise_error(ArgumentError, /Object/)
|
9
|
+
it "handles non-twirp response" do
|
10
|
+
expect(Object).not_to be_a_twirp_response
|
33
11
|
end
|
34
12
|
|
35
13
|
context "with attributes" do
|
36
|
-
|
37
|
-
|
14
|
+
let(:response) { GoodbyeResponse.new(**attrs) }
|
38
15
|
let(:attrs) { { message: "bye", name: "Bob" } }
|
39
16
|
|
40
17
|
it "can match attributes" do
|
41
|
-
is_expected.to be_a_twirp_response(
|
18
|
+
is_expected.to be_a_twirp_response(**attrs)
|
42
19
|
end
|
43
20
|
|
44
21
|
it "supports regex matches" do
|
@@ -48,29 +25,17 @@ describe "be_a_twirp_response" do
|
|
48
25
|
it "catches mismatches" do
|
49
26
|
expect {
|
50
27
|
is_expected.to be_a_twirp_response(name: "nope")
|
51
|
-
}.to
|
28
|
+
}.to fail_including(
|
29
|
+
'-:name => "nope",',
|
30
|
+
'+:name => "Bob",',
|
31
|
+
)
|
52
32
|
|
53
33
|
expect {
|
54
34
|
is_expected.to be_a_twirp_response(name: /no/)
|
55
|
-
}.to
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
expect {
|
60
|
-
is_expected.to be_a_twirp_response(namezzz: "Bob")
|
61
|
-
}.to raise_error(ArgumentError, /namezzz/)
|
62
|
-
end
|
63
|
-
|
64
|
-
it "catches type mismatches" do
|
65
|
-
expect {
|
66
|
-
is_expected.to be_a_twirp_response(name: 123)
|
67
|
-
}.to raise_error(TypeError, /string field.*given Integer/)
|
68
|
-
end
|
69
|
-
|
70
|
-
it "can't also match a specific response" do
|
71
|
-
expect {
|
72
|
-
is_expected.to be_a_twirp_response(response, name: "Bob")
|
73
|
-
}.to raise_error(ArgumentError, /but not both/)
|
35
|
+
}.to fail_including(
|
36
|
+
'-:name => /no/,',
|
37
|
+
'+:name => "Bob",',
|
38
|
+
)
|
74
39
|
end
|
75
40
|
end
|
76
41
|
end
|
@@ -92,7 +57,7 @@ describe "be_a_twirp_response" do
|
|
92
57
|
it "catches mismatches" do
|
93
58
|
expect {
|
94
59
|
is_expected.to be_a_twirp_response.with_error(:internal)
|
95
|
-
}.to fail_with /code
|
60
|
+
}.to fail_with /to have code `:internal`/
|
96
61
|
end
|
97
62
|
end
|
98
63
|
|
@@ -115,7 +80,7 @@ describe "be_a_twirp_response" do
|
|
115
80
|
context "with both response and error" do
|
116
81
|
subject { Twirp::ClientResp.new(GoodbyeResponse.new, Twirp::Error.not_found("Not Found")) }
|
117
82
|
|
118
|
-
it "
|
83
|
+
it "does not permit both attr and error matching" do
|
119
84
|
expect {
|
120
85
|
is_expected.to be_a_twirp_response(name: "Bob").with_error
|
121
86
|
}.to raise_error(ArgumentError, /but not both/)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-twirp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 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-
|
11
|
+
date: 2022-11-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-protobuf
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-protobuf
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.2'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.2'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: twirp
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -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: []
|
@@ -103,17 +117,11 @@ files:
|
|
103
117
|
- lib/rspec-twirp.rb
|
104
118
|
- lib/rspec/twirp.rb
|
105
119
|
- lib/rspec/twirp/error_matcher.rb
|
106
|
-
- lib/rspec/twirp/helpers.rb
|
107
|
-
- lib/rspec/twirp/make_request_matcher.rb
|
108
120
|
- lib/rspec/twirp/message_matcher.rb
|
109
|
-
- lib/rspec/twirp/mock_client.rb
|
110
|
-
- lib/rspec/twirp/mock_connection.rb
|
111
121
|
- lib/rspec/twirp/response_matcher.rb
|
112
122
|
- lib/rspec/twirp/version.rb
|
113
123
|
- spec/error_spec.rb
|
114
|
-
- spec/make_request_spec.rb
|
115
124
|
- spec/message_spec.rb
|
116
|
-
- spec/mock_connection_spec.rb
|
117
125
|
- spec/response_spec.rb
|
118
126
|
homepage: https://github.com/dpep/rspec-twirp_rb
|
119
127
|
licenses:
|
@@ -140,7 +148,5 @@ specification_version: 4
|
|
140
148
|
summary: Gem::Specification::RSpec::Twirp
|
141
149
|
test_files:
|
142
150
|
- spec/error_spec.rb
|
143
|
-
- spec/make_request_spec.rb
|
144
151
|
- spec/message_spec.rb
|
145
|
-
- spec/mock_connection_spec.rb
|
146
152
|
- spec/response_spec.rb
|
data/lib/rspec/twirp/helpers.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
require "rspec/twirp/mock_client"
|
2
|
-
require "rspec/twirp/mock_connection"
|
3
|
-
|
4
|
-
module RSpec
|
5
|
-
module Twirp
|
6
|
-
module Helpers
|
7
|
-
def mock_twirp_connection(...)
|
8
|
-
RSpec::Twirp.mock_connection(...)
|
9
|
-
end
|
10
|
-
|
11
|
-
def mock_twirp_client(...)
|
12
|
-
RSpec::Twirp.mock_client(...)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,169 +0,0 @@
|
|
1
|
-
# expect {
|
2
|
-
# do_the_thing
|
3
|
-
# }.to make_twirp_request(client | service | rpc_method).with(request | attrs)
|
4
|
-
#
|
5
|
-
# expect(client).to make_twirp_request(rpc_method).with(...)
|
6
|
-
|
7
|
-
RSpec::Matchers.define :make_twirp_request do |*matchers|
|
8
|
-
chain :with do |input_matcher = nil|
|
9
|
-
@input_matcher = if input_matcher
|
10
|
-
if input_matcher.is_a?(Google::Protobuf::MessageExts)
|
11
|
-
defaults = input_matcher.class.new.to_h
|
12
|
-
hash_form = input_matcher.to_h.reject {|k,v| v == defaults[k] }
|
13
|
-
|
14
|
-
->(input) do
|
15
|
-
if input.is_a?(Google::Protobuf::MessageExts)
|
16
|
-
values_match?(input_matcher, input)
|
17
|
-
else
|
18
|
-
values_match?(include(**hash_form), input.to_h)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
elsif input_matcher.is_a?(Class) && input_matcher < Google::Protobuf::MessageExts
|
22
|
-
->(input) { values_match?(be_a(input_matcher), input) }
|
23
|
-
elsif input_matcher.is_a?(Hash)
|
24
|
-
->(input) { values_match?(include(**input_matcher), input.to_h) }
|
25
|
-
else
|
26
|
-
raise TypeError, "Expected an input_matcher of type `Google::Protobuf::MessageExts`, found #{input_matcher.class}"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
chain(:and_call_original) { @and_call_original = true }
|
32
|
-
chain(:and_return) do |arg|
|
33
|
-
@and_return = case arg
|
34
|
-
when Google::Protobuf::MessageExts
|
35
|
-
Twirp::ClientResp.new(arg, nil)
|
36
|
-
when Twirp::Error
|
37
|
-
Twirp::ClientResp.new(nil, arg)
|
38
|
-
when Class
|
39
|
-
if arg < Google::Protobuf::MessageExts
|
40
|
-
Twirp::ClientResp.new(arg.new, nil)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
unless @and_return
|
45
|
-
raise TypeError, "Expected type `Google::Protobuf::MessageExts`, found #{arg}"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
supports_block_expectations
|
50
|
-
|
51
|
-
match do |client_or_block|
|
52
|
-
@input_matcher ||= ->(*){ true }
|
53
|
-
|
54
|
-
if @and_call_original && @and_return
|
55
|
-
raise ArgumentError, "use `and_call_original` or `and_return`, but not both"
|
56
|
-
end
|
57
|
-
|
58
|
-
if client_or_block.is_a? Proc
|
59
|
-
RSpec::Mocks.with_temporary_scope do
|
60
|
-
match_block_request(client_or_block, matchers)
|
61
|
-
end
|
62
|
-
elsif client_or_block.is_a?(Twirp::Client)
|
63
|
-
match_client_request(client_or_block, matchers)
|
64
|
-
else
|
65
|
-
raise ArgumentError, "Expected Twirp::Client or block, found: #{client_or_block}"
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def match_block_request(block, matchers)
|
70
|
-
expected_client = be_a(Twirp::Client)
|
71
|
-
expected_service = anything
|
72
|
-
expected_rpc_name = anything
|
73
|
-
|
74
|
-
matchers.each do |matcher|
|
75
|
-
case matcher
|
76
|
-
when Twirp::Client
|
77
|
-
expected_client = be(matcher)
|
78
|
-
when Class
|
79
|
-
if matcher <= Twirp::Client
|
80
|
-
expected_client = be_a(matcher)
|
81
|
-
elsif matcher <= Twirp::Service
|
82
|
-
expected_service = matcher.service_full_name
|
83
|
-
else
|
84
|
-
raise TypeError
|
85
|
-
end
|
86
|
-
when String
|
87
|
-
expected_rpc_name = be(matcher.to_sym)
|
88
|
-
when Symbol
|
89
|
-
expected_rpc_name = be(matcher)
|
90
|
-
when Regexp
|
91
|
-
expected_rpc_name = matcher
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
@twirp_request_made = false
|
96
|
-
|
97
|
-
# stub pre-existing client instances
|
98
|
-
ObjectSpace.each_object(Twirp::Client) do |client|
|
99
|
-
if expected_client === client && (expected_service === client.class.service_full_name)
|
100
|
-
stub_client(client, expected_rpc_name)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# stub future client instances
|
105
|
-
ObjectSpace.each_object(Twirp::Client.singleton_class).select do |obj|
|
106
|
-
obj < Twirp::Client && obj != Twirp::ClientJSON
|
107
|
-
end.each do |client_type|
|
108
|
-
next unless client_type.name && expected_service === client_type.service_full_name
|
109
|
-
|
110
|
-
allow(client_type).to receive(:new).and_wrap_original do |orig, *args, **kwargs|
|
111
|
-
orig.call(*args, **kwargs).tap do |client|
|
112
|
-
if expected_client === client
|
113
|
-
stub_client(client, expected_rpc_name)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
block.call
|
120
|
-
|
121
|
-
@twirp_request_made
|
122
|
-
end
|
123
|
-
|
124
|
-
def stub_client(client, rpc_matcher)
|
125
|
-
allow(client).to receive(:rpc).and_wrap_original do |orig, rpc_name, input, req_opts|
|
126
|
-
if values_match?(rpc_matcher, rpc_name) && @input_matcher.call(input)
|
127
|
-
@twirp_request_made = true
|
128
|
-
end
|
129
|
-
|
130
|
-
if @and_call_original
|
131
|
-
orig.call(rpc_name, input, req_opts)
|
132
|
-
elsif @and_return
|
133
|
-
@and_return
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def match_client_request(client, matchers)
|
139
|
-
rpc_name = matchers.first.to_sym if matchers.any?
|
140
|
-
|
141
|
-
if rpc_name
|
142
|
-
rpc_info = client.class.rpcs.values.find do |x|
|
143
|
-
x[:rpc_method] == rpc_name || x[:ruby_method] == rpc_name
|
144
|
-
end
|
145
|
-
|
146
|
-
raise ArgumentError, "invalid rpc method: #{rpc_name}" unless rpc_info
|
147
|
-
|
148
|
-
msg = "Expected #{client} to make a twirp request to #{rpc_name}"
|
149
|
-
rpc_matcher = eq(rpc_info[:rpc_method])
|
150
|
-
else
|
151
|
-
rpc_info = nil
|
152
|
-
msg = "Expected #{client} to make a twirp request"
|
153
|
-
rpc_matcher = anything
|
154
|
-
end
|
155
|
-
|
156
|
-
expect(client).to receive(:rpc) do |rpc_name, input, req_opts|
|
157
|
-
expect(rpc_name).to match(rpc_matcher), msg
|
158
|
-
expect(@input_matcher.call(input)).to be(true), msg
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
description do
|
163
|
-
"make a Twirp request"
|
164
|
-
end
|
165
|
-
|
166
|
-
failure_message { @fail_msg || super() }
|
167
|
-
end
|
168
|
-
|
169
|
-
RSpec::Matchers.alias_matcher :make_a_twirp_request, :make_twirp_request
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# mock_twirp_client(Twirp::Client, { rpc => response } )
|
2
|
-
|
3
|
-
module RSpec
|
4
|
-
module Twirp
|
5
|
-
def mock_client(client, **responses)
|
6
|
-
unless client.is_a?(Class) && client < ::Twirp::Client
|
7
|
-
raise ArgumentError, "Expected Twirp::Client, found: #{client.class}"
|
8
|
-
end
|
9
|
-
|
10
|
-
rpcs = client.rpcs.values
|
11
|
-
|
12
|
-
client_instance = client.new(mock_connection)
|
13
|
-
|
14
|
-
unless responses.empty?
|
15
|
-
# validate input
|
16
|
-
responses.transform_keys! do |rpc_name|
|
17
|
-
rpc_info = rpcs.find do |x|
|
18
|
-
x[:rpc_method] == rpc_name || x[:ruby_method] == rpc_name
|
19
|
-
end
|
20
|
-
|
21
|
-
unless rpc_info
|
22
|
-
raise ArgumentError, "invalid rpc method: #{rpc_name}"
|
23
|
-
end
|
24
|
-
|
25
|
-
rpc_info[:rpc_method]
|
26
|
-
end
|
27
|
-
|
28
|
-
# repackage responses
|
29
|
-
client_responses = {}
|
30
|
-
responses.each do |rpc_method, response|
|
31
|
-
if response.is_a?(Hash)
|
32
|
-
response = client.rpcs[rpc_method.to_s][:output_class].new(**response)
|
33
|
-
end
|
34
|
-
|
35
|
-
client_responses[rpc_method] = RSpec::Twirp.generate_client_response(response)
|
36
|
-
end
|
37
|
-
|
38
|
-
# mock
|
39
|
-
rpcs.each do |info|
|
40
|
-
response = client_responses[info[:rpc_method]]
|
41
|
-
|
42
|
-
if response
|
43
|
-
allow(client_instance).to receive(:rpc).with(
|
44
|
-
info[:rpc_method],
|
45
|
-
any_args,
|
46
|
-
).and_return(response)
|
47
|
-
else
|
48
|
-
allow(client_instance).to receive(:rpc).with(
|
49
|
-
info[:rpc_method],
|
50
|
-
any_args,
|
51
|
-
).and_raise(::RSpec::Mocks::MockExpectationError)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
client_instance
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
# GoodbyeClient.new(mock_twirp_connection)
|
2
|
-
|
3
|
-
module RSpec
|
4
|
-
module Twirp
|
5
|
-
extend self
|
6
|
-
|
7
|
-
def mock_connection(response = nil)
|
8
|
-
if block_given? && response
|
9
|
-
raise ArgumentError, "can not specify both block and response"
|
10
|
-
end
|
11
|
-
|
12
|
-
Faraday.new do |conn|
|
13
|
-
conn.adapter :test do |stub|
|
14
|
-
stub.post(/.*/) do |env|
|
15
|
-
response = yield(env) if block_given?
|
16
|
-
response ||= {}
|
17
|
-
|
18
|
-
if response.is_a?(Hash)
|
19
|
-
# create default response
|
20
|
-
|
21
|
-
# determine which client would make this rpc call
|
22
|
-
service_full_name, rpc_method = env.url.path.split("/").last(2)
|
23
|
-
client = ObjectSpace.each_object(::Twirp::Client.singleton_class).find do |client|
|
24
|
-
next unless client.name
|
25
|
-
|
26
|
-
client.service_full_name == service_full_name && client.rpcs.key?(rpc_method)
|
27
|
-
end
|
28
|
-
|
29
|
-
unless client
|
30
|
-
raise TypeError, "could not determine Twirp::Client for: #{env.url.path}"
|
31
|
-
end
|
32
|
-
|
33
|
-
response = client.rpcs[rpc_method][:output_class].new(**response)
|
34
|
-
end
|
35
|
-
|
36
|
-
res = RSpec::Twirp.generate_client_response(response)
|
37
|
-
|
38
|
-
if res.data
|
39
|
-
status = 200
|
40
|
-
headers = { "Content-Type" => ::Twirp::Encoding::PROTO }
|
41
|
-
body = res.data.to_proto
|
42
|
-
else
|
43
|
-
status = ::Twirp::ERROR_CODES_TO_HTTP_STATUS[res.error.code]
|
44
|
-
headers = { "Content-Type" => ::Twirp::Encoding::JSON } # errors are always JSON
|
45
|
-
body = ::Twirp::Encoding.encode_json(res.error.to_h)
|
46
|
-
end
|
47
|
-
|
48
|
-
[ status, headers, body ]
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
data/spec/make_request_spec.rb
DELETED
@@ -1,181 +0,0 @@
|
|
1
|
-
describe "make_twirp_request" do
|
2
|
-
let(:client) { HelloWorldClient.new(conn) }
|
3
|
-
let(:conn) { mock_twirp_connection(response) }
|
4
|
-
let!(:other_client) { HelloWorldClient.new(conn) }
|
5
|
-
let(:request) { HelloRequest.new(name: "World", count: 3) }
|
6
|
-
let(:response) { HelloResponse.new(message: ["Hello", "Hello", "Hello World"]) }
|
7
|
-
|
8
|
-
def hello
|
9
|
-
client.hello(request)
|
10
|
-
end
|
11
|
-
|
12
|
-
describe "block mode" do
|
13
|
-
it { expect { hello }.to make_twirp_request }
|
14
|
-
|
15
|
-
it "returns nil" do
|
16
|
-
expect {
|
17
|
-
expect(hello).to be_nil
|
18
|
-
}.to make_twirp_request
|
19
|
-
end
|
20
|
-
|
21
|
-
context "with client instance matcher" do
|
22
|
-
it "matches a client instance" do
|
23
|
-
expect { hello }.to make_twirp_request(client)
|
24
|
-
end
|
25
|
-
|
26
|
-
it "matches a pre-existing client instance" do
|
27
|
-
expect {
|
28
|
-
other_client.hello(HelloRequest.new)
|
29
|
-
}.to make_twirp_request(other_client)
|
30
|
-
end
|
31
|
-
|
32
|
-
it "catches client mismaches" do
|
33
|
-
expect {
|
34
|
-
expect { hello }.to make_twirp_request(other_client)
|
35
|
-
}.to fail
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
context "with client class matcher" do
|
40
|
-
it "matches a client class" do
|
41
|
-
expect { hello }.to make_twirp_request(HelloWorldClient)
|
42
|
-
end
|
43
|
-
|
44
|
-
it "matches subclasses" do
|
45
|
-
expect { hello }.to make_twirp_request(Twirp::Client)
|
46
|
-
end
|
47
|
-
|
48
|
-
it "catches mismatches" do
|
49
|
-
expect {
|
50
|
-
expect { hello }.to make_twirp_request(GoodbyeClient)
|
51
|
-
}.to fail
|
52
|
-
end
|
53
|
-
|
54
|
-
it "catches type errors" do
|
55
|
-
expect {
|
56
|
-
expect { hello }.to make_twirp_request(Object)
|
57
|
-
}.to raise_error(TypeError)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
context "with rpc name matcher" do
|
62
|
-
it { expect { hello }.to make_twirp_request(:Hello) }
|
63
|
-
it { expect { hello }.to make_twirp_request("Hello") }
|
64
|
-
it { expect { hello }.to make_twirp_request(/^He/) }
|
65
|
-
|
66
|
-
it "catches mismatches" do
|
67
|
-
expect {
|
68
|
-
expect { hello }.to make_twirp_request(:Bye)
|
69
|
-
}.to fail
|
70
|
-
|
71
|
-
expect {
|
72
|
-
expect { hello }.to make_twirp_request(/B/)
|
73
|
-
}.to fail
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
context "with input matcher" do
|
78
|
-
it "matches messages" do
|
79
|
-
expect { hello }.to make_twirp_request.with(request)
|
80
|
-
end
|
81
|
-
|
82
|
-
it "matches message type" do
|
83
|
-
expect { hello }.to make_twirp_request.with(HelloRequest)
|
84
|
-
end
|
85
|
-
|
86
|
-
it "matches with attrs" do
|
87
|
-
expect { hello }.to make_twirp_request.with(count: 3)
|
88
|
-
end
|
89
|
-
|
90
|
-
context "with json request" do
|
91
|
-
it "matches messages" do
|
92
|
-
expect {
|
93
|
-
client.hello(name: "World")
|
94
|
-
}.to make_twirp_request.with(HelloRequest.new(name: "World"))
|
95
|
-
end
|
96
|
-
|
97
|
-
it "matches attrs" do
|
98
|
-
expect {
|
99
|
-
client.hello(name: "World")
|
100
|
-
}.to make_twirp_request.with(name: "World")
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
it "catches mismatches" do
|
105
|
-
expect {
|
106
|
-
expect { hello }.to make_twirp_request.with(count: 1)
|
107
|
-
}.to fail
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
context "with service matcher" do
|
112
|
-
it { expect { hello }.to make_twirp_request(HelloWorldService) }
|
113
|
-
|
114
|
-
it "catches mismatches" do
|
115
|
-
expect {
|
116
|
-
expect { hello }.to make_twirp_request(GoodbyeService)
|
117
|
-
}.to fail
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
describe ".and_call_original" do
|
122
|
-
it "calls original" do
|
123
|
-
expect {
|
124
|
-
expect(hello).to be_a_twirp_response(response)
|
125
|
-
}.to make_twirp_request.and_call_original
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
describe ".and_return" do
|
130
|
-
it "returns the specified value" do
|
131
|
-
expect {
|
132
|
-
expect(hello).to be_a_twirp_response(HelloRequest.new)
|
133
|
-
}.to make_twirp_request.and_return(HelloRequest.new)
|
134
|
-
end
|
135
|
-
|
136
|
-
it "returns the specified value" do
|
137
|
-
expect {
|
138
|
-
expect(hello).to be_a_twirp_response(HelloRequest.new)
|
139
|
-
}.to make_twirp_request.and_return(HelloRequest)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
describe "inline mode" do
|
145
|
-
after { hello }
|
146
|
-
|
147
|
-
it { expect(client).to make_twirp_request }
|
148
|
-
|
149
|
-
it "matches a specific rpc method" do
|
150
|
-
expect(client).to make_twirp_request(:hello)
|
151
|
-
end
|
152
|
-
|
153
|
-
it "matches a specific rpc method by rpc name" do
|
154
|
-
expect(client).to make_twirp_request(:Hello)
|
155
|
-
end
|
156
|
-
|
157
|
-
it "fails when client is not called within scope" do
|
158
|
-
expect_expectation_failure {
|
159
|
-
expect(client).to make_twirp_request
|
160
|
-
}
|
161
|
-
end
|
162
|
-
|
163
|
-
describe ".with" do
|
164
|
-
let(:request) { HelloRequest.new(name: "Daniel") }
|
165
|
-
|
166
|
-
it "matches the request message" do
|
167
|
-
expect(client).to make_twirp_request(:hello).with(request)
|
168
|
-
end
|
169
|
-
|
170
|
-
it "matches the request arguments" do
|
171
|
-
expect(client).to make_twirp_request(:hello).with(name: "Daniel")
|
172
|
-
end
|
173
|
-
|
174
|
-
it "fails when params don't match" do
|
175
|
-
expect_expectation_failure {
|
176
|
-
expect(client).to make_twirp_request.with(name: "Bob")
|
177
|
-
}
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
@@ -1,103 +0,0 @@
|
|
1
|
-
describe :mock_twirp_connection do
|
2
|
-
subject { client.bye(request) }
|
3
|
-
|
4
|
-
let(:client) { GoodbyeClient.new(conn) }
|
5
|
-
let(:request) { GoodbyeRequest.new }
|
6
|
-
let(:response) { GoodbyeResponse.new(**response_attrs) }
|
7
|
-
let(:response_attrs) { { message: "bye" } }
|
8
|
-
|
9
|
-
context "without a mock" do
|
10
|
-
let(:conn) { "http://localhost:3000/twirp/Goodbye/Bye" }
|
11
|
-
|
12
|
-
it { expect { subject }.to raise_error(Faraday::Error) }
|
13
|
-
end
|
14
|
-
|
15
|
-
describe "with a response instance" do
|
16
|
-
let(:conn) { mock_twirp_connection(response) }
|
17
|
-
|
18
|
-
it { is_expected.to be_a(Twirp::ClientResp) }
|
19
|
-
it { is_expected.to be_a_twirp_response }
|
20
|
-
it { is_expected.to be_a_twirp_response(response) }
|
21
|
-
it { is_expected.to be_a_twirp_response(message: "bye") }
|
22
|
-
|
23
|
-
it "catches mismatches" do
|
24
|
-
expect {
|
25
|
-
is_expected.to be_a_twirp_response(message: "nope")
|
26
|
-
}.to fail
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe "with a response type" do
|
31
|
-
let(:conn) { mock_twirp_connection(GoodbyeResponse) }
|
32
|
-
|
33
|
-
it { is_expected.to be_a_twirp_response(GoodbyeResponse) }
|
34
|
-
|
35
|
-
it "catches mismatches" do
|
36
|
-
expect {
|
37
|
-
is_expected.to be_a_twirp_response(HelloResponse)
|
38
|
-
}.to fail
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
describe "with default response" do
|
43
|
-
let(:conn) { mock_twirp_connection }
|
44
|
-
|
45
|
-
it { is_expected.to be_a_twirp_response(GoodbyeResponse) }
|
46
|
-
|
47
|
-
context "and with attrs" do
|
48
|
-
let(:conn) { mock_twirp_connection(message: "adios") }
|
49
|
-
|
50
|
-
it { is_expected.to be_a_twirp_response(message: "adios") }
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
describe "with an error" do
|
55
|
-
let(:conn) { mock_twirp_connection(error) }
|
56
|
-
let(:error) { Twirp::Error.not_found("nope") }
|
57
|
-
|
58
|
-
it { is_expected.to be_a_twirp_response.with_error(error) }
|
59
|
-
|
60
|
-
context "when error is symbol" do
|
61
|
-
let(:error) { :not_found }
|
62
|
-
|
63
|
-
it { is_expected.to be_a_twirp_response.with_error(404) }
|
64
|
-
it { is_expected.to be_a_twirp_response.with_error(:not_found) }
|
65
|
-
end
|
66
|
-
|
67
|
-
context "when error is integer" do
|
68
|
-
let(:error) { 500 }
|
69
|
-
|
70
|
-
it { is_expected.to be_a_twirp_response.with_error(500) }
|
71
|
-
it { is_expected.to be_a_twirp_response.with_error(:internal) }
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
describe "with a block" do
|
76
|
-
context "with a response object" do
|
77
|
-
let(:conn) { mock_twirp_connection { response } }
|
78
|
-
|
79
|
-
it { is_expected.to be_a_twirp_response(response) }
|
80
|
-
end
|
81
|
-
|
82
|
-
context "with response attrs" do
|
83
|
-
let(:conn) { mock_twirp_connection { response_attrs } }
|
84
|
-
|
85
|
-
it "determines the correct response type and incorporates the attrs" do
|
86
|
-
is_expected.to be_a_twirp_response(GoodbyeResponse, **response_attrs)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
context "with error" do
|
91
|
-
let(:conn) { mock_twirp_connection { error } }
|
92
|
-
let(:error) { Twirp::Error.not_found("nope") }
|
93
|
-
|
94
|
-
it { is_expected.to be_a_twirp_response.with_error(error) }
|
95
|
-
end
|
96
|
-
|
97
|
-
context "with error code" do
|
98
|
-
let(:conn) { mock_twirp_connection { :not_found } }
|
99
|
-
|
100
|
-
it { is_expected.to be_a_twirp_response.with_error(:not_found) }
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|