Commit 3a210c0e by andrew morton

Start hooking up consumes/produces

parent 53254556
...@@ -7,6 +7,10 @@ module RSpec ...@@ -7,6 +7,10 @@ module RSpec
@data = data.deep_symbolize_keys @data = data.deep_symbolize_keys
end end
def [](value)
data[value]
end
def resolve_ref(ref) def resolve_ref(ref)
unless %r{#/(?<location>parameters|definitions)/(?<name>.+)} =~ ref unless %r{#/(?<location>parameters|definitions)/(?<name>.+)} =~ ref
raise ArgumentError, "Invalid reference: #{ref}" raise ArgumentError, "Invalid reference: #{ref}"
......
module RSpec module RSpec
module Swagger module Swagger
module Helpers module Helpers
# paths: (Paths)
# /pets: (Path Item)
# post: (Operation)
# tags:
# - pet
# summary: Add a new pet to the store
# description: ""
# operationId: addPet
# consumes:
# - application/json
# produces:
# - application/json
# parameters: (Parameters)
# - in: body
# name: body
# description: Pet object that needs to be added to the store
# required: false
# schema:
# $ref: "#/definitions/Pet"
# responses: (Responses)
# "405": (Response)
# description: Invalid input
# The helpers serve as a DSL. # The helpers serve as a DSL.
def self.add_swagger_type_configurations(config) def self.add_swagger_type_configurations(config)
# The filters are used to ensure that the methods are nested correctly # The filters are used to ensure that the methods are nested correctly
...@@ -14,33 +37,6 @@ module RSpec ...@@ -14,33 +37,6 @@ module RSpec
config.include Resolver, :swagger_object config.include Resolver, :swagger_object
end end
=begin
paths: (Paths)
/pets: (Path Item)
post: (Operation)
tags:
- pet
summary: Add a new pet to the store
description: ""
operationId: addPet
consumes:
- application/json
- application/xml
produces:
- application/json
- application/xml
parameters: (Parameters)
- in: body
name: body
description: Pet object that needs to be added to the store
required: false
schema:
$ref: "#/definitions/Pet"
responses: (Responses)
"405": (Response)
description: Invalid input
=end
module Paths module Paths
def path template, attributes = {}, &block def path template, attributes = {}, &block
attributes.symbolize_keys! attributes.symbolize_keys!
...@@ -99,6 +95,14 @@ paths: (Paths) ...@@ -99,6 +95,14 @@ paths: (Paths)
end end
module Operation module Operation
def consumes *mime_types
metadata[:swagger_data][:consumes] = mime_types
end
def produces *mime_types
metadata[:swagger_data][:produces] = mime_types
end
def response status_code, desc, params = {}, headers = {}, &block def response status_code, desc, params = {}, headers = {}, &block
unless status_code == :default || (100..599).cover?(status_code) unless status_code == :default || (100..599).cover?(status_code)
raise ArgumentError, "status_code must be an integer 100 to 599, or :default" raise ArgumentError, "status_code must be an integer 100 to 599, or :default"
...@@ -107,23 +111,25 @@ paths: (Paths) ...@@ -107,23 +111,25 @@ paths: (Paths)
swagger_object: :status_code, swagger_object: :status_code,
swagger_data: metadata[:swagger_data].merge(status_code: status_code, response_description: desc) swagger_data: metadata[:swagger_data].merge(status_code: status_code, response_description: desc)
} }
describe("#{status_code}", meta) do describe(status_code, meta) do
self.module_exec(&block) if block_given? self.module_exec(&block) if block_given?
before do |example| before do |example|
method = example.metadata[:swagger_data][:operation] swagger_data = example.metadata[:swagger_data]
path = resolve_path(example.metadata[:swagger_data][:path], self)
path = resolve_path(swagger_data[:path], self)
headers = resolve_headers(swagger_data)
# Run the request
args = if ::Rails::VERSION::MAJOR >= 5 args = if ::Rails::VERSION::MAJOR >= 5
[path, {params: params, headers: headers}] [path, {params: params, headers: headers}]
else else
[path, params, headers] [path, params, headers]
end end
self.send(swagger_data[:operation], *args)
# Run the request
self.send(method, *args)
if example.metadata[:capture_example] if example.metadata[:capture_example]
example.metadata[:swagger_data][:example] = { swagger_data[:example] = {
body: response.body, body: response.body,
content_type: response.content_type.to_s content_type: response.content_type.to_s
} }
...@@ -144,6 +150,32 @@ paths: (Paths) ...@@ -144,6 +150,32 @@ paths: (Paths)
end end
module Resolver module Resolver
# TODO Really hate that we have to keep passing swagger_data around
# like this
def load_document swagger_data
::RSpec.configuration.swagger_docs[swagger_data[:document]]
end
def resolve_prodces swagger_data
swagger_data[:produces] #|| load_document(swagger_data)[:produces]
end
def resolve_consumes swagger_data
swagger_data[:consumes] #|| load_document(swagger_data)[:consumes]
end
def resolve_headers swagger_data
headers = {}
# Match the names that Rails uses internally
if produces = resolve_prodces(swagger_data)
headers['HTTP_ACCEPT'] = produces.join(';')
end
if consumes = resolve_consumes(swagger_data)
headers['CONTENT_TYPE'] = consumes.first
end
headers
end
def resolve_params swagger_data, group_instance def resolve_params swagger_data, group_instance
params = swagger_data[:params].values params = swagger_data[:params].values
# TODO resolve $refs # TODO resolve $refs
......
...@@ -3,16 +3,21 @@ require 'swagger_helper' ...@@ -3,16 +3,21 @@ require 'swagger_helper'
RSpec.describe "Requestsing", type: :request do RSpec.describe "Requestsing", type: :request do
path '/posts' do path '/posts' do
operation "GET", "fetch list" do operation "GET", "fetch list" do
produces 'application/json'
# params # params
response(200, "successful", {}, {'CONTENT_TYPE' => 'application/json', 'HTTP_ACCEPT' => 'application/json'}) response(200, "successful", {})
end end
operation "POST", "create" do operation "POST", "create" do
produces 'application/json'
consumes 'application/json'
parameter "body", in: :body parameter "body", in: :body
let(:body) { { post: { title: 'asdf', body: "blah" } } } let(:body) { { post: { title: 'asdf', body: "blah" } } }
# TODO: it should pull the body from the params # TODO: it should pull the body from the params
response(201, "successfully created", { post: { title: 'asdf', body: "blah" } }.to_json, {'CONTENT_TYPE' => 'application/json', 'HTTP_ACCEPT' => 'application/json'}) do response(201, "successfully created", { post: { title: 'asdf', body: "blah" } }.to_json) do
it "uses the body we passed in" do it "uses the body we passed in" do
post = JSON.parse(response.body) post = JSON.parse(response.body)
expect(post["title"]).to eq('asdf') expect(post["title"]).to eq('asdf')
...@@ -28,9 +33,11 @@ RSpec.describe "Requestsing", type: :request do ...@@ -28,9 +33,11 @@ RSpec.describe "Requestsing", type: :request do
let(:post_id) { 1 } let(:post_id) { 1 }
operation "GET", "fetch item" do operation "GET", "fetch item" do
produces 'application/json'
before { Post.new.save } before { Post.new.save }
parameter "op-param", {in: :query} parameter "op-param", {in: :query}
response(200, "success", {}, {'CONTENT_TYPE' => 'application/json', 'HTTP_ACCEPT' => 'application/json'}) do response(200, "success", {}) do
capture_example capture_example
end end
end end
......
...@@ -5,7 +5,7 @@ RSpec.describe RSpec::Swagger::Document do ...@@ -5,7 +5,7 @@ RSpec.describe RSpec::Swagger::Document do
let(:data) { minimial_example } let(:data) { minimial_example }
it "stores the data" do it "stores the data" do
expect(subject.data[:swagger]).to eq('2.0') expect(subject[:swagger]).to eq('2.0')
end end
describe "#resolve_ref" do describe "#resolve_ref" do
......
...@@ -40,17 +40,10 @@ RSpec.describe RSpec::Swagger::Formatter do ...@@ -40,17 +40,10 @@ RSpec.describe RSpec::Swagger::Formatter do
it "copies the requests into the document" do it "copies the requests into the document" do
formatter.example_finished(example_notification) formatter.example_finished(example_notification)
expect(formatter.documents.values.first).to eq({ expect(formatter.documents.values.first[:paths]).to eq({
swagger: '2.0', '/ping' => {
info: { put: {
version: '0.0.0', responses: {200 => {description: 'OK'}}
title: 'Simple API'
},
paths: {
'/ping' => {
put: {
responses: {200 => {description: 'OK'}}
}
} }
} }
}) })
......
...@@ -111,7 +111,7 @@ end ...@@ -111,7 +111,7 @@ end
RSpec.describe RSpec::Swagger::Helpers::Resolver do RSpec.describe RSpec::Swagger::Helpers::Resolver do
# Tthis helper is an include rather than an extend we can get it pulled into # Tthis helper is an include rather than an extend we can get it pulled into
# the test just by matching the filter metadata. # the test just by matching the filter metadata.
describe("#resolve_params", swagger_object: :something) do describe("#resolve_params", :swagger_object) do
let(:swagger_data) { { params: params } } let(:swagger_data) { { params: params } }
describe "with a missing value" do describe "with a missing value" do
...@@ -134,7 +134,7 @@ RSpec.describe RSpec::Swagger::Helpers::Resolver do ...@@ -134,7 +134,7 @@ RSpec.describe RSpec::Swagger::Helpers::Resolver do
end end
end end
describe("#resolve_path", swagger_object: :something) do describe "#resolve_path", :swagger_object do
describe "with a missing value" do describe "with a missing value" do
it "raises an error" do it "raises an error" do
expect{ resolve_path('/sites/{site_id}', self) }.to raise_exception(NoMethodError) expect{ resolve_path('/sites/{site_id}', self) }.to raise_exception(NoMethodError)
...@@ -156,4 +156,26 @@ RSpec.describe RSpec::Swagger::Helpers::Resolver do ...@@ -156,4 +156,26 @@ RSpec.describe RSpec::Swagger::Helpers::Resolver do
end end
end end
end end
describe "#resolve_headers", :swagger_object do
context "with consumes set" do
let(:swagger_data) { {consumes: ['application/json']} }
it "sets the Content-Type header" do
expect(resolve_headers(swagger_data)).to include('CONTENT_TYPE' => 'application/json')
end
end
context "with produces set" do
let(:swagger_data) { {produces: ['application/xml']} }
it "sets the Accepts header" do
expect(resolve_headers(swagger_data)).to include('HTTP_ACCEPT' => 'application/xml')
end
end
xit "includes paramters" do
end
end
end end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment