swagger_autogenerate 1.1.0 → 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 +4 -4
- data/CHANGELOG.md +2 -0
- data/Gemfile.lock +1 -1
- data/lib/swagger_autogenerate/configuration.rb +14 -7
- data/lib/swagger_autogenerate/swagger_trace.rb +185 -26
- data/lib/swagger_autogenerate/version.rb +1 -1
- data/lib/swagger_autogenerate.rb +15 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa0e0d56334a728cbd835bf8ecf0cf4b2c330eb62aeb92e6b9bc20d1251ed5cd
|
4
|
+
data.tar.gz: c5869ad74ec90bffdb1a58bdfbb52645849b14f88e81e876f5b856d280dab536
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7766553dbaa81ee1506f36727411a24e36d9dd7c73bc4733a2bc034be406b2c94e4526f7c73467e1d383cf3e566fecaa6ea592a06627f4a5778dba61cd5f142e
|
7
|
+
data.tar.gz: ab857ce41cc465f94b961c61d2f3bbeb48195c8bf5472152c43524384caa57313325b852df8417e2c07489fed8ae0e656c941d9c91a395ea6e16895ace7a990c
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,22 +1,24 @@
|
|
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'
|
13
15
|
@environment_name = :test
|
14
|
-
@security =
|
15
|
-
@swagger_config =
|
16
|
-
@response_status =
|
16
|
+
@security = default_security
|
17
|
+
@swagger_config = default_swagger_config
|
18
|
+
@response_status = default_response_status
|
17
19
|
end
|
18
20
|
|
19
|
-
def
|
21
|
+
def default_response_status
|
20
22
|
{
|
21
23
|
100 => 'The initial part of the request has been received, and the client should proceed with sending the remainder of the request',
|
22
24
|
101 => 'The server agrees to switch protocols and is acknowledging the client\'s request to change the protocol being used',
|
@@ -42,7 +44,7 @@ module SwaggerAutogenerate
|
|
42
44
|
}
|
43
45
|
end
|
44
46
|
|
45
|
-
def
|
47
|
+
def default_swagger_config
|
46
48
|
{
|
47
49
|
'openapi' => '3.0.0',
|
48
50
|
'info' => {
|
@@ -63,7 +65,7 @@ module SwaggerAutogenerate
|
|
63
65
|
}
|
64
66
|
end
|
65
67
|
|
66
|
-
def
|
68
|
+
def default_security
|
67
69
|
[
|
68
70
|
{ 'org_slug' => [] },
|
69
71
|
{ 'locale' => [] }
|
@@ -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
|
-
@
|
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, :
|
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,24 +216,42 @@ 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
|
-
|
221
|
-
|
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
|
226
240
|
end
|
227
241
|
|
228
242
|
def content_form_data(data)
|
229
|
-
|
243
|
+
hash_data = {}
|
244
|
+
data.map do |key, value|
|
245
|
+
if value.is_a?(Hash)
|
246
|
+
hash_data.merge!({ key => value })
|
247
|
+
elsif value.is_a?(Array)
|
248
|
+
value.each_with_index { |v, index| convert_to_multipart(v, key) }
|
249
|
+
else
|
250
|
+
payload_hash.merge!({ key => { 'type' => schema_type(value), 'example' => example(value) } })
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
convert_to_multipart(hash_data)
|
230
255
|
converted_payload = @payload_hash.clone
|
231
256
|
@payload_hash = nil
|
232
257
|
@payload_keys = nil
|
@@ -241,10 +266,93 @@ module SwaggerAutogenerate
|
|
241
266
|
}
|
242
267
|
end
|
243
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
|
+
|
244
352
|
def content_body(data)
|
245
353
|
hash = {}
|
246
354
|
# hash.merge!(content_json(data))
|
247
|
-
hash.merge!(
|
355
|
+
hash.merge!(json_to_content_form_data(data))
|
248
356
|
|
249
357
|
{ 'content' => hash }
|
250
358
|
end
|
@@ -342,19 +450,18 @@ module SwaggerAutogenerate
|
|
342
450
|
end
|
343
451
|
|
344
452
|
def content_json_example(data)
|
345
|
-
|
453
|
+
example_title = full_rspec_description.present? ? full_rspec_description : 'example-0'
|
454
|
+
|
455
|
+
{
|
346
456
|
'application/json' => {
|
347
457
|
'schema' => { 'type' => 'object' },
|
348
458
|
'examples' => {
|
349
|
-
|
459
|
+
example_title => {
|
350
460
|
'value' => data
|
351
461
|
}
|
352
462
|
}
|
353
463
|
}
|
354
464
|
}
|
355
|
-
hash['application/json']['examples']['example-0']['description'] = "payload => #{example_description}" if with_example_description && !example_description.empty?
|
356
|
-
|
357
|
-
hash
|
358
465
|
end
|
359
466
|
|
360
467
|
def example_description
|
@@ -387,20 +494,48 @@ module SwaggerAutogenerate
|
|
387
494
|
@payload_hash ||= {}
|
388
495
|
end
|
389
496
|
|
390
|
-
def new_example
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
last_example =
|
396
|
-
last_example
|
397
|
-
|
398
|
-
|
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])
|
399
506
|
end
|
400
507
|
|
401
508
|
true
|
402
509
|
end
|
403
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
|
+
|
404
539
|
def apply_yaml_file_changes
|
405
540
|
(check_path || check_method || check_status) &&
|
406
541
|
(check_parameters || check_parameter) &&
|
@@ -429,24 +564,29 @@ module SwaggerAutogenerate
|
|
429
564
|
def check_path
|
430
565
|
unless old_paths.key?(current_path)
|
431
566
|
yaml_file['paths'].merge!({ current_path => paths[current_path] })
|
567
|
+
update_example_title(true)
|
432
568
|
end
|
433
569
|
end
|
434
570
|
|
435
571
|
def check_method
|
436
572
|
unless old_paths[current_path].key?(request.method.downcase)
|
437
573
|
yaml_file['paths'][current_path][request.method.downcase] = { 'responses' => swagger_response }
|
574
|
+
update_example_title(true)
|
438
575
|
end
|
439
576
|
end
|
440
577
|
|
441
578
|
def check_status
|
579
|
+
example_title = full_rspec_description.present? ? full_rspec_description : 'example-0'
|
442
580
|
if old_paths[current_path][request.method.downcase]['responses'].present?
|
443
581
|
if old_paths[current_path][request.method.downcase]['responses']&.key?(response.status.to_s)
|
444
|
-
|
582
|
+
update_example_title
|
445
583
|
else
|
446
584
|
yaml_file['paths'][current_path][request.method.downcase]['responses'].merge!(swagger_response)
|
585
|
+
update_example_title(true)
|
447
586
|
end
|
448
587
|
else
|
449
588
|
yaml_file['paths'][current_path][request.method.downcase]['responses'] = swagger_response
|
589
|
+
update_example_title
|
450
590
|
end
|
451
591
|
end
|
452
592
|
|
@@ -472,12 +612,31 @@ module SwaggerAutogenerate
|
|
472
612
|
|
473
613
|
def check_request_body
|
474
614
|
if paths[current_path][request.method.downcase]['requestBody'].present?
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
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
|
479
623
|
end
|
480
624
|
end
|
481
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
|
482
641
|
end
|
483
642
|
end
|
data/lib/swagger_autogenerate.rb
CHANGED
@@ -8,9 +8,23 @@ module SwaggerAutogenerate
|
|
8
8
|
def process_action(*args)
|
9
9
|
super
|
10
10
|
|
11
|
-
if
|
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
|
20
|
+
end
|
21
|
+
|
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
|
16
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.
|
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-
|
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
|