gapic-generator 0.7.5 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +45 -0
  3. data/lib/gapic/generator/version.rb +1 -1
  4. data/lib/gapic/generators/default_generator.rb +11 -1
  5. data/lib/gapic/generators/default_generator_parameters.rb +3 -1
  6. data/lib/gapic/presenters.rb +2 -0
  7. data/lib/gapic/presenters/gem_presenter.rb +63 -10
  8. data/lib/gapic/presenters/method/rest_pagination_info.rb +246 -0
  9. data/lib/gapic/presenters/method_presenter.rb +21 -2
  10. data/lib/gapic/presenters/method_rest_presenter.rb +70 -4
  11. data/lib/gapic/presenters/resource_presenter.rb +8 -0
  12. data/lib/gapic/presenters/service_config_presenter.rb +48 -0
  13. data/lib/gapic/presenters/service_presenter.rb +69 -0
  14. data/lib/gapic/presenters/service_rest_presenter.rb +36 -28
  15. data/lib/gapic/presenters/snippet_presenter.rb +103 -0
  16. data/lib/gapic/schema/api.rb +32 -8
  17. data/lib/gapic/schema/request_param_parser.rb +2 -2
  18. data/lib/gapic/schema/wrappers.rb +26 -0
  19. data/templates/default/gem/readme.erb +3 -3
  20. data/templates/default/lib/rest/_rest.erb +0 -2
  21. data/templates/default/service/client/_client.erb +18 -20
  22. data/templates/default/service/client/_config.erb +13 -14
  23. data/templates/default/service/client/_credentials.erb +2 -0
  24. data/templates/default/service/client/_operations.erb +1 -1
  25. data/templates/default/service/client/_paths.erb +1 -1
  26. data/templates/default/service/client/_self_configure_defaults.erb +2 -2
  27. data/templates/default/service/client/method/_def.erb +2 -0
  28. data/templates/default/service/client/method/def/_options_defaults.erb +3 -1
  29. data/templates/default/service/client/method/docs/_deprecated.erb +5 -0
  30. data/templates/default/service/client/method/docs/_snippets.erb +6 -0
  31. data/templates/default/service/rest/client/_client.erb +15 -24
  32. data/templates/default/service/rest/client/_config.erb +48 -0
  33. data/templates/default/service/rest/client/method/_def.erb +1 -1
  34. data/templates/default/service/rest/client/method/def/_options_defaults.erb +7 -3
  35. data/templates/default/service/rest/client/method/def/_response.erb +6 -0
  36. data/templates/default/service/rest/client/method/def/_response_normal.erb +4 -15
  37. data/templates/default/service/rest/client/method/def/_response_paged.erb +7 -0
  38. data/templates/default/service/rest/client/method/docs/_result.erb +3 -3
  39. data/templates/default/service/rest/service_stub.erb +6 -0
  40. data/templates/default/service/rest/service_stub/_service_stub.erb +25 -0
  41. data/templates/default/service/rest/{grpc_transcoding/method → service_stub/grpc_transcoding_method}/_def.erb +4 -1
  42. data/templates/default/service/rest/{grpc_transcoding/method → service_stub/grpc_transcoding_method}/def/_query_string_param.erb +0 -0
  43. data/templates/default/service/rest/service_stub/method/_def.erb +20 -0
  44. data/templates/default/service/rest/service_stub/method/def/_request.erb +2 -0
  45. data/templates/default/service/rest/service_stub/method/def/_response.erb +17 -0
  46. data/templates/default/service/rest/test/client.erb +18 -0
  47. data/templates/default/service/rest/test/method/_assert_response.erb +2 -0
  48. data/templates/default/service/rest/test/method/_configure.erb +19 -0
  49. data/templates/default/service/rest/test/method/_normal.erb +71 -0
  50. data/templates/default/service/rest/test/method/_setup.erb +38 -0
  51. data/templates/default/service/test/client_paths.erb +1 -1
  52. data/templates/default/snippets/gemfile.erb +17 -0
  53. data/templates/default/snippets/snippet/_structure.erb +71 -0
  54. data/templates/default/snippets/standalone.erb +6 -0
  55. metadata +29 -12
  56. data/templates/default/service/client/_self_configure_retry_policy.erb +0 -15
  57. data/templates/default/service/rest/client/_requires.erb +0 -1
  58. data/templates/default/service/rest/grpc_transcoding/_grpc_transcoding.erb +0 -9
