swagger_autogenerate 1.1.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a323ab35e5b839c6b85294fdf080ce0053fe43854eafbc1d1046b26cf14b7f2
4
- data.tar.gz: 996cd6d73b26711cc59cefe81f720fb747d1a38d5442fa713b3284528f3b8d2b
3
+ metadata.gz: fa0e0d56334a728cbd835bf8ecf0cf4b2c330eb62aeb92e6b9bc20d1251ed5cd
4
+ data.tar.gz: c5869ad74ec90bffdb1a58bdfbb52645849b14f88e81e876f5b856d280dab536
5
5
  SHA512:
6
- metadata.gz: 5794de7918cd298fab142696ff91a6873563fc2a31f6fa9ea60d8ea5a8c483c4467f64c5736f97ebdb92509059ab888032de8d903e8ef1caea486796384693b9
7
- data.tar.gz: 82593525706f167db50f96ead26c6e6ef4f6f1ba5911b761838bd5bf6ab0772d3cd9378fd8b4e1648d9fc0bf85a87868078bfe642175fd7994c7998258a3dfa5
6
+ metadata.gz: 7766553dbaa81ee1506f36727411a24e36d9dd7c73bc4733a2bc034be406b2c94e4526f7c73467e1d383cf3e566fecaa6ea592a06627f4a5778dba61cd5f142e
7
+ data.tar.gz: ab857ce41cc465f94b961c61d2f3bbeb48195c8bf5472152c43524384caa57313325b852df8417e2c07489fed8ae0e656c941d9c91a395ea6e16895ace7a990c
data/CHANGELOG.md CHANGED
@@ -11,5 +11,6 @@
11
11
  ## [1.0.9] - 2024-06-04
12
12
  ## [1.1.0] - 2024-06-23
13
13
  ## [1.1.1] - 2024-06-26
14
+ ## [1.1.2] - 2024-08-17
14
15
 
15
16
  - Initial release
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- swagger_autogenerate (1.1.1)
4
+ swagger_autogenerate (1.1.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -1,12 +1,14 @@
1
1
  module SwaggerAutogenerate
2
2
  class Configuration
3
- attr_accessor :with_config, :with_multiple_examples, :with_example_description,
3
+ attr_accessor :with_config, :with_multiple_examples, :with_rspec_examples, :with_example_description,
4
4
  :with_response_description, :swagger_environment_variable,
5
5
  :environment_name, :security, :swagger_config, :response_status
6
6
 
7
7
  def initialize
8
8
  @with_config = true
9
9
  @with_multiple_examples = true
10
+ @with_rspec_examples = true
11
+ # remove this when we do not need it any more
10
12
  @with_example_description = true
11
13
  @with_response_description = true
12
14
  @swagger_environment_variable = 'SWAGGER'
@@ -78,4 +80,9 @@ module SwaggerAutogenerate
78
80
  def self.configure
79
81
  yield(configuration)
80
82
  end
83
+
84
+ def self.extract_description(full_rspec_description)
85
+ parts = full_rspec_description.split(' ')
86
+ parts&.length > 1 ? parts[2..-1].join(" ") : full_rspec_description
87
+ end
81
88
  end
@@ -5,7 +5,7 @@ module SwaggerAutogenerate
5
5
  def initialize(request, response)
6
6
  @with_config = ::SwaggerAutogenerate.configuration.with_config
7
7
  @with_multiple_examples = ::SwaggerAutogenerate.configuration.with_multiple_examples
8
- @with_example_description = ::SwaggerAutogenerate.configuration.with_example_description
8
+ @with_rspec_examples = ::SwaggerAutogenerate.configuration.with_rspec_examples
9
9
  @with_response_description = ::SwaggerAutogenerate.configuration.with_response_description
10
10
  @security = ::SwaggerAutogenerate.configuration.security
11
11
  @swagger_config = ::SwaggerAutogenerate.configuration.swagger_config
@@ -39,7 +39,7 @@ module SwaggerAutogenerate
39
39
  private
40
40
 
41
41
  attr_reader :request, :response, :current_path, :yaml_file, :configuration,
42
- :with_config, :with_multiple_examples, :with_example_description,
42
+ :with_config, :with_multiple_examples, :with_rspec_examples,
43
43
  :with_response_description, :security, :response_status, :swagger_config
44
44
 
45
45
  # main methods
@@ -88,6 +88,13 @@ module SwaggerAutogenerate
88
88
  data['paths'] = paths
89
89
  organize_result(data['paths'])
90
90
  data = data.to_hash
91
+ # handel examples names
92
+ example_title = full_rspec_description.present? ? full_rspec_description : 'example-0'
93
+ old_examples = data['paths'][current_path][request.method.downcase]['responses'][response.status.to_s]['content']['application/json']['examples']
94
+ current_example = old_examples[example_title]
95
+ new_example(example_title, current_example, old_examples, data['paths'], true)
96
+ # result
97
+
91
98
  result = add_quotes_to_dates(YAML.dump(data))
92
99
  file.write(result)
93
100
  end
@@ -209,17 +216,24 @@ module SwaggerAutogenerate
209
216
  }
