grape-swagger 0.33.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -7
  3. data/.rubocop_todo.yml +0 -6
  4. data/.travis.yml +11 -10
  5. data/CHANGELOG.md +75 -5
  6. data/Gemfile +5 -5
  7. data/README.md +73 -5
  8. data/grape-swagger.gemspec +1 -1
  9. data/lib/grape-swagger/doc_methods/build_model_definition.rb +0 -17
  10. data/lib/grape-swagger/doc_methods/data_type.rb +1 -1
  11. data/lib/grape-swagger/doc_methods/extensions.rb +6 -1
  12. data/lib/grape-swagger/doc_methods/format_data.rb +51 -0
  13. data/lib/grape-swagger/doc_methods/move_params.rb +22 -49
  14. data/lib/grape-swagger/doc_methods/parse_params.rb +6 -0
  15. data/lib/grape-swagger/doc_methods.rb +2 -0
  16. data/lib/grape-swagger/endpoint/params_parser.rb +22 -22
  17. data/lib/grape-swagger/endpoint.rb +33 -14
  18. data/lib/grape-swagger/version.rb +1 -1
  19. data/lib/grape-swagger.rb +1 -1
  20. data/spec/issues/751_deeply_nested_objects_spec.rb +190 -0
  21. data/spec/lib/data_type_spec.rb +2 -2
  22. data/spec/lib/endpoint/params_parser_spec.rb +46 -21
  23. data/spec/lib/endpoint_spec.rb +4 -4
  24. data/spec/lib/extensions_spec.rb +10 -0
  25. data/spec/lib/format_data_spec.rb +91 -0
  26. data/spec/lib/move_params_spec.rb +4 -266
  27. data/spec/lib/optional_object_spec.rb +0 -1
  28. data/spec/spec_helper.rb +1 -1
  29. data/spec/support/model_parsers/entity_parser.rb +1 -1
  30. data/spec/support/model_parsers/representable_parser.rb +1 -1
  31. data/spec/swagger_v2/api_swagger_v2_hash_and_array_spec.rb +3 -1
  32. data/spec/swagger_v2/api_swagger_v2_hide_param_spec.rb +14 -3
  33. data/spec/swagger_v2/api_swagger_v2_response_with_root_spec.rb +153 -0
  34. data/spec/swagger_v2/boolean_params_spec.rb +1 -1
  35. data/spec/swagger_v2/description_not_initialized_spec.rb +39 -0
  36. data/spec/swagger_v2/endpoint_versioned_path_spec.rb +33 -0
  37. data/spec/swagger_v2/mounted_target_class_spec.rb +1 -1
  38. data/spec/swagger_v2/namespace_tags_prefix_spec.rb +15 -1
  39. data/spec/swagger_v2/params_array_spec.rb +2 -2
  40. data/spec/swagger_v2/parent_less_namespace_spec.rb +32 -0
  41. data/spec/swagger_v2/{reference_entity.rb → reference_entity_spec.rb} +17 -10
  42. metadata +20 -13
  43. data/spec/swagger_v2/description_not_initialized.rb +0 -39
  44. data/spec/swagger_v2/parent_less_namespace.rb +0 -49
@@ -87,7 +87,12 @@ module GrapeSwagger
87
87
  part.select { |x| x == identifier }
88
88
  end
89
89
 
90
- def method
90
+ def method(*args)
91
+ # We're shadowing Object.method(:symbol) here so we provide
92
+ # a compatibility layer for code that introspects the methods
93
+ # of this class
94
+ return super if args.size.positive?
95
+
91
96
  @route.request_method.downcase.to_sym
92
97
  end