@@ -25,5 +25,7 @@ metadata[:"x-goog-request-params"] ||= request_params_header
25
25
  options.apply_defaults timeout: @config.rpcs.<%= method.name %>.timeout,
26
26
  metadata: metadata,
27
27
  retry_policy: @config.rpcs.<%= method.name %>.retry_policy
28
- options.apply_defaults metadata: @config.metadata,
28
+
29
+ options.apply_defaults timeout: @config.timeout,
30
+ metadata: @config.metadata,
29
31
  retry_policy: @config.retry_policy
@@ -0,0 +1,5 @@
1
+ <%- assert_locals method -%>
2
+ <%- if method.is_deprecated? -%>
3
+ # @deprecated This method is deprecated and may be removed in the next major version update.
4
+ #
5
+ <%- end -%>
@@ -0,0 +1,6 @@
1
+ <%- assert_locals method -%>
2
+ <%- if method.generate_yardoc_snippets? -%>
3
+ # @example Basic example
4
+ <%= indent render(partial: "snippets/snippet/structure", locals: { snippet: method.snippet }), "# " %>
5
+ #
6
+ <%- end -%>
@@ -2,6 +2,7 @@
2
2
  <% @requires = capture do %>
3
3
  <%= render partial: "service/client/requires", locals: { service: service} -%>
4
4
  require "<%= service.proto_service_require %>"
5
+ require "<%= service.rest.service_stub_require %>"
5
6
  <% end %>
6
7
  ##
7
8
  # REST client for the <%= service.name %> service.
@@ -11,7 +12,6 @@
11
12
  #
12
13
  <%- end -%>
13
14
  class <%= service.rest.client_name %>
14
- include <%= service.rest.transcoding_helper_name %>
15
15
  <%- if service.paths? -%>
16
16
  include <%= service.paths_name %>
17
17
  <%- end -%>
@@ -25,13 +25,12 @@ class <%= service.rest.client_name %>
25
25
  # See {<%= service.rest.client_name_full %>::Configuration}
26
26
  # for a description of the configuration fields.
27
27
  #
28
- # ## Example
28
+ # @example
29
29
  #
30
- # To modify the configuration for all <%= service.name %> clients:
31
- #
32
- # <%= service.rest.client_name_full %>.configure do |config|
33
- # config.timeout = 10.0
34
- # end
30
+ # # Modify the configuration for all <%= service.name %> clients
31
+ # <%= service.rest.client_name_full %>.configure do |config|
32
+ # config.timeout = 10.0
33
+ # end
35
34
  #
36
35
  # @yield [config] Configure the <%= service.rest.client_name %> client.
37
36
  # @yieldparam config [<%= service.rest.client_name %>::Configuration]
@@ -65,28 +64,20 @@ class <%= service.rest.client_name %>
65
64
  ##
66
65
  # Create a new <%= service.name %> REST client object.
67
66
  #
68
- # ## Examples
69
- #
70
- # To create a new <%= service.name %> REST client with the default
71
- # configuration:
67
+ # @example
72
68
  #
73
- # client = <%= service.rest.client_name_full %>.new
69
+ # # Create a client using the default configuration
70
+ # client = <%= service.rest.client_name_full %>.new
74
71
  #
75
- # To create a new <%= service.name %> REST client with a custom
76
- # configuration:
77
- #
78
- # client = <%= service.rest.client_name_full %>.new do |config|
79
- # config.timeout = 10.0
80
- # end
72
+ # # Create a client using a custom configuration
73
+ # client = <%= service.rest.client_name_full %>.new do |config|
74
+ # config.timeout = 10.0
75
+ # end
81
76
  #
82
77
  # @yield [config] Configure the <%= service.name %> client.
83
78
  # @yieldparam config [<%= service.rest.client_name %>::Configuration]
84
79
  #
85
80
  def initialize
86
- # These require statements are intentionally placed here to initialize
87
- # the REST modules only when it's required.
88
- require "gapic/rest"
89
-
90
81
  # Create the configuration object
91
82
  @config = Configuration.new <%= service.rest.client_name %>.configure
92
83
 
@@ -97,12 +88,12 @@ class <%= service.rest.client_name %>
97
88
  credentials = @config.credentials
