swagger_autogenerate 1.1.1 → 1.1.2

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: 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