93
98
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GrapeSwagger
4
+ module DocMethods
5
+ class FormatData
6
+ class << self
7
+ def to_format(parameters)
8
+ parameters.reject { |parameter| parameter[:in] == 'body' }.each do |b|
9
+ related_parameters = parameters.select do |p|
10
+ p[:name] != b[:name] && p[:name].to_s.include?(b[:name].to_s.gsub(/\[\]\z/, '') + '[')
11
+ end
12
+ parameters.reject! { |p| p[:name] == b[:name] } if move_down(b, related_parameters)
13
+ end
14
+ parameters
15
+ end
16
+
17
+ def move_down(parameter, related_parameters)
18
+ case parameter[:type]
19
+ when 'array'
20
+ add_array(parameter, related_parameters)
21
+ unless related_parameters.blank?
22
+ add_braces(parameter, related_parameters) if parameter[:name].match?(/\A.*\[\]\z/)
23
+ return true
24
+ end
25
+ when 'object'
26
+ return true
27
+ end
28
+ false
29
+ end
30
+
31
+ def add_braces(parameter, related_parameters)
32
+ param_name = parameter[:name].gsub(/\A(.*)\[\]\z/, '\1')
33
+ related_parameters.each { |p| p[:name] = p[:name].gsub(param_name, param_name + '[]') }
34
+ end
35
+
36
+ def add_array(parameter, related_parameters)
37
+ related_parameters.each do |p|
38
+ p_type = p[:type] == 'array' ? 'string' : p[:type]
39
+ p[:items] = { type: p_type, format: p[:format], enum: p[:enum], is_array: p[:is_array] }
40
+ p[:items].delete_if { |_k, v| v.nil? }
41
+ p[:type] = 'array'
42
+ p[:is_array] = parameter[:is_array]
43
+ p.delete(:format)
44
+ p.delete(:enum)
45
+ p.delete_if { |_k, v| v.nil? }
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -8,7 +8,7 @@ module GrapeSwagger
8
8
  class << self
9
9
  attr_accessor :definitions
10
10
 
11
- def can_be_moved?(params, http_verb)
11
+ def can_be_moved?(http_verb, params)
12
12
  move_methods.include?(http_verb) && includes_body_param?(params)
13
13
  end
14
14
 
@@ -51,22 +51,33 @@ module GrapeSwagger
51
51
 
52
52
  def move_params_to_new(definition, params)
53
53
  params, nested_params = params.partition { |x| !x[:name].to_s.include?('[') }
54
-
55
- unless params.blank?
56
- properties, required = build_properties(params)
57
- add_properties_to_definition(definition, properties, required)
54
+ params.each do |param|
55
+ property = param[:name]
56
+ param_properties, param_required = build_properties([param])
57
+ add_properties_to_definition(definition, param_properties, param_required)
58
+ related_nested_params, nested_params = nested_params.partition { |x| x[:name].start_with?("#{property}[") }
59
+ prepare_nested_names(property, related_nested_params)
60
+
61
+ next if related_nested_params.blank?
62
+
63
+ nested_definition = if should_expose_as_array?([param])
64
+ move_params_to_new(array_type, related_nested_params)
65
+ else
66
+ move_params_to_new(object_type, related_nested_params)
67
+ end
68
+ if definition.key?(:items)
69
+ definition[:items][:properties][property.to_sym].deep_merge!(nested_definition)
70
+ else
71
+ definition[:properties][property.to_sym].deep_merge!(nested_definition)
72
+ end
58
73
  end
59
-
60
- nested_properties = build_nested_properties(nested_params) unless nested_params.blank?
61
- add_properties_to_definition(definition, nested_properties, []) unless nested_params.blank?
74
+ definition
62
75
  end
63
76
 
64
77
  def build_properties(params)
65
78
  properties = {}
66
79
  required = []
67
80
 
68
- prepare_nested_types(params) if should_expose_as_array?(params)
69
-
70
81
  params.each do |param|
71
82
  name = param[:name].to_sym
72
83
 
@@ -103,28 +114,6 @@ module GrapeSwagger
103
114
  end
104
115
  end
105
116
 