98
89
  <%- unless service.generic_endpoint? -%>
99
90
  credentials ||= Credentials.default scope: @config.scope
100
- if credentials.is_a?(String) || credentials.is_a?(Hash)
91
+ if credentials.is_a?(::String) || credentials.is_a?(::Hash)
101
92
  credentials = Credentials.new credentials, scope: @config.scope
102
93
  end
103
94
  <%- end -%>
104
95
 
105
- @client_stub = ::Gapic::Rest::ClientStub.new endpoint: @config.endpoint, credentials: credentials
96
+ @<%= service.stub_name %> = <%= service.rest.service_stub_name_full %>.new endpoint: @config.endpoint, credentials: credentials
106
97
  end
107
98
 
108
99
  # Service calls
@@ -51,6 +51,9 @@
51
51
  # @!attribute [rw] timeout
52
52
  # The call timeout in seconds.
53
53
  # @return [::Numeric]
54
+ # @!attribute [rw] metadata
55
+ # Additional REST headers to be sent with the call.
56
+ # @return [::Hash{::Symbol=>::String}]
54
57
  #
55
58
  class Configuration
56
59
  extend ::Gapic::Config
@@ -64,6 +67,7 @@ class Configuration
64
67
  config_attr :lib_name, nil, ::String, nil
65
68
  config_attr :lib_version, nil, ::String, nil
66
69
  config_attr :timeout, nil, ::Numeric, nil
70
+ config_attr :metadata, nil, ::Hash, nil
67
71
 
68
72
  # @private
69
73
  def initialize parent_config = nil
@@ -71,4 +75,48 @@ class Configuration
71
75
 
72
76
  yield self if block_given?
73
77
  end
78
+
79
+ ##
80
+ # Configurations for individual RPCs
81
+ # @return [Rpcs]
82
+ #
83
+ def rpcs
84
+ @rpcs ||= begin
85
+ parent_rpcs = nil
86
+ parent_rpcs = @parent_config.rpcs if defined?(@parent_config) && @parent_config.respond_to?(:rpcs)
87
+ Rpcs.new parent_rpcs
88
+ end
89
+ end
90
+
91
+ ##
92
+ # Configuration RPC class for the <%= service.name %> API.
93
+ #
94
+ # Includes fields providing the configuration for each RPC in this service.
95
+ # Each configuration object is of type `Gapic::Config::Method` and includes
96
+ # the following configuration fields:
97
+ #
98
+ # * `timeout` (*type:* `Numeric`) - The call timeout in seconds
99
+ #
100
+ # there is one other field (`retry_policy`) that can be set
101
+ # but is currently not supported for REST Gapic libraries.
102
+ #
103
+ class Rpcs
104
+ <%- method_service.methods.each do |method| -%>
105
+ ##
106
+ # RPC-specific configuration for `<%= method.name %>`
107
+ # @return [::Gapic::Config::Method]
108
+ #
109
+ attr_reader :<%= method.name %>
110
+ <%- end -%>
111
+
112
+ # @private
113
+ def initialize parent_rpcs = nil
114
+ <%- method_service.methods.each do |method| -%>
115
+ <%= method.name %>_config = parent_rpcs.<%= method.name %> if parent_rpcs.respond_to? :<%= method.name %>
116
+ @<%= method.name %> = ::Gapic::Config::Method.new <%= method.name %>_config
117
+ <%- end -%>
118
+
119
+ yield self if block_given?
120
+ end
121
+ end
74
122
  end
@@ -13,6 +13,6 @@ def <%= method.name %> request, options = nil
13
13
 
14
14
  <%= indent render(partial: "service/rest/client/method/def/options_defaults", locals: { method: method }), 2 %>
15
15
 
16
- <%= indent render(partial: "service/rest/client/method/def/response_normal", locals: { method: method }), 2 %>
16
+ <%= indent render(partial: "service/rest/client/method/def/response", locals: { method: method }), 2 %>
17
17
  <%= render partial: "service/rest/client/method/def/rescue", locals: { method: method } -%>
18
18
  end
@@ -3,12 +3,16 @@
3
3
  options = ::Gapic::CallOptions.new(**options.to_h) if options.respond_to? :to_h
4
4
 
5
5
  # Customize the options with defaults
