webmock-twirp 0.0.1 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +76 -8
- data/lib/webmock/twirp/refinements.rb +11 -0
- data/lib/webmock/twirp/request_stub.rb +61 -16
- data/lib/webmock/twirp/version.rb +1 -1
- data/lib/webmock/twirp.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 944a35bac7c3e752f543bc37f6d2b0a66a1a7f771022ac28c9c30ddba2e92891
|
4
|
+
data.tar.gz: db6bfad348186e05d483d6d09c485fd470679e3978fcca131e93d5fcee6649de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b7fb99d4bf12cad35620ef9bb22bd7faabd626254c6e5a307b27da7478091eaf88256d0fc902cb507311312837c52ecc0b238796cedc0153674dbb34db69308
|
7
|
+
data.tar.gz: 8f4bf9c6f3b828843e2cc8167c4b47e7ccda55a56dda1c678f5b1cf7e2b0eba01207e71572d08e13004e7c031f5ef950160f61a907ffffefbbec862be7d1918b
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -2,27 +2,95 @@ WebMock::Twirp
|
|
2
2
|
======
|
3
3
|
Twirp support for [WebMock](https://github.com/bblimke/webmock). All our favorite http request stubbing for Twirp RPCs - message and error serialization done automatically.
|
4
4
|
|
5
|
+
### Install
|
6
|
+
```ruby
|
7
|
+
gem "webmock-twirp"
|
8
|
+
```
|
5
9
|
|
10
|
+
### Example
|
6
11
|
```ruby
|
7
|
-
require "webmock
|
12
|
+
require "webmock/twirp"
|
13
|
+
|
14
|
+
it "stubs twirp calls" do
|
15
|
+
stub_twirp_request
|
16
|
+
|
17
|
+
client.my_rpc_method(request)
|
18
|
+
end
|
8
19
|
|
9
|
-
|
20
|
+
it "matches calls from specific twirp clients and rpc methods" do
|
21
|
+
stub_twirp_request(MyTwirpClient, :optional_rpc_method)
|
22
|
+
end
|
10
23
|
|
11
|
-
|
24
|
+
# match parameters
|
25
|
+
stub_twirp_request.with(my_request_message: /^foo/)
|
12
26
|
|
13
27
|
# or use block mode
|
14
|
-
stub_twirp_request
|
28
|
+
stub_twirp_request.with do |request|
|
15
29
|
request # the Twirp request, aka. proto message, used to initiate the request
|
16
30
|
request.my_request_message == "hello"
|
17
31
|
end
|
18
32
|
|
19
33
|
|
20
|
-
|
21
|
-
stub_twirp_request
|
34
|
+
# stub responses
|
35
|
+
stub_twirp_request.and_return(return_message: "yo yo")
|
36
|
+
stub_twirp_request.and_return(404) # results in a Twirp::Error.not_found
|
22
37
|
|
23
38
|
# or use block mode
|
24
|
-
stub_twirp_request
|
25
|
-
{ response_message: "oh hi" } # will get properly packaged up
|
39
|
+
stub_twirp_request.and_return do |request|
|
40
|
+
{ response_message: "oh hi" } # will get properly packaged up
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
|
45
|
+
## Usage
|
46
|
+
|
47
|
+
### .with
|
48
|
+
`stub_twirp_request.with` allows you to only stub requests which match specific attributes. It accepts a hash or a `Google::Protobuf::MessageExts` instance. The hash supports constants, regexes, and rspec matchers.
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
stub_twirp_request.with(message: "hi")
|
52
|
+
stub_twirp_request.with(message: /^h/)
|
53
|
+
stub_twirp_request.with(message: include("i"))
|
54
|
+
|
55
|
+
expected_request = MyTwirpRequest.new(message: "hi")
|
56
|
+
stub_twirp_request.with(expected_request)
|
57
|
+
```
|
58
|
+
|
59
|
+
|
60
|
+
If you want even more control over the matching criteria, use the block mode. A `Protobuf` instance is passed into the block with the request's parameters.
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
stub_twirp_request.with do |request|
|
64
|
+
request.message == "hi"
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
|
69
|
+
### .to_return
|
70
|
+
`stub_twirp_request.to_return` allows you to specify a response, or use a default response. It can be a hash or `Protobuf` instance. To return an error, specify an error code, http status, or `Twirp::Error`.
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
stub_twirp_request.to_return # ie. `MyTwirpResponse.new`
|
74
|
+
|
75
|
+
stub_twirp_request.to_return(msg: "bye")
|
76
|
+
|
77
|
+
response = MyTwirpResponse.new(msg: "bye")
|
78
|
+
stub_twirp_request.to_return(response)
|
79
|
+
|
80
|
+
# errors
|
81
|
+
stub_twirp_request.to_return(:not_found)
|
82
|
+
stub_twirp_request.to_return(404)
|
83
|
+
stub_twirp_request.to_return(Twirp::Error.not_found("Nope"))
|
84
|
+
```
|
85
|
+
|
86
|
+
The block mode passes in the request Protobuf.
|
87
|
+
```ruby
|
88
|
+
stub_twirp_request.to_return do |request|
|
89
|
+
if request.message == "hi"
|
90
|
+
{ msg: "bye" }
|
91
|
+
else
|
92
|
+
:not_found
|
93
|
+
end
|
26
94
|
end
|
27
95
|
```
|
28
96
|
|
@@ -1,29 +1,59 @@
|
|
1
1
|
module WebMock
|
2
2
|
module Twirp
|
3
3
|
class RequestStub < WebMock::RequestStub
|
4
|
-
|
5
|
-
klass = client_or_service.is_a?(Class) ? client_or_service : client_or_service.class
|
4
|
+
using Refinements
|
6
5
|
|
7
|
-
|
8
|
-
|
6
|
+
def initialize(*filters)
|
7
|
+
rpc_name = filters.snag { |x| x.is_a?(Symbol) }
|
8
|
+
|
9
|
+
client = filters.snag { |x| x.is_a?(::Twirp::Client) }
|
10
|
+
|
11
|
+
klass = client&.class
|
12
|
+
klass ||= filters.snag do |x|
|
13
|
+
x.is_a?(Class) && (x < ::Twirp::Client || x < ::Twirp::Service)
|
14
|
+
end
|
15
|
+
|
16
|
+
unless filters.empty?
|
17
|
+
raise ArgumentError, "unexpected arguments: #{filters}"
|
18
|
+
end
|
19
|
+
|
20
|
+
uri = ""
|
21
|
+
|
22
|
+
if client
|
23
|
+
conn = client.instance_variable_get(:@conn)
|
24
|
+
uri += conn.url_prefix.to_s if conn
|
9
25
|
end
|
10
26
|
|
11
|
-
|
12
|
-
|
27
|
+
if klass
|
28
|
+
@rpcs = klass.rpcs
|
29
|
+
uri += "/#{klass.service_full_name}"
|
30
|
+
else
|
31
|
+
uri += "/[^/]+"
|
32
|
+
end
|
13
33
|
|
14
34
|
if rpc_name
|
15
|
-
|
16
|
-
|
17
|
-
|
35
|
+
if klass
|
36
|
+
# kindly convert ruby method to rpc method name
|
37
|
+
rpc_info = klass.rpcs.values.find do |x|
|
38
|
+
x[:rpc_method] == rpc_name || x[:ruby_method] == rpc_name
|
39
|
+
end
|
18
40
|
|
19
|
-
|
41
|
+
raise ArgumentError, "invalid rpc method: #{rpc_name}" unless rpc_info
|
20
42
|
|
21
|
-
|
43
|
+
uri += "/#{rpc_info[:rpc_method]}"
|
44
|
+
else
|
45
|
+
uri += "/#{rpc_name}"
|
46
|
+
end
|
22
47
|
else
|
23
48
|
uri += "/[^/]+"
|
24
49
|
end
|
25
50
|
|
26
51
|
super(:post, /#{uri}$/)
|
52
|
+
|
53
|
+
# filter on Twirp header
|
54
|
+
@request_pattern.with(
|
55
|
+
headers: { "Content-Type" => ::Twirp::Encoding::PROTO },
|
56
|
+
)
|
27
57
|
end
|
28
58
|
|
29
59
|
def with(request = nil, **attrs, &block)
|
@@ -87,6 +117,7 @@ module WebMock
|
|
87
117
|
|
88
118
|
super(*response_hashes, &decoder)
|
89
119
|
end
|
120
|
+
alias_method :and_return, :to_return # update existing alias
|
90
121
|
|
91
122
|
def to_return_json(*)
|
92
123
|
raise NotImplementedError
|
@@ -94,10 +125,24 @@ module WebMock
|
|
94
125
|
|
95
126
|
private
|
96
127
|
|
97
|
-
attr_reader :rpcs
|
98
|
-
|
99
128
|
def rpc_from_request(request_signature)
|
100
|
-
|
129
|
+
service_full_name, rpc_name = request_signature.uri.path.split("/").last(2)
|
130
|
+
|
131
|
+
rpcs = @rpcs || begin
|
132
|
+
# find matching client instance
|
133
|
+
client = ObjectSpace.each_object(::Twirp::Client).find do |client|
|
134
|
+
service_full_name == client.class.service_full_name && \
|
135
|
+
client.class.rpcs.key?(rpc_name)
|
136
|
+
end
|
137
|
+
|
138
|
+
unless client
|
139
|
+
raise "could not determine Twirp::Client for call to: #{service_full_name}/#{rpc_name}"
|
140
|
+
end
|
141
|
+
|
142
|
+
client.class.rpcs
|
143
|
+
end
|
144
|
+
|
145
|
+
rpcs[rpc_name]
|
101
146
|
end
|
102
147
|
|
103
148
|
def generate_http_response(msg_class, obj)
|
@@ -124,10 +169,10 @@ module WebMock
|
|
124
169
|
if code = ::Twirp::ERROR_CODES_TO_HTTP_STATUS.key(obj)
|
125
170
|
::Twirp::Error.new(code, code)
|
126
171
|
else
|
127
|
-
raise ArgumentError, "invalid error
|
172
|
+
raise ArgumentError, "invalid http error status: #{obj}"
|
128
173
|
end
|
129
174
|
else
|
130
|
-
raise
|
175
|
+
raise ArgumentError, "can not generate twirp reponse from: #{obj}"
|
131
176
|
end
|
132
177
|
|
133
178
|
if res.is_a?(Google::Protobuf::MessageExts)
|
data/lib/webmock/twirp.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "google/protobuf"
|
2
2
|
require "twirp"
|
3
3
|
require "webmock"
|
4
|
+
require "webmock/twirp/refinements"
|
4
5
|
require "webmock/twirp/request_stub"
|
5
6
|
require "webmock/twirp/version"
|
6
7
|
|
@@ -30,8 +31,7 @@ if $LOADED_FEATURES.find { |x| x =~ %r{/webmock/rspec.rb} }
|
|
30
31
|
# require "webmock/rspec"
|
31
32
|
RSpec.configure { |c| c.include WebMock::Twirp::API }
|
32
33
|
else
|
33
|
-
# patch
|
34
|
-
|
34
|
+
# patch WebMock to also export stub_twirp_request
|
35
35
|
module WebMock
|
36
36
|
module API
|
37
37
|
include WebMock::Twirp::API
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: webmock-twirp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
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-10-
|
11
|
+
date: 2022-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: webmock
|
@@ -105,6 +105,7 @@ files:
|
|
105
105
|
- README.md
|
106
106
|
- lib/webmock-twirp.rb
|
107
107
|
- lib/webmock/twirp.rb
|
108
|
+
- lib/webmock/twirp/refinements.rb
|
108
109
|
- lib/webmock/twirp/request_stub.rb
|
109
110
|
- lib/webmock/twirp/version.rb
|
110
111
|
- webmock-twirp.gemspec
|