106
- def build_nested_properties(params, properties = {})
107
- property = params.bsearch { |x| x[:name].include?('[') }[:name].split('[').first
108
-
109
- nested_params, params = params.partition { |x| x[:name].start_with?("#{property}[") }
110
- prepare_nested_names(property, nested_params)
111
-
112
- recursive_call(properties, property, nested_params) unless nested_params.empty?
113
- build_nested_properties(params, properties) unless params.empty?
114
-
115
- properties
116
- end
117
-
118
- def recursive_call(properties, property, nested_params)
119
- if should_expose_as_array?(nested_params)
120
- properties[property.to_sym] = array_type
121
- move_params_to_new(properties[property.to_sym][:items], nested_params)
122
- else
123
- properties[property.to_sym] = object_type
124
- move_params_to_new(properties[property.to_sym], nested_params)
125
- end
126
- end
127
-
128
117
  def movable_params(params)
129
118
  to_delete = params.each_with_object([]) { |x, memo| memo << x if deletable?(x) }
130
119
  delete_from(params, to_delete)
@@ -177,22 +166,6 @@ module GrapeSwagger
177
166
  { type: 'object', properties: {} }
178
167
  end
179
168
 
180
- def prepare_nested_types(params)
181
- params.each do |param|
182
- next unless param[:items]
183
-
184
- param[:type] = if param[:items][:type] == 'array'
185
- 'string'
186
- elsif param[:items].key?('$ref')
187
- param[:type] = 'object'
188
- else
189
- param[:items][:type]
190
- end
191
- param[:format] = param[:items][:format] if param[:items][:format]
192
- param.delete(:items) if param[:type] != 'object'
193
- end
194
- end
195
-
196
169
  def prepare_nested_names(property, params)
197
170
  params.each { |x| x[:name] = x[:name].sub(property, '').sub('[', '').sub(']', '') }
198
171
  end
@@ -208,7 +181,7 @@ module GrapeSwagger
208
181
  end
209
182
 
210
183
  def property_keys
211
- %i[type format description minimum maximum items enum default]
184
+ %i[type format description minimum maximum items enum default additionalProperties]
212
185
  end
213
186
 
214
187
  def deletable?(param)
@@ -25,6 +25,7 @@ module GrapeSwagger
25
25
  document_default_value(settings) unless value_type[:is_array]
26
26
  document_range_values(settings) unless value_type[:is_array]
27
27
  document_required(settings)
28
+ document_additional_properties(settings)
28
29
 
29
30
  @parsed_param
30
31
  end
@@ -91,6 +92,11 @@ module GrapeSwagger
91
92
  @parsed_param[:collectionFormat] = collection_format if DataType.collections.include?(collection_format)
92
93
  end
93
94
 
95
+ def document_additional_properties(settings)
96
+ additional_properties = settings[:additionalProperties]
97
+ @parsed_param[:additionalProperties] = additional_properties if additional_properties
98
+ end
99
+
94
100
  def param_type(value_type)
95
101
  param_type = value_type[:param_type] || value_type[:in]
96
102
  if value_type[:path].include?("{#{value_type[:param_name]}}")
@@ -4,6 +4,7 @@ require 'grape-swagger/doc_methods/status_codes'
4
4
  require 'grape-swagger/doc_methods/produces_consumes'
5
5
  require 'grape-swagger/doc_methods/data_type'
6
6
  require 'grape-swagger/doc_methods/extensions'
7
+ require 'grape-swagger/doc_methods/format_data'
7
8
  require 'grape-swagger/doc_methods/operation_id'
8
9
  require 'grape-swagger/doc_methods/optional_object'
9
10
  require 'grape-swagger/doc_methods/path_string'
@@ -102,6 +103,7 @@ module GrapeSwagger
102
103
  base_path: nil,
103
104
  add_base_path: false,
104
105
  add_version: true,
106
+ add_root: false,
105
107
  hide_documentation_path: true,