6
- call_metadata = {}
6
+ call_metadata = @config.rpcs.<%= method.name %>.metadata.to_h
7
7
 
8
8
  # Set x-goog-api-client header
9
9
  call_metadata[:"x-goog-api-client"] ||= ::Gapic::Headers.x_goog_api_client \
10
10
  lib_name: @config.lib_name, lib_version: @config.lib_version,
11
- gapic_version: ::<%= method.service.gem.version_name_full %>
11
+ gapic_version: ::<%= method.service.gem.version_name_full %>,
12
+ transports_version_send: [:rest]
12
13
 
13
- options.apply_defaults timeout: @config.timeout,
14
+ options.apply_defaults timeout: @config.rpcs.<%= method.name %>.timeout,
14
15
  metadata: call_metadata
16
+
17
+ options.apply_defaults timeout: @config.timeout,
18
+ metadata: @config.metadata
@@ -0,0 +1,6 @@
1
+ <%- assert_locals method -%>
2
+ <%- if method.rest.paged? -%>
3
+ <%= render partial: "service/rest/client/method/def/response_paged", locals: { method: method } -%>
4
+ <%- else -%>
5
+ <%= render partial: "service/rest/client/method/def/response_normal", locals: { method: method } -%>
6
+ <%- end -%>
@@ -1,17 +1,6 @@
1
1
  <%- assert_locals method -%>
2
2
 
3
- uri, <%= method.rest.body_var_name %>, <%= method.rest.query_string_params_var_name %> = <%= method.rest.transcoding_helper_name %> request
4
- response = @client_stub.make_<%= method.rest.verb %>_request(
5
- uri: uri,
6
- <%- if method.rest.body? -%>
7
- body: body,
8
- <%- end -%>
9
- <%- if method.rest.query_string_params? -%>
10
- params: query_string_params,
11
- <%- end -%>
12
- options: options
13
- )
14
- result = <%= method.return_type %>.decode_json response.body, ignore_unknown_fields: true
15
-
16
- yield result, response if block_given?
17
- result
3
+ @<%= method.service.stub_name %>.<%= method.name %> request, options do |result, response|
4
+ yield result, response if block_given?
5
+ return result
6
+ end
@@ -0,0 +1,7 @@
1
+ <%- assert_locals method -%>
2
+
3
+ @<%= method.service.stub_name %>.<%= method.name %> request, options do |result, response|
4
+ result = ::Gapic::Rest::PagedEnumerable.new @<%= method.service.stub_name %>, :<%= method.name %>, "<%= method.rest.pagination.response_repeated_field_name %>", request, result, options
5
+ yield result, response if block_given?
6
+ return result
7
+ end
@@ -1,6 +1,6 @@
1
1
  <%- assert_locals method -%>
2
- # @yield [result, env] Access the result along with the Faraday environment object
3
- # @yieldparam result [<%= method.doc_response_type %>]
2
+ # @yield [result, response] Access the result along with the Faraday response object
3
+ # @yieldparam result [<%= method.rest.doc_response_type %>]
4
4
  # @yieldparam response [::Faraday::Response]
5
5
  #
6
- # @return [<%= method.doc_response_type %>]
6
+ # @return [<%= method.rest.doc_response_type %>]
@@ -0,0 +1,6 @@
1
+ <%- assert_locals service -%>
2
+ <%= render partial: "service/rest/service_stub/service_stub",
3
+ layout: "layouts/ruby",
4
+ locals: { service: service,
5
+ namespace: service.rest.service_name_full }
6
+ %>
@@ -0,0 +1,25 @@
1
+ <%- assert_locals service -%>
2
+ <% @requires = capture do %>
3
+ require "<%= service.proto_service_require %>"
4
+ <% end %>
5
+ ##
6
+ # REST service stub for the <%= service.name %> service.
7
+ # service stub contains baseline method implementations
8
+ # including transcoding, making the REST call and deserialing the response
9
+ #
10
+ class <%= service.rest.service_stub_name %>
11
+ def initialize endpoint:, credentials:
12
+ # These require statements are intentionally placed here to initialize
13
+ # the REST modules only when it's required.
14
+ require "gapic/rest"
15
+
16
+ @client_stub = ::Gapic::Rest::ClientStub.new endpoint: endpoint, credentials: credentials
17
+ end
18
+
19
+ <%- service.methods.each do |method| -%>
20
+
21
+ <%= indent_tail render(partial: "service/rest/service_stub/method/def", locals: { method: method }), 2 %>
22
+
23
+ <%= indent_tail render(partial: "service/rest/service_stub/grpc_transcoding_method/def", locals: { method: method }), 2 %>
24
+ <%- end %>
25
+ end
@@ -1,4 +1,7 @@
1
1
  <%- assert_locals method -%>
