webmock-twirp 0.0.1 → 0.1.1
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/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
|