106
108
  format: :json,
107
109
  authorizations: nil,
@@ -3,49 +3,37 @@
3
3
  module GrapeSwagger
4
4
  module Endpoint
5
5
  class ParamsParser
6
- attr_reader :params, :settings
6
+ attr_reader :params, :settings, :endpoint
7
7
 
8
- def self.parse_request_params(params, settings)
9
- new(params, settings).parse_request_params
8
+ def self.parse_request_params(params, settings, endpoint)
9
+ new(params, settings, endpoint).parse_request_params
10
10
  end
11
11
 
12
- def initialize(params, settings)
12
+ def initialize(params, settings, endpoint)
13
13
  @params = params
14
14
  @settings = settings
15
+ @endpoint = endpoint
15
16
  end
16
17
 
17
18
  def parse_request_params
18
- array_keys = []
19
19
  public_params.each_with_object({}) do |(name, options), memo|
20
20
  name = name.to_s
21
21
  param_type = options[:type]
22
22
  param_type = param_type.to_s unless param_type.nil?
23
23
 
24
24
  if param_type_is_array?(param_type)
25
- array_keys << name
26
25
  options[:is_array] = true
27
-
28
- name += '[]' if array_use_braces?(options)
29
- else
30
- keys = array_keys.find_all { |key| name.start_with? "#{key}[" }
31
- if keys.any?
32
- options[:is_array] = true
33
- if array_use_braces?(options)
34
- keys.sort.reverse_each do |key|
35
- name = name.sub(key, "#{key}[]")
36
- end
37
- end
38
- end
26
+ name += '[]' if array_use_braces?
39
27
  end
40
28
 
41
- memo[name] = options unless %w[Hash Array].include?(param_type) && !options.key?(:documentation)
29
+ memo[name] = options
42
30
  end
43
31
  end
44
32
 
45
33
  private
46
34
 
47
- def array_use_braces?(options)
48
- settings[:array_use_braces] && !(options[:documentation] && options[:documentation][:param_type] == 'body')
35
+ def array_use_braces?
36
+ @array_use_braces ||= settings[:array_use_braces] && !includes_body_param?
49
37
  end
50
38
 
51
39
  def param_type_is_array?(param_type)
@@ -68,9 +56,21 @@ module GrapeSwagger
68
56
  return true unless param_options.key?(:documentation) && !param_options[:required]
69
57
 
70
58
  param_hidden = param_options[:documentation].fetch(:hidden, false)
71
- param_hidden = param_hidden.call if param_hidden.is_a?(Proc)
59
+ if param_hidden.is_a?(Proc)
60
+ param_hidden = if settings[:token_owner]
61
+ param_hidden.call(endpoint.send(settings[:token_owner].to_sym))
62
+ else
63
+ param_hidden.call
64
+ end
65
+ end
72
66
  !param_hidden
73
67
  end
68
+
69
+ def includes_body_param?
70
+ params.any? do |_, options|
71
+ options.dig(:documentation, :param_type) == 'body' || options.dig(:documentation, :in) == 'body'
72
+ end
73
+ end
74
74
  end
75
75
  end
76
76
  end
@@ -78,8 +78,7 @@ module Grape
78
78
  def path_and_definition_objects(namespace_routes, options)
79
79
  @paths = {}
80
80
  @definitions = {}
81
- namespace_routes.each_key do |key|
82
- routes = namespace_routes[key]
81
+ namespace_routes.each_value do |routes|
83
82
  path_item(routes, options)
84
83
  end
85
84
 
@@ -121,7 +120,7 @@ module Grape
121
120
  method[:consumes] = consumes_object(route, options[:format])
122
121
  method[:parameters] = params_object(route, options, path)
123
122
  method[:security] = security_object(route)
124
- method[:responses] = response_object(route)
123
+ method[:responses] = response_object(route, options)
125
124
  method[:tags] = route.options.fetch(:tags, tag_object(route, path))