2
+ ##
3
+ # GRPC transcoding helper method for the <%= method.name %> REST call
4
+ #
2
5
  # @param request_pb [<%= method.request_type %>]
3
6
  # A request object representing the call parameters. Required.
4
7
  # @return [Array(String, [String, nil], Hash{String => String})]
@@ -13,7 +16,7 @@ def <%= method.rest.transcoding_helper_name %> request_pb
13
16
  query_string_params = {}
14
17
  <%- if method.rest.query_string_params? -%>
15
18
  <%- method.rest.query_string_params.each do |field| -%>
16
- <%= render partial: "service/rest/grpc_transcoding/method/def/query_string_param", locals: { field: field } -%>
19
+ <%= render partial: "service/rest/service_stub/grpc_transcoding_method/def/query_string_param", locals: { field: field } -%>
17
20
  <%- end -%>
18
21
  <%- end -%>
19
22
 
@@ -0,0 +1,20 @@
1
+ <%- assert_locals method -%>
2
+ ##
3
+ # Baseline implementation for the <%= method.name %> REST call
4
+ #
5
+ # @param request_pb [<%= method.rest.request_type %>]
6
+ # A request object representing the call parameters. Required.
7
+ # @param options [::Gapic::CallOptions]
8
+ # Overrides the default settings for this call, e.g, timeout, retries etc. Optional.
9
+ #
10
+ # @yield [result, response] Access the result along with the Faraday response object
11
+ # @yieldparam result [<%= method.rest.return_type %>]
12
+ # @yieldparam response [::Faraday::Response]
13
+ #
14
+ # @return [<%= method.rest.return_type %>]
15
+ # A result object deserialized from the server's reply
16
+ def <%= method.name %> request_pb, options = nil
17
+ <%= indent render(partial: "service/rest/service_stub/method/def/request", locals: { method: method }), 2 %>
18
+
19
+ <%= indent render(partial: "service/rest/service_stub/method/def/response", locals: { method: method }), 2 %>
20
+ end
@@ -0,0 +1,2 @@
1
+ <%- assert_locals method -%>
2
+ raise ::ArgumentError, "request must be provided" if request_pb.nil?
@@ -0,0 +1,17 @@
1
+ <%- assert_locals method -%>
2
+
3
+ uri, <%= method.rest.body_var_name %>, <%= method.rest.query_string_params_var_name %> = <%= method.rest.transcoding_helper_name %> request_pb
4
+ response = @client_stub.make_<%= method.rest.verb %>_request(
5
+ uri: uri,
6
+ <%- if method.rest.body? -%>
7
+ body: body,
8
+ <%- end -%>
9
+ <%- if method.rest.query_string_params? -%>
10
+ params: query_string_params,
11
+ <%- end -%>
12
+ options: options
13
+ )
14
+ result = <%= method.return_type %>.decode_json response.body, ignore_unknown_fields: true
15
+
16
+ yield result, response if block_given?
17
+ result
@@ -0,0 +1,18 @@
1
+ <%- assert_locals service -%>
2
+ <%= render partial: "shared/header" %>
3
+ require "helper"
4
+ require "gapic/rest"
5
+ require "<%= service.proto_service_require %>"
6
+ require "<%= service.service_require %>"
7
+
8
+
9
+ class <%= service.client_name_full %>Test < Minitest::Test
10
+ <%= indent render(partial: "service/rest/test/method/setup"), 2 %>
11
+
12
+ <% service.methods.each do |method| %>
13
+ <%= indent render(partial: "service/rest/test/method/#{method.kind}",
14
+ locals: { method: method }), 2 %>
15
+
16
+ <% end %>
17
+ <%= indent render(partial: "service/rest/test/method/configure", locals: { service: service }), 2 %>
18
+ end
@@ -0,0 +1,2 @@
1
+ <%- assert_locals method -%>
2
+ assert_equal http_response, response
@@ -0,0 +1,19 @@
1
+ <%- assert_locals service -%>
2
+ <%- full_client_name = defined?(client_name_full) ? client_name_full : service.rest.client_name_full -%>
3
+ def test_configure
4
+ credentials_token = :dummy_value
5
+
6
+ client = block_config = config = nil
7
+ Gapic::Rest::ClientStub.stub :new, nil do
8
+ client = <%= full_client_name =%>.new do |config|
9
+ config.credentials = credentials_token
10
+ end
11
+ end
12
+
13
+ config = client.configure do |c|
14
+ block_config = c
15
+ end
16
+
17
+ assert_same block_config, config
18
+ assert_kind_of <%= full_client_name %>::Configuration, config
19
+ end
@@ -0,0 +1,71 @@
1
+ <%- assert_locals method -%>
2
+ <%- full_client_name = defined?(client_name_full) ? client_name_full : method.service.rest.client_name_full -%>
3
+ <%- fields = method.fields_with_first_oneof -%>
4
+ def test_<%= method.name %>
5
+ # Create test objects.
6
+ client_result = <%= method.return_type %>.new
7
+ http_response = OpenStruct.new body: client_result.to_json
8
+
9
+ call_options = {}
10
+
11
+ # Create request parameters for a unary method.
12
+ <%- fields.each do |field| -%>
13
+ <%= field.name %> = <%= field.default_value %>
14
+ <%- end -%>
15
+
16
+ <%= method.name %>_client_stub = ClientStub.new http_response do |verb, uri:, body:, params:, options:|
17
+ assert_equal :<%= method.rest.verb %>, verb
18
+
19
+ assert options.metadata.key? :"x-goog-api-client"
20
+ assert options.metadata[:"x-goog-api-client"].include? "rest"
21
+ refute options.metadata[:"x-goog-api-client"].include? "grpc"
22
+
23
+ <%- if method.rest.query_string_params? -%>
24
+ <%- method.rest.query_string_params.each do |field| -%>
25
+ assert params.key? "<%= field.camel_name %>"
26
+ <%- end -%>
27
+ <%- end -%>
28
+ <%- if method.rest.body? %>
29
+ refute_nil body
30
+ <%- else -%>
31
+ assert_nil body
32
+ <%- end -%>
33
+ end
34
+
35
+ Gapic::Rest::ClientStub.stub :new, <%= method.name %>_client_stub do
36
+ # Create client
37
+ client = <%= full_client_name %>.new do |config|
38
+ config.credentials = :dummy_value
39
+ end
40
+
41
+ # Use hash object
42
+ client.<%= method.name %>({ <%= fields.map(&:as_kwarg).join ", " %> }) do |result, response|
43
+ <%= indent_tail render(partial: "service/rest/test/method/assert_response", locals: { method: method }), 6 %>
44
+ end
45
+
46
+ <%- if fields.any? -%>
47
+ # Use named arguments
48
+ client.<%= method.name %> <%= fields.map(&:as_kwarg).join ", " %> do |result, response|
49
+ <%= indent_tail render(partial: "service/rest/test/method/assert_response", locals: { method: method }), 6 %>
50
+ end
51
+
52
+ <%- end -%>
53
+ # Use protobuf object
54
+ client.<%= method.name %> <%= method.request_type %>.new(<%= fields.map(&:as_kwarg).join ", " %>) do |result, response|
55
+ <%= indent_tail render(partial: "service/rest/test/method/assert_response", locals: { method: method }), 6 %>
56
+ end
57
+
58
+ # Use hash object with options
59
+ client.<%= method.name %>({ <%= fields.map(&:as_kwarg).join ", " %> }, call_options) do |result, response|
60
+ <%= indent_tail render(partial: "service/rest/test/method/assert_response", locals: { method: method }), 6 %>
61
+ end
62
+
63
+ # Use protobuf object with options
64
+ client.<%= method.name %>(<%= method.request_type %>.new(<%= fields.map(&:as_kwarg).join ", " %>), call_options) do |result, response|
65
+ <%= indent_tail render(partial: "service/rest/test/method/assert_response", locals: { method: method }), 6 %>
66
+ end
67
+
68
+ # Verify method calls
69
+ assert_equal <%= fields.any? ? 5 : 4 %>, <%= method.name %>_client_stub.call_count
70
+ end
71
+ end