210
217
  end
211
218
 
212
- def convert_to_multipart(payload)
219
+ def convert_to_multipart(payload, main_key = nil, index = nil)
220
+ payload_keys.push(main_key) if main_key.present?
213
221
  payload.each do |key, value|
214
222
  if value.is_a?(Hash)
215
223
  payload_keys.push(key)
216
224
  convert_to_multipart(value)
225
+ elsif value.is_a?(Array)
226
+ value.each_with_index { |v, index| convert_to_multipart(v, key, index) }
217
227
  else
218
228
  keys = payload_keys.clone
219
229
  first_key = keys.shift
220
- keys.each { |inner_key| first_key = "#{first_key}[#{inner_key}]" }
221
- first_key = "#{first_key}[#{key}]"
230
+ if index.present?
231
+ keys.each { |inner_key| first_key = "#{first_key}[#{inner_key}][#{index}]" }
232
+ else
233
+ keys.each { |inner_key| first_key = "#{first_key}[#{inner_key}]" }
234
+ end
222
235
 
236
+ first_key = "#{first_key}[#{key}]"
223
237
  payload_hash.merge!({ first_key => { 'type' => schema_type(value), 'example' => example(value) } })
224
238
  end
225
239
  end
@@ -230,6 +244,8 @@ module SwaggerAutogenerate
230
244
  data.map do |key, value|
231
245
  if value.is_a?(Hash)
232
246
  hash_data.merge!({ key => value })
247
+ elsif value.is_a?(Array)
248
+ value.each_with_index { |v, index| convert_to_multipart(v, key) }
233
249
  else
234
250
  payload_hash.merge!({ key => { 'type' => schema_type(value), 'example' => example(value) } })
235
251
  end
@@ -250,10 +266,93 @@ module SwaggerAutogenerate
250
266
  }
251
267
  end
252
268
 
269
+ def json_to_content_form_data(json)
270
+ {
271
+ 'multipart/form-data' => {
272
+ 'schema' => build_properties(json)
273
+ }
274
+ }
275
+ end
276
+
277
+ def build_properties(json)
278
+ case json
279
+ when Hash
280
+ hash_properties = json.transform_values { |value| build_properties(value) if value.present? }
281
+ hash_properties = hash_properties.delete_if { |_k, v| !v.present? }
282
+
283
+ hashs = {
284
+ 'type' => 'object',
285
+ 'properties' => hash_properties
286
+ }
287
+ when Array
288
+ item_schemas = json.map { |item| build_properties(item) }
289
+ merged_schema = merge_array_schemas(item_schemas)
290
+
291
+ if merged_schema[:type] == 'object'
292
+ { 'type' => 'array', 'items' => merged_schema }
293
+ else
294
+ { 'type' => 'array', 'items' => { 'oneOf' => item_schemas.uniq } }
295
+ end
296
+ when String
297
+ { 'type' => 'string', 'example' => json }
298
+ when Integer
299
+ { 'type' => 'integer', 'example' => json }
300
+ when Float
301
+ { 'type' => 'number', 'example' => json }
302
+ when TrueClass, FalseClass
303
+ { 'type' => 'boolean', 'example' => json }
304
+ else
305
+ { 'type' => 'string', 'example' => json.to_s }
306
+ end
307
+ end
308
+
309
+ def merge_array_schemas(schemas)
310
+ return {} if schemas.empty?
311
+
312
+ # Attempt to merge all schemas into a single schema
313
+ schemas.reduce do |merged, schema|
314
+ merge_properties(merged, schema)
315
+ end
316
+ end
317
+
318
+ def merge_properties(old_data, new_data)
319
+ return old_data unless old_data.is_a?(Hash) && new_data.is_a?(Hash)
320
+
321
+ merged = old_data.dup
322
+ new_data.each do |key, value|
323
+ merged[key] = if merged[key].is_a?(Hash) && value.is_a?(Hash)
324
+ merge_properties(merged[key], value)
325
+ else
326
+ value
327
+ end
328
+ end
329
+ merged
330
+ end
331
+
332
+ def content_application_json_schema_properties(data)
333
+ hash_data = {}
334
+ data.map do |key, value|
335
+ if value.is_a?(Hash)
336
+ hash_data.merge!({ key => value })
337
+ elsif value.is_a?(Array)
338
+ value.each_with_index { |v, index| convert_to_multipart(v, key, index) }
339
+ else
340
+ payload_hash.merge!({ key => { 'type' => schema_type(value), 'example' => example(value) } })
341
+ end
342
+ end
343
+
344
+ convert_to_multipart(hash_data)
345
+ converted_payload = @payload_hash.clone
346
+ @payload_hash = nil
347
+ @payload_keys = nil
348
+
349
+ converted_payload
350
+ end
351
+
253
352
  def content_body(data)