126
125
  method[:operationId] = GrapeSwagger::DocMethods::OperationId.build(route, path)
127
126
  method[:deprecated] = deprecated_object(route)
@@ -179,22 +178,24 @@ module Grape
179
178
  parameters = partition_params(route, options).map do |param, value|
180
179
  value = { required: false }.merge(value) if value.is_a?(Hash)
181
180
  _, value = default_type([[param, value]]).first if value == ''
182
- if value[:type]
183
- expose_params(value[:type])
184
- elsif value[:documentation]
181
+ if value.dig(:documentation, :type)
185
182
  expose_params(value[:documentation][:type])
183
+ elsif value[:type]
184
+ expose_params(value[:type])
186
185
  end
187
186
  GrapeSwagger::DocMethods::ParseParams.call(param, value, path, route, @definitions)
188
187
  end
189
188
 
190
- if GrapeSwagger::DocMethods::MoveParams.can_be_moved?(parameters, route.request_method)
189
+ if GrapeSwagger::DocMethods::MoveParams.can_be_moved?(route.request_method, parameters)
191
190
  parameters = GrapeSwagger::DocMethods::MoveParams.to_definition(path, parameters, route, @definitions)
192
191
  end
193
192
 
193
+ GrapeSwagger::DocMethods::FormatData.to_format(parameters)
194
+
194
195
  parameters.presence
195
196
  end
196
197
 
197
- def response_object(route)
198
+ def response_object(route, options)
198
199
  codes = http_codes_from_route(route)
199
200
  codes.map! { |x| x.is_a?(Array) ? { code: x[0], message: x[1], model: x[2], examples: x[3], headers: x[4] } : x }
200
201
 
@@ -219,7 +220,7 @@ module Grape
219
220
 
220
221
  @definitions[response_model][:description] = description_object(route)
221
222
 
222
- memo[value[:code]][:schema] = build_reference(route, value, response_model)
223
+ memo[value[:code]][:schema] = build_reference(route, value, response_model, options)
223
224
  memo[value[:code]][:examples] = value[:examples] if value[:examples]
224
225
  end
225
226
  end
@@ -250,20 +251,38 @@ module Grape
250
251
  def tag_object(route, path)
251
252
  version = GrapeSwagger::DocMethods::Version.get(route)
252
253
  version = [version] unless version.is_a?(Array)
253
-
254
+ prefix = route.prefix.to_s.split('/').reject(&:empty?)
254
255
  Array(
255
256
  path.split('{')[0].split('/').reject(&:empty?).delete_if do |i|
256
- i == route.prefix.to_s || version.map(&:to_s).include?(i)
257
+ prefix.include?(i) || version.map(&:to_s).include?(i)
257
258
  end.first
258
259
  ).presence
259
260
  end
260
261
 
261
262
  private
262
263
 
263
- def build_reference(route, value, response_model)
264
+ def build_reference(route, value, response_model, settings)
264
265
  # TODO: proof that the definition exist, if model isn't specified
265
266
  reference = { '$ref' => "#/definitions/#{response_model}" }
266
- route.options[:is_array] && value[:code] < 300 ? { type: 'array', items: reference } : reference
267
+ return reference unless value[:code] < 300
268
+
269
+ reference = { type: 'array', items: reference } if route.options[:is_array]
270
+ build_root(route, reference, response_model, settings)
271
+ end
272
+
273
+ def build_root(route, reference, response_model, settings)
274
+ default_root = response_model.underscore
275
+ default_root = default_root.pluralize if route.options[:is_array]
276
+ case route.settings.dig(:swagger, :root)
277
+ when true
278
+ { type: 'object', properties: { default_root => reference } }
279
+ when false
280
+ reference
281
+ when nil
282
+ settings[:add_root] ? { type: 'object', properties: { default_root => reference } } : reference
283
+ else
284
+ { type: 'object', properties: { route.settings.dig(:swagger, :root) => reference } }
285
+ end
267
286
  end
268
287
 
269
288
  def file_response?(value)
@@ -282,7 +301,7 @@ module Grape
282
301
  default_type(required)
283
302
 
284
303
  request_params = unless declared_params.nil? && route.headers.nil?
285
- GrapeSwagger::Endpoint::ParamsParser.parse_request_params(required, settings)
304
+ GrapeSwagger::Endpoint::ParamsParser.parse_request_params(required, settings, self)
286
305
  end || {}
287
306
 
288
307
  request_params.empty? ? required : request_params
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GrapeSwagger
4
- VERSION = '0.33.0'
4
+ VERSION = '1.0.0'
5
5
  end
data/lib/grape-swagger.rb CHANGED
@@ -26,7 +26,7 @@ module SwaggerRouting
26
26
  def combine_routes(app, doc_klass)
27
27
  app.routes.each do |route|
28
28
  route_path = route.path
29
- route_match = route_path.split(/^.*?#{route.prefix.to_s}/).last
29
+ route_match = route_path.split(/^.*?#{route.prefix}/).last
30
30
  next unless route_match
31
31
 
32
32
  route_match = route_match.match('\/([\w|-]*?)[\.\/\(]') || route_match.match('\/([\w|-]*)$')
@@ -0,0 +1,190 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe '751 deeply nested objects' do
6
+ let(:app) do
7
+ Class.new(Grape::API) do
8
+ content_type :json, 'application/json; charset=UTF-8'
9
+ default_format :json
10
+ class Vrp < Grape::API
11
+ def self.vrp_request_timewindow(this)
12
+ this.optional(:start, types: [String, Float, Integer])
13
+ this.optional(:end, types: [String, Float, Integer])
14
+ end
15
+
16
+ def self.vrp_request_point(this)
17
+ this.requires(:id, type: String, allow_blank: false)
18
+ this.optional(:matrix_index, type: Integer)
19
+ this.optional(:location, type: Hash) do
20
+ requires(:lat, type: Float, allow_blank: false)
21
+ requires(:lon, type: Float, allow_blank: false)
22
+ end
23
+ this.at_least_one_of :matrix_index, :location
24
+ end
25
+
26
+ def self.vrp_request_activity(this)
27
+ this.optional(:duration, types: [String, Float, Integer])
28
+ this.requires(:point_id, type: String, allow_blank: false)
29
+ this.optional(:timewindows, type: Array) do
30
+ Vrp.vrp_request_timewindow(self)
31
+ end
32
+ end
33
+
34
+ def self.vrp_request_service(this)
35
+ this.requires(:id, type: String, allow_blank: false)
36
+ this.optional(:skills, type: Array[String])
37
+
38
+ this.optional(:activity, type: Hash) do
39
+ Vrp.vrp_request_activity(self)
40
+ end
41
+ this.optional(:activities, type: Array) do
42
+ Vrp.vrp_request_activity(self)
43
+ end
44
+ this.mutually_exclusive :activity, :activities
45
+ end
46
+ end
47
+
48
+ namespace :vrp do
49
+ resource :submit do
50
+ desc 'Submit Problems', nickname: 'vrp'
51
+ params do
52
+ optional(:vrp, type: Hash, documentation: { param_type: 'body' }) do
53
+ optional(:points, type: Array) do
54
+ Vrp.vrp_request_point(self)
55
+ end
56
+
57
+ optional(:services, type: Array) do
58
+ Vrp.vrp_request_service(self)
59
+ end
60
+ end
61
+ end
62
+ post do
63
+ { vrp: params[:vrp] }.to_json
64
+ end
65
+ end
66
+ end
67
+
68
+ add_swagger_documentation format: :json
69
+ end
70
+ end
71
+
72
+ subject do
73
+ get '/swagger_doc'
74
+ JSON.parse(last_response.body)
75
+ end
76
+
77
+ describe 'Correctness of vrp Points' do
78
+ let(:get_points_response) { subject['definitions']['postVrpSubmit']['properties']['vrp']['properties']['points'] }
79
+ specify do
80
+ expect(get_points_response).to eql(
81
+ 'type' => 'array',
82
+ 'items' => {
83
+ 'type' => 'object',
84
+ 'properties' => {
85
+ 'id' => {
86
+ 'type' => 'string'
87
+ },
88
+ 'matrix_index' => {
89
+ 'type' => 'integer',
90
+ 'format' => 'int32'
91
+ },
92
+ 'location' => {
93
+ 'type' => 'object',
94
+ 'properties' => {
95
+ 'lat' => {
96
+ 'type' => 'number',
97
+ 'format' => 'float'
98
+ },
99
+ 'lon' => {
100
+ 'type' => 'number',
101
+ 'format' => 'float'
102
+ }
103
+ },
104
+ 'required' => %w[lat lon]
105
+ }
106
+ },
107
+ 'required' => ['id']
108
+ }
109
+ )
110
+ end
111
+ end
112
+
113
+ describe 'Correctness of vrp Services' do
114
+ let(:get_service_response) { subject['definitions']['postVrpSubmit']['properties']['vrp']['properties']['services'] }
115
+ specify do
116
+ expect(get_service_response).to include(
117
+ 'type' => 'array',
118
+ 'items' => {
119
+ 'type' => 'object',
120
+ 'properties' => {
121
+ 'id' => {
122
+ 'type' => 'string'
123
+ },
124
+ 'skills' => {
125
+ 'type' => 'array',
126
+ 'items' => {
127
+ 'type' => 'string'
128
+ }
129
+ },
130
+ 'activity' => {
131
+ 'type' => 'object',
132
+ 'properties' => {
133
+ 'duration' => {
134
+ 'type' => 'string'
135
+ },
136
+ 'point_id' => {
137
+ 'type' => 'string'
138
+ },
139
+ 'timewindows' => {
140
+ 'type' => 'array',
141
+ 'items' => {
142
+ 'type' => 'object',
143
+ 'properties' => {
144
+ 'start' => {
145
+ 'type' => 'string'
146
+ },
147
+ 'end' => {
148
+ 'type' => 'string'
149
+ }
150
+ }
151
+ }
152
+ }
153
+ },
154
+ 'required' => ['point_id']
155
+ }, 'activities' => {
156
+ 'type' => 'array',
157
+ 'items' => {
158
+ 'type' => 'object',
159
+ 'properties' => {
160
+ 'duration' => {
161
+ 'type' => 'string'
162
+ },
163
+ 'point_id' => {
164
+ 'type' => 'string'
165
+ },
166
+ 'timewindows' => {
167
+ 'type' => 'array',
168
+ 'items' => {
169
+ 'type' => 'object',
170
+ 'properties' => {
171
+ 'start' => {
172
+ 'type' => 'string'
173
+ },
174
+ 'end' => {
175
+ 'type' => 'string'
176
+ }
177
+ }
178
+ }
179
+ }
180
+ },
181
+ 'required' => ['point_id']
182
+ }
183
+ }
184
+ },
185
+ 'required' => ['id']
186
+ }
187
+ )
188
+ end
189
+ end
190
+ end
@@ -55,8 +55,8 @@ describe GrapeSwagger::DocMethods::DataType do
55
55
  it { is_expected.to eq 'file' }
56
56
  end
57
57
 
58
- describe 'Virtus::Attribute::Boolean' do
59
- let(:value) { { type: Virtus::Attribute::Boolean } }
58
+ describe 'Grape::API::Boolean' do
59
+ let(:value) { { type: Grape::API::Boolean } }
60
60
 
61
61
  it { is_expected.to eq 'boolean' }
62
62
  end