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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 165be6973cc98a0dcfb538746766610afa45c02a344bf3c79f0567c36ab92d4c
4
- data.tar.gz: 65a3021683eff819b8a5e1ca6e54d8d4eed63ed9364fd2631cb5308772243ade
3
+ metadata.gz: 944a35bac7c3e752f543bc37f6d2b0a66a1a7f771022ac28c9c30ddba2e92891
4
+ data.tar.gz: db6bfad348186e05d483d6d09c485fd470679e3978fcca131e93d5fcee6649de
5
5
  SHA512:
6
- metadata.gz: e5c02e2bfbe249a15af9aa36b1701e894550a330a72da318bec451a142e2d053ce40bc7c112e43057f1f216c8a0429dc3a670b8c112d136cd167ab482dbc9585
7
- data.tar.gz: 6e1839bcd0cf51cb664cdda48408e8bcb89aec4dfbe60ba142cdd33f19b3462257ed56b5096fd9f338996257ec76b5121a2a8028f9e2ae848d2b1e79efd2d433
6
+ metadata.gz: 7b7fb99d4bf12cad35620ef9bb22bd7faabd626254c6e5a307b27da7478091eaf88256d0fc902cb507311312837c52ecc0b238796cedc0153674dbb34db69308
7
+ data.tar.gz: 8f4bf9c6f3b828843e2cc8167c4b47e7ccda55a56dda1c678f5b1cf7e2b0eba01207e71572d08e13004e7c031f5ef950160f61a907ffffefbbec862be7d1918b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ### v0.1.1 (2022-10-11)
2
+ - test coverage
3
+ - error messages
4
+ - fix and_return alias
5
+ - Update README.md
6
+
7
+ ### v0.1.0 (2022-10-09)
8
+ - dynamic client/rpc lookup
9
+
1
10
  ### v0.0.1 (2022-10-07)
2
11
  - stub_twirp_request
3
12
 
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-twirp"
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
- stub_twirp_request(MyTwirpClient, :optional_rpc_method)
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
- stub_twirp_request(...).with(my_request_message: /^foo/)
24
+ # match parameters
25
+ stub_twirp_request.with(my_request_message: /^foo/)
12
26
 
13
27
  # or use block mode
14
- stub_twirp_request(...).with do |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
- stub_twirp_request(...).and_return(return_message: "yo yo")
21
- stub_twirp_request(...).and_return(404) # results in a Twirp::Error.not_found
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(...).and_return do |request|
25
- { response_message: "oh hi" } # will get properly packaged up automagically
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
 
@@ -0,0 +1,11 @@
1
+ module WebMock
2
+ module Twirp
3
+ module Refinements
4
+ refine Array do
5
+ def snag(&block)
6
+ find(&block)&.tap { |x| delete(x) }
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,29 +1,59 @@
1
1
  module WebMock
2
2
  module Twirp
3
3
  class RequestStub < WebMock::RequestStub
4
- def initialize(client_or_service, rpc_name = nil)
5
- klass = client_or_service.is_a?(Class) ? client_or_service : client_or_service.class
4
+ using Refinements
6
5
 
7
- unless klass < ::Twirp::Client || klass < ::Twirp::Service
8
- raise TypeError, "expected Twirp Client or Service, found: #{client_or_service}"
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
- @rpcs = klass.rpcs
12
- uri = "/#{klass.service_full_name}"
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
- rpc_info = rpcs.values.find do |x|
16
- x[:rpc_method] == rpc_name.to_sym || x[:ruby_method] == rpc_name.to_sym
17
- end
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
- raise ArgumentError, "invalid rpc method: #{rpc_name}" unless rpc_info
41
+ raise ArgumentError, "invalid rpc method: #{rpc_name}" unless rpc_info
20
42
 
21
- uri += "/#{rpc_info[:rpc_method]}"
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
- rpcs[request_signature.uri.path.split("/").last]
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 code: #{obj}"
172
+ raise ArgumentError, "invalid http error status: #{obj}"
128
173
  end
129
174
  else
130
- raise NotImplementedError
175
+ raise ArgumentError, "can not generate twirp reponse from: #{obj}"
131
176
  end
132
177
 
133
178
  if res.is_a?(Google::Protobuf::MessageExts)
@@ -1,5 +1,5 @@
1
1
  module WebMock
2
2
  module Twirp
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.1"
4
4
  end
5
5
  end
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 Webmock to also export stub_twirp_request
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.0.1
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-08 00:00:00.000000000 Z
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