254
353
  hash = {}
255
354
  # hash.merge!(content_json(data))
256
- hash.merge!(content_form_data(data))
355
+ hash.merge!(json_to_content_form_data(data))
257
356
 
258
357
  { 'content' => hash }
259
358
  end
@@ -351,19 +450,18 @@ module SwaggerAutogenerate
351
450
  end
352
451
 
353
452
  def content_json_example(data)
354
- hash = {
453
+ example_title = full_rspec_description.present? ? full_rspec_description : 'example-0'
454
+
455
+ {
355
456
  'application/json' => {
356
457
  'schema' => { 'type' => 'object' },
357
458
  'examples' => {
358
- 'example-0' => {
459
+ example_title => {
359
460
  'value' => data
360
461
  }
361
462
  }
362
463
  }
363
464
  }
364
- hash['application/json']['examples']['example-0']['description'] = "payload => #{example_description}" if with_example_description && !example_description.empty?
365
-
366
- hash
367
465
  end
368
466
 
369
467
  def example_description
@@ -396,20 +494,48 @@ module SwaggerAutogenerate
396
494
  @payload_hash ||= {}
397
495
  end
398
496
 
399
- def new_example
400
- current_example = swagger_response[response.status.to_s]['content']['application/json']['examples']['example-0']
401
- old_examples = old_paths[current_path][request.method.downcase]['responses'][response.status.to_s]['content']['application/json']['examples']
402
-
403
- unless old_examples.value?(current_example)
404
- last_example = json_example_plus_one(old_examples.keys.last)
405
- last_example ||= 'example-0'
406
- last_example = 'example-0' unless with_multiple_examples
407
- yaml_file['paths'][current_path][request.method.downcase]['responses'][response.status.to_s]['content']['application/json']['examples'][last_example] = current_example
497
+ def new_example(example_title, current_example, old_examples, all_paths = yaml_file['paths'], with_schema_properties = false)
498
+ if !old_examples.value?(current_example)
499
+ last_example = handel_name_last_example(old_examples)
500
+ last_example ||= example_title
501
+ last_example = example_title unless with_multiple_examples
502
+ all_paths[current_path][request.method.downcase]['responses'][response.status.to_s]['content']['application/json']['examples'][last_example] = current_example
503
+ add_properties_to_schema(last_example, all_paths[current_path])
504
+ elsif with_schema_properties
505
+ add_properties_to_schema(full_rspec_description.present? ? full_rspec_description : 'example-0', all_paths[current_path])
408
506
  end
409
507
 
410
508
  true
411
509
  end
412
510
 
511
+ def handel_name_last_example(old_examples)
512
+ last_example = old_examples.keys.last
513
+ last_example += '-1' if json_example_plus_one(last_example) == last_example
514
+ json_example_plus_one(last_example)
515
+ end
516
+
517
+ def add_properties_to_schema(last_example, main_path = yaml_file['paths'][current_path])
518
+ parameters = {}
519
+ parameters.merge!(request_parameters.values.first, query_parameters.values.first, path_parameters.values.first)
520
+ hash = {
521
+ last_example => build_properties(parameters.as_json)
522
+ }
523
+
524
+ main_path[request.method.downcase]['responses'][response.status.to_s].deep_merge!(
525
+ {
526
+ 'content' => {
527
+ 'application/json' => {
528
+ 'schema' => {
529
+ 'description' => 'These are the payloads for each example',
530
+ 'type' => 'object',
531
+ 'properties' => hash
532
+ }
533
+ }
534
+ }
535
+ }
536
+ )
537
+ end
538
+
413
539
  def apply_yaml_file_changes
414
540
  (check_path || check_method || check_status) &&
415
541
  (check_parameters || check_parameter) &&
@@ -438,24 +564,29 @@ module SwaggerAutogenerate
438
564
  def check_path
439
565
  unless old_paths.key?(current_path)
440
566
  yaml_file['paths'].merge!({ current_path => paths[current_path] })
567
+ update_example_title(true)
441
568
  end
442
569
  end
443
570
 
444
571
  def check_method
445
572
  unless old_paths[current_path].key?(request.method.downcase)
446
573
  yaml_file['paths'][current_path][request.method.downcase] = { 'responses' => swagger_response }
574
+ update_example_title(true)
447
575
  end
448
576
  end
449
577
 
450
578
  def check_status
579
+ example_title = full_rspec_description.present? ? full_rspec_description : 'example-0'
451
580
  if old_paths[current_path][request.method.downcase]['responses'].present?
452
581
  if old_paths[current_path][request.method.downcase]['responses']&.key?(response.status.to_s)
453
- new_example
582
+ update_example_title
454
583
  else
455
584
  yaml_file['paths'][current_path][request.method.downcase]['responses'].merge!(swagger_response)
585
+ update_example_title(true)
456
586
  end
457
587
  else
458
588
  yaml_file['paths'][current_path][request.method.downcase]['responses'] = swagger_response
589
+ update_example_title
459
590
  end
460
591
  end
461
592
 
@@ -481,12 +612,31 @@ module SwaggerAutogenerate
481
612
 
482
613
  def check_request_body
483
614
  if paths[current_path][request.method.downcase]['requestBody'].present?
484
- param_names = paths[current_path][request.method.downcase]['requestBody']['content']['multipart/form-data']['schema']['properties'].keys - yaml_file['paths'][current_path][request.method.downcase]['requestBody']['content']['multipart/form-data']['schema']['properties'].keys
485
- param_names.each do |param_name|
486
- param = paths[current_path][request.method.downcase]['requestBody']['content']['multipart/form-data']['schema']['properties'].select { |parameter| parameter == param_name }
487
- yaml_file['paths'][current_path][request.method.downcase]['requestBody']['content']['multipart/form-data']['schema']['properties'].merge!(param)
615
+ param_current_hash = paths[current_path][request.method.downcase]['requestBody']['content']['multipart/form-data']['schema']['properties']
616
+ param_current_file = yaml_file['paths'][current_path][request.method.downcase]['requestBody']['content']['multipart/form-data']['schema']['properties']
617
+ if param_current_hash.present? && param_current_file.present?
618
+ param_names = param_current_hash.keys - param_current_file.keys
619
+ param_names.each do |param_name|
620
+ param = paths[current_path][request.method.downcase]['requestBody']['content']['multipart/form-data']['schema']['properties'].select { |parameter| parameter == param_name }
621
+ yaml_file['paths'][current_path][request.method.downcase]['requestBody']['content']['multipart/form-data']['schema']['properties'].merge!(param)
622
+ end
488
623
  end
489
624
  end
490
625
  end
626
+
627
+ def update_example_title(with_schema_properties = false)
628
+ example_title = full_rspec_description.present? ? full_rspec_description : 'example-0'
629
+ current_example = swagger_response[response.status.to_s]['content']['application/json']['examples'][example_title]
630
+ old_examples = old_paths[current_path][request.method.downcase]['responses'][response.status.to_s]['content']['application/json']['examples']
631
+ new_example(example_title, current_example, old_examples, yaml_file['paths'], with_schema_properties)
632
+ end
633
+
634
+ def full_rspec_description
635
+ with_rspec_examples ? SwaggerAutogenerate::SwaggerTrace.rspec_description : nil
636
+ end
637
+
638
+ class << self
639
+ attr_accessor :rspec_description
640
+ end
491
641
  end
492
642
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SwaggerAutogenerate
4
- VERSION = "1.1.1"
4
+ VERSION = "1.1.2"
5
5
  end
@@ -8,14 +8,23 @@ module SwaggerAutogenerate
8
8
  def process_action(*args)
9
9
  super
10
10
 
11
- if ENV[SwaggerTrace.swagger_environment_variable].present? && Rails.env.send("#{SwaggerTrace.environment_name.to_s}?")
11
+ if SwaggerAutogenerate.allow_swagger?
12
12
  SwaggerTrace.new(request, response).call
13
13
  end
14
14
  end
15
15
  end
16
+
17
+ def self.allow_swagger?
18
+ ENV[SwaggerTrace.swagger_environment_variable].present? && Rails.env.send("#{SwaggerTrace.environment_name.to_s}?")
19
+ end
16
20
  end
17
21
 
18
- # fix []
19
- # create command to direct add configuration file in test environment
20
- # handel headers
21
- # can the SWAGGER accespt empty value?
22
+ if defined?(RSpec) && SwaggerAutogenerate.allow_swagger?
23
+ require 'rspec/rails'
24
+
25
+ RSpec.configure do |config|
26
+ config.before(:each) do |example|
27
+ SwaggerAutogenerate::SwaggerTrace.rspec_description = SwaggerAutogenerate.extract_description(example.metadata[:full_description])
28
+ end
29
+ end
30
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: swagger_autogenerate
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - MohammedBuraiah
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-27 00:00:00.000000000 Z
11
+ date: 2024-08-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Generating Swagger YAML Automatically Based on Existing Test Cases in
14
14
  Ruby on Rails