From acebef6eae1fd4dc746de1a356aa141e4f0a85b8 Mon Sep 17 00:00:00 2001 From: Kriston Date: Mon, 22 Mar 2021 14:57:25 -0400 Subject: [PATCH 1/2] I have no idea what Im doing --- rswag-specs/lib/rswag/specs/example_group_helpers.rb | 12 ++++++++++++ rswag-specs/lib/rswag/specs/swagger_formatter.rb | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/rswag-specs/lib/rswag/specs/example_group_helpers.rb b/rswag-specs/lib/rswag/specs/example_group_helpers.rb index 591a7e9cd..7930fad2f 100644 --- a/rswag-specs/lib/rswag/specs/example_group_helpers.rb +++ b/rswag-specs/lib/rswag/specs/example_group_helpers.rb @@ -51,6 +51,18 @@ def parameter(attributes) end end + + def request_body_example(name:, summary:, value:, mime:) + if metadata.key?(:operation) + metadata[:operation][:request_examples] ||= {} + metadata[:operation][:request_examples][mime] ||= {} + metadata[:operation][:request_examples][mime][name] = { + value: value, + summary: summary, + } + end + end + def response(code, description, metadata = {}, &block) metadata[:response] = { code: code, description: description } context(description, metadata, &block) diff --git a/rswag-specs/lib/rswag/specs/swagger_formatter.rb b/rswag-specs/lib/rswag/specs/swagger_formatter.rb index e640da351..d9d7e1438 100644 --- a/rswag-specs/lib/rswag/specs/swagger_formatter.rb +++ b/rswag-specs/lib/rswag/specs/swagger_formatter.rb @@ -60,7 +60,12 @@ def stop(_notification = nil) if value && schema_param && mime_list value[:requestBody] = { content: {} } unless value.dig(:requestBody, :content) mime_list.each do |mime| + value[:requestBody][:content][mime] = { schema: schema_param[:schema] } + examples = value.dig(:request_examples, mime) + if examples + value[:requestBody][:content][mime][:examples] = examples + end end end @@ -209,6 +214,7 @@ def remove_invalid_operation_keys!(value) is_hash = value.is_a?(Hash) value.delete(:consumes) if is_hash && value.dig(:consumes) value.delete(:produces) if is_hash && value.dig(:produces) + value.delete(:request_examples) if is_hash && value.dig(:request_examples) end end end From 894dcfad18a22d4cef60cfffb9faff8171759677 Mon Sep 17 00:00:00 2001 From: Kriston Date: Tue, 23 Mar 2021 12:01:16 -0400 Subject: [PATCH 2/2] Adding support for examples and tests --- .../lib/rswag/specs/example_group_helpers.rb | 14 +-- .../lib/rswag/specs/swagger_formatter.rb | 11 ++- .../rswag/specs/example_group_helpers_spec.rb | 32 +++++++ .../rswag/specs/swagger_formatter_spec.rb | 92 ++++++++++++++++++- 4 files changed, 138 insertions(+), 11 deletions(-) diff --git a/rswag-specs/lib/rswag/specs/example_group_helpers.rb b/rswag-specs/lib/rswag/specs/example_group_helpers.rb index 7930fad2f..d66290656 100644 --- a/rswag-specs/lib/rswag/specs/example_group_helpers.rb +++ b/rswag-specs/lib/rswag/specs/example_group_helpers.rb @@ -52,14 +52,14 @@ def parameter(attributes) end - def request_body_example(name:, summary:, value:, mime:) + def request_body_example(value:, summary: nil, name: nil) if metadata.key?(:operation) - metadata[:operation][:request_examples] ||= {} - metadata[:operation][:request_examples][mime] ||= {} - metadata[:operation][:request_examples][mime][name] = { - value: value, - summary: summary, - } + metadata[:operation][:request_examples] ||= [] + example = { value: value } + example[:summary] = summary if summary + # We need the examples to have a unique name for a set of examples, so just make the name the length if one isn't provided. + example[:name] = name || metadata[:operation][:request_examples].length() + metadata[:operation][:request_examples] << example end end diff --git a/rswag-specs/lib/rswag/specs/swagger_formatter.rb b/rswag-specs/lib/rswag/specs/swagger_formatter.rb index d9d7e1438..1cb6559f0 100644 --- a/rswag-specs/lib/rswag/specs/swagger_formatter.rb +++ b/rswag-specs/lib/rswag/specs/swagger_formatter.rb @@ -59,12 +59,17 @@ def stop(_notification = nil) mime_list = value.dig(:consumes) if value && schema_param && mime_list value[:requestBody] = { content: {} } unless value.dig(:requestBody, :content) + examples = value.dig(:request_examples) mime_list.each do |mime| - value[:requestBody][:content][mime] = { schema: schema_param[:schema] } - examples = value.dig(:request_examples, mime) if examples - value[:requestBody][:content][mime][:examples] = examples + value[:requestBody][:content][mime][:examples] ||= {} + examples.map do |example| + value[:requestBody][:content][mime][:examples][example[:name]] = { + summary: example[:summary] || value[:summary], + value: example[:value] + } + end end end end diff --git a/rswag-specs/spec/rswag/specs/example_group_helpers_spec.rb b/rswag-specs/spec/rswag/specs/example_group_helpers_spec.rb index 29225230b..ffb5e967d 100644 --- a/rswag-specs/spec/rswag/specs/example_group_helpers_spec.rb +++ b/rswag-specs/spec/rswag/specs/example_group_helpers_spec.rb @@ -136,6 +136,38 @@ module Specs end end + describe '#request_body_example(value:, summary: nil, name: nil)' do + context "when adding one example" do + before { subject.request_body_example(value: value)} + let(:api_metadata) { { operation: {} } } + let(:value) { { field: 'A', another_field: 'B' } } + + it "assigns the example to the metadata" do + expect(api_metadata[:operation][:request_examples].length()).to eq(1) + expect(api_metadata[:operation][:request_examples][0]).to eq({ value: value, name: 0 }) + end + end + + context "when adding multiple examples with additional information" do + before { + subject.request_body_example(value: example_one) + subject.request_body_example(value: example_two, name: example_two_name, summary: example_two_summary) + } + let(:api_metadata) { { operation: {} } } + let(:example_one) { { field: 'A', another_field: 'B' } } + let(:example_two) { { field: 'B', another_field: 'C' } } + let(:example_two_name) { 'example_two' } + let(:example_two_summary) { 'An example description' } + + it "assigns all examples to the metadata" do + expect(api_metadata[:operation][:request_examples].length()).to eq(2) + expect(api_metadata[:operation][:request_examples][0]).to eq({ value: example_one, name: 0 }) + expect(api_metadata[:operation][:request_examples][1]).to eq({ value: example_two, name: example_two_name, summary: example_two_summary }) + end + end + end + + describe '#examples(example)' do let(:json_example) do { diff --git a/rswag-specs/spec/rswag/specs/swagger_formatter_spec.rb b/rswag-specs/spec/rswag/specs/swagger_formatter_spec.rb index 1a58315b7..79f30d212 100644 --- a/rswag-specs/spec/rswag/specs/swagger_formatter_spec.rb +++ b/rswag-specs/spec/rswag/specs/swagger_formatter_spec.rb @@ -21,12 +21,17 @@ module Specs allow(config).to receive(:get_swagger_doc).and_return(swagger_doc) subject.example_group_finished(notification) end + let(:request_examples) { nil } let(:notification) { OpenStruct.new(group: OpenStruct.new(metadata: api_metadata)) } let(:api_response) { { code: '201', description: 'blog created', headers: { type: :string }, schema: { '$ref' => '#/definitions/blog' } } } let(:api_metadata) do + operation = { verb: :post, summary: 'Creates a blog', parameters: [{ type: :string }] } + if request_examples + operation[:request_examples] = request_examples + end { path_item: { template: '/blogs', parameters: [{ type: :string }] }, - operation: { verb: :post, summary: 'Creates a blog', parameters: [{ type: :string }] }, + operation: operation, response: api_response, document: document } @@ -396,6 +401,91 @@ module Specs after do FileUtils.rm_r(swagger_root) if File.exist?(swagger_root) end + + + context 'with request examples' do + let(:doc_2) do + { + paths: { + '/path/' => { + post: { + summary: 'Retrieve Nested Paths', + tags: ['nested Paths'], + produces: ['application/json'], + consumes: ['application/json'], + parameters: [{ + in: :body, + schema: { + '$ref': '#/components/schemas/BlogPost' + } + },{ + in: :headers + }], + request_examples: [ + { + name: 'basic', + value: { + some_field: 'Foo' + }, + summary: 'An example' + }, + { + name: 'another_basic', + value: { + some_field: 'Bar' + } + } + ], + } + } + }, + components: { + schemas: { + 'BlogPost' => { + type: 'object', + properties: { + some_field: { + type: 'string', + description: 'description' + } + } + } + } + } + } + end + + it 'removes remaining request_examples' do + expect(doc_2[:paths]['/path/'][:post].keys).to eql([:summary, :tags, :parameters, :requestBody]) + end + + it 'creates requestBody examples' do + expect(doc_2[:paths]['/path/'][:post][:parameters]).to eql([{ in: :headers }]) + expect(doc_2[:paths]['/path/'][:post][:requestBody]).to eql(content: { + 'application/json' => { + schema: { '$ref': '#/components/schemas/BlogPost' }, + examples: { + 'basic' => { + value: { + some_field: 'Foo' + }, + summary: 'An example' + }, + 'another_basic' => { + value: { + some_field: 'Bar' + }, + summary: 'Retrieve Nested Paths' + } + } + } + }) + end + end + + after do + FileUtils.rm_r(swagger_root) if File.exist?(swagger_root) + end end end end