mirror of
https://github.com/ditkrg/rswag.git
synced 2026-01-22 22:06:43 +00:00
First iteration of rspec driven swagger
This commit is contained in:
parent
d579dab7d8
commit
63861a3940
@ -3,8 +3,8 @@ module SwaggerRails
|
||||
|
||||
def index
|
||||
@discovery_paths = Hash[
|
||||
SwaggerRails.swagger_docs.map do |name, path|
|
||||
[ name, "#{root_path}#{path}" ]
|
||||
SwaggerRails.swagger_docs.map do |path, doc|
|
||||
[ "#{root_path}#{path}", doc[:info][:title] ]
|
||||
end
|
||||
]
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
if (url && url.length > 1) {
|
||||
url = decodeURIComponent(url[1]);
|
||||
} else {
|
||||
url = "<%= @discovery_paths.values.first %>";
|
||||
url = "<%= @discovery_paths.keys.first %>";
|
||||
}
|
||||
|
||||
// Pre load translate...
|
||||
@ -110,8 +110,8 @@
|
||||
<div class='input'><input placeholder="api_key" id="input_apiKey" name="apiKey" type="text"/></div>
|
||||
<div class='input'>
|
||||
<select id="select_version">
|
||||
<% @discovery_paths.each do |name, path| %>
|
||||
<option value="<%= path %>"><%= name %></option>
|
||||
<% @discovery_paths.each do |path, title| %>
|
||||
<option value="<%= path %>"><%= title %></option>
|
||||
<% end %>
|
||||
</select>
|
||||
<script type="text/javascript">
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
SwaggerRails.configure do |c|
|
||||
|
||||
# List the names and paths (relative to config/swagger) of Swagger
|
||||
# documents you'd like to expose in your swagger-ui
|
||||
c.swagger_docs = {
|
||||
'API V1' => 'v1/swagger.json'
|
||||
}
|
||||
# Define the swagger documents you'd like to expose and provide global metadata
|
||||
c.swagger_doc 'v1/swagger.json' do
|
||||
{
|
||||
info: {
|
||||
title: 'API V1',
|
||||
version: 'v1'
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@ -7,10 +7,19 @@ module SwaggerRails
|
||||
end
|
||||
|
||||
class << self
|
||||
attr_accessor :swagger_docs
|
||||
attr_accessor :doc_factories
|
||||
@@doc_factories = {}
|
||||
|
||||
@@swagger_docs = {
|
||||
'V1' => 'v1/swagger.json'
|
||||
}
|
||||
def swagger_doc(path, &block)
|
||||
@@doc_factories[path] = block
|
||||
end
|
||||
|
||||
def swagger_docs
|
||||
Hash[
|
||||
@@doc_factories.map do |path, factory|
|
||||
[ path, { swagger: '2.0' }.merge(factory.call) ]
|
||||
end
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -5,55 +5,56 @@ module SwaggerRails
|
||||
module Adapter
|
||||
|
||||
def path(path_template, &block)
|
||||
describe(path_template, path_template: path_template, &block)
|
||||
metadata = {
|
||||
path_template: path_template
|
||||
}
|
||||
describe(path_template, metadata, &block)
|
||||
end
|
||||
|
||||
def operation(method, summary=nil, &block)
|
||||
operation_metadata = {
|
||||
method: method,
|
||||
def operation(http_verb, summary=nil, &block)
|
||||
metadata = {
|
||||
http_verb: http_verb,
|
||||
summary: summary,
|
||||
parameters: []
|
||||
}
|
||||
describe(method, operation: operation_metadata, &block)
|
||||
describe(http_verb, metadata, &block)
|
||||
end
|
||||
|
||||
[ :get, :post, :patch, :put, :delete, :head ].each do |http_verb|
|
||||
define_method(http_verb) do |summary=nil, &block|
|
||||
operation(http_verb, summary, &block)
|
||||
end
|
||||
end
|
||||
|
||||
def consumes(*mime_types)
|
||||
metadata[:operation][:consumes] = mime_types
|
||||
metadata[:consumes] = mime_types
|
||||
end
|
||||
|
||||
def produces(*mime_types)
|
||||
metadata[:operation][:produces] = mime_types
|
||||
metadata[:produces] = mime_types
|
||||
end
|
||||
|
||||
def header(name, attributes={})
|
||||
parameter(name, 'header', attributes)
|
||||
def parameter(name, attributes={})
|
||||
metadata[:parameters] << { name: name.to_s }.merge(attributes)
|
||||
end
|
||||
|
||||
def body(name, attributes={})
|
||||
parameter(name, 'body', attributes)
|
||||
end
|
||||
|
||||
def parameter(name, location, attributes={})
|
||||
parameter_metadata = { name: name.to_s, in: location }.merge(attributes)
|
||||
metadata[:operation][:parameters] << parameter_metadata
|
||||
end
|
||||
|
||||
def response(status, description, &block)
|
||||
response_metadata = { status: status, description: description }
|
||||
context(description, response: response_metadata, &block)
|
||||
def response(code, description, &block)
|
||||
metadata = {
|
||||
response_code: code,
|
||||
response: {
|
||||
description: description
|
||||
}
|
||||
}
|
||||
context(description, metadata, &block)
|
||||
end
|
||||
|
||||
def run_test!
|
||||
before do |example|
|
||||
SwaggerRails::TestVisitor.instance.act!(
|
||||
self, example.metadata[:path_template], example.metadata[:operation]
|
||||
)
|
||||
SwaggerRails::TestVisitor.instance.submit_request!(self, example.metadata)
|
||||
end
|
||||
|
||||
it "returns a #{metadata[:response][:status]} status" do |example|
|
||||
SwaggerRails::TestVisitor.instance.assert!(
|
||||
self, example.metadata[:response]
|
||||
)
|
||||
it "returns a #{metadata[:response_code]} status" do |example|
|
||||
SwaggerRails::TestVisitor.instance.assert_response!(self, example.metadata)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,36 +1,60 @@
|
||||
require 'rspec/core/formatters/base_text_formatter'
|
||||
require 'rails_helper'
|
||||
|
||||
module SwaggerRails
|
||||
module RSpec
|
||||
|
||||
class Formatter
|
||||
::RSpec::Core::Formatters.register self,
|
||||
:example_group_started,
|
||||
:example_group_finished,
|
||||
:stop
|
||||
|
||||
def initialize(output)
|
||||
@output = output
|
||||
@swagger_docs = {}
|
||||
@group_level = 0
|
||||
@swagger_docs = SwaggerRails.swagger_docs
|
||||
|
||||
@output.puts 'Generating Swagger Docs ...'
|
||||
end
|
||||
|
||||
def example_group_started(notification)
|
||||
@group_level += 1
|
||||
group = notification.group
|
||||
metadata = group.metadata
|
||||
|
||||
@output.puts "group_level: #{@group_level}"
|
||||
@output.puts metadata.slice(:doc, :path_template, :operation, :response).inspect
|
||||
end
|
||||
|
||||
def example_group_finished(notification)
|
||||
@group_level -= 1
|
||||
metadata = notification.group.metadata
|
||||
return unless metadata.has_key?(:response_code)
|
||||
|
||||
swagger_data = swagger_data_from(metadata)
|
||||
swagger_doc = @swagger_docs[metadata[:docs_path]] || @swagger_docs.values.first
|
||||
swagger_doc.deep_merge!(swagger_data)
|
||||
end
|
||||
|
||||
def stop(notification)
|
||||
@swagger_docs.each do |path, doc|
|
||||
file_path = File.join(Rails.root, 'config/swagger', path)
|
||||
|
||||
File.open(file_path, 'w') do |file|
|
||||
file.write(JSON.pretty_generate(doc))
|
||||
end
|
||||
end
|
||||
|
||||
@output.puts 'Swagger Doc generated'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def swagger_data_from(metadata)
|
||||
{
|
||||
paths: {
|
||||
metadata[:path_template] => {
|
||||
metadata[:http_verb] => operation_from(metadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def operation_from(metadata)
|
||||
metadata.slice(:summary, :consumes, :produces, :parameters).tap do |operation|
|
||||
operation[:responses] = {
|
||||
metadata[:response_code] => metadata[:response]
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -5,18 +5,18 @@ module SwaggerRails
|
||||
|
||||
include Singleton
|
||||
|
||||
def act!(test, path_template, operation)
|
||||
params_data = params_data_for(test, operation[:parameters])
|
||||
def submit_request!(test, metadata)
|
||||
params_data = params_data_for(test, metadata[:parameters])
|
||||
|
||||
path = build_path(path_template, params_data)
|
||||
path = build_path(metadata[:path_template], params_data)
|
||||
body_or_params = build_body_or_params(params_data)
|
||||
headers = build_headers(params_data, operation[:consumes], operation[:produces])
|
||||
headers = build_headers(params_data, metadata[:consumes], metadata[:produces])
|
||||
|
||||
test.send(operation[:method], path, body_or_params, headers)
|
||||
test.send(metadata[:http_verb], path, body_or_params, headers)
|
||||
end
|
||||
|
||||
def assert!(test, expected_response)
|
||||
test.assert_response(expected_response[:status].to_i)
|
||||
def assert_response!(test, metadata)
|
||||
test.assert_response(metadata[:response_code].to_i)
|
||||
end
|
||||
|
||||
private
|
||||
@ -30,57 +30,29 @@ module SwaggerRails
|
||||
end
|
||||
|
||||
def build_path(path_template, params_data)
|
||||
path = path_template.dup
|
||||
params_data.each do |param_data|
|
||||
path.sub!("\{#{param_data[:name]}\}", param_data[:value].to_s)
|
||||
path_template.dup.tap do |path|
|
||||
params_data.each do |param_data|
|
||||
path.sub!("\{#{param_data[:name]}\}", param_data[:value].to_s)
|
||||
end
|
||||
end
|
||||
return path
|
||||
end
|
||||
|
||||
def build_body_or_params(params_data)
|
||||
body_params_data = params_data.select { |p| p[:in] == 'body' }
|
||||
body_params_data = params_data.select { |p| p[:in] == :body }
|
||||
return body_params_data.first[:value].to_json if body_params_data.any?
|
||||
|
||||
query_params_data = params_data.select { |p| p[:in] == 'query' }
|
||||
query_params_data = params_data.select { |p| p[:in] == :query }
|
||||
Hash[query_params_data.map { |p| [ p[:name], p[:value] ] }]
|
||||
end
|
||||
|
||||
def build_headers(params_data, consumes, produces)
|
||||
header_params_data = params_data.select { |p| p[:in] == 'header' }
|
||||
header_params_data = params_data.select { |p| p[:in] == :header }
|
||||
headers = Hash[header_params_data.map { |p| [ p[:name].underscore.upcase, p[:value] ] }]
|
||||
|
||||
headers['ACCEPT'] = consumes.join(';') if consumes.present?
|
||||
headers['CONTENT_TYPE'] = produces.join(';') if produces.present?
|
||||
headers['ACCEPT'] = produces.join(';') if produces.present?
|
||||
headers['CONTENT_TYPE'] = consumes.join(';') if consumes.present?
|
||||
|
||||
return headers
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#require 'swagger_rails/testing/test_case_builder'
|
||||
#
|
||||
#module SwaggerRails
|
||||
#
|
||||
# class TestVisitor
|
||||
#
|
||||
# def initialize(swagger)
|
||||
# @swagger = swagger
|
||||
# end
|
||||
#
|
||||
# def run_test(path_template, http_method, test, &block)
|
||||
# builder = TestCaseBuilder.new(path_template, http_method, @swagger)
|
||||
# builder.instance_exec(&block) if block_given?
|
||||
# test_data = builder.test_data
|
||||
#
|
||||
# test.send(http_method,
|
||||
# test_data[:path],
|
||||
# test_data[:params],
|
||||
# test_data[:headers]
|
||||
# )
|
||||
#
|
||||
# test.assert_response(test_data[:expected_response][:status])
|
||||
# test.assert_equal(test_data[:expected_response][:body], JSON.parse(test.response.body))
|
||||
# end
|
||||
# end
|
||||
#end
|
||||
#
|
||||
|
||||
@ -8,5 +8,5 @@ require 'rspec/core/rake_task'
|
||||
desc 'Generate Swagger JSON files from integration specs'
|
||||
RSpec::Core::RakeTask.new('swagger_rails:gen') do |t|
|
||||
t.pattern = 'spec/integration/**/*_spec.rb'
|
||||
t.rspec_opts = [ '--format SwaggerRails::RSpec::SwaggerFormatter' ]
|
||||
t.rspec_opts = [ '--format SwaggerRails::RSpec::Formatter', '--dry-run' ]
|
||||
end
|
||||
|
||||
@ -5,6 +5,7 @@ class Blog < ActiveRecord::Base
|
||||
|
||||
def as_json(options)
|
||||
{
|
||||
id: id,
|
||||
title: title,
|
||||
content: content
|
||||
}
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
SwaggerRails.configure do |c|
|
||||
|
||||
# List the names and paths (relative to config/swagger) of Swagger
|
||||
# documents you'd like to expose in your swagger-ui
|
||||
c.swagger_docs = {
|
||||
'API V1' => 'v1/swagger.json'
|
||||
}
|
||||
# Define the swagger documents you'd like to expose and provide global metadata
|
||||
c.swagger_doc 'v1/swagger.json' do
|
||||
{
|
||||
info: {
|
||||
title: 'API V1',
|
||||
version: 'v1'
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,122 +1,79 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"version": "0.0.0",
|
||||
"title": "Dummy app for testing swagger_rails"
|
||||
},
|
||||
"paths": {
|
||||
"/blogs": {
|
||||
"post": {
|
||||
"description": "Creates a new Blog",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "X-Forwarded-For",
|
||||
"in": "header",
|
||||
"type": "string",
|
||||
"default": "client1"
|
||||
},
|
||||
{
|
||||
"name": "blog",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Blog"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Created",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Blog"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/RequestError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"get": {
|
||||
"description": "Searches Bloggs",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "published",
|
||||
"in": "query",
|
||||
"type": "boolean",
|
||||
"default": "true"
|
||||
},
|
||||
{
|
||||
"name": "keywords",
|
||||
"in": "query",
|
||||
"type": "string",
|
||||
"default": "Ruby on Rails"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Ok",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"item": {
|
||||
"$ref": "#/definitions/Blog"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
"/blogs/{id}": {
|
||||
"get": {
|
||||
"description": "Retrieves a specific Blog by unique ID",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"type": "string",
|
||||
"default": "123"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Ok",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Blog"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"Blog": {
|
||||
"properties": {
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "API V1",
|
||||
"version": "v1"
|
||||
},
|
||||
"paths": {
|
||||
"/blogs": {
|
||||
"post": {
|
||||
"summary": "creates a new blog",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "blog",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "string"
|
||||
"type": "string"
|
||||
},
|
||||
"content": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"title": "Test Blog",
|
||||
"content": "Hello World"
|
||||
}
|
||||
},
|
||||
"RequestError": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"item": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"title": [ "is required" ]
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "valid request"
|
||||
},
|
||||
"422": {
|
||||
"description": "invalid request"
|
||||
}
|
||||
}
|
||||
},
|
||||
"get": {
|
||||
"summary": "searches existing blogs",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"parameters": [
|
||||
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "valid request"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/blogs/{id}": {
|
||||
"get": {
|
||||
"summary": "retreives a specific blog",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "blog found"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,19 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'Blogs API', doc: 'blogs/v1' do
|
||||
describe 'Blogs API', docs_path: 'blogs/v1/swagger.json' do
|
||||
|
||||
path '/blogs' do
|
||||
|
||||
operation 'post', 'creates a new blog' do
|
||||
post 'creates a new blog' do
|
||||
consumes 'application/json'
|
||||
produces 'application/json'
|
||||
body :blog
|
||||
parameter :blog, :in => :body, schema: {
|
||||
:type => :object,
|
||||
:properties => {
|
||||
title: { type: 'string' },
|
||||
content: { type: 'string' }
|
||||
}
|
||||
}
|
||||
|
||||
let(:blog) { { title: 'foo', content: 'bar' } }
|
||||
|
||||
@ -21,7 +27,7 @@ describe 'Blogs API', doc: 'blogs/v1' do
|
||||
end
|
||||
end
|
||||
|
||||
operation 'get', 'searches existing blogs' do
|
||||
get 'searches existing blogs' do
|
||||
produces 'application/json'
|
||||
|
||||
response '200', 'valid request' do
|
||||
@ -31,9 +37,9 @@ describe 'Blogs API', doc: 'blogs/v1' do
|
||||
end
|
||||
|
||||
path '/blogs/{id}' do
|
||||
operation 'get', 'retreives a specific blog' do
|
||||
get 'retreives a specific blog' do
|
||||
produces 'application/json'
|
||||
parameter :id, 'path'
|
||||
parameter :id, :in => :path, :type => :string
|
||||
|
||||
response '200', 'blog found' do
|
||||
let(:blog) { Blog.create(title: 'foo', content: 'bar') }
|
||||
|
||||
@ -50,4 +50,7 @@ RSpec.configure do |config|
|
||||
config.filter_rails_from_backtrace!
|
||||
# arbitrary gems may also be filtered via:
|
||||
# config.filter_gems_from_backtrace("gem name")
|
||||
|
||||
require 'swagger_rails/rspec/adapter'
|
||||
config.extend SwaggerRails::RSpec::Adapter
|
||||
end
|
||||
|
||||
@ -89,7 +89,4 @@ RSpec.configure do |config|
|
||||
# as the one that triggered the failure.
|
||||
Kernel.srand config.seed
|
||||
=end
|
||||
|
||||
require 'swagger_rails/rspec/adapter'
|
||||
config.extend SwaggerRails::RSpec::Adapter
|
||||
end
|
||||
|
||||
107
spec/test_visitor_spec.rb
Normal file
107
spec/test_visitor_spec.rb
Normal file
@ -0,0 +1,107 @@
|
||||
require 'rails_helper'
|
||||
require 'swagger_rails/test_visitor'
|
||||
|
||||
module SwaggerRails
|
||||
|
||||
describe TestVisitor do
|
||||
let(:test) { spy('test') }
|
||||
subject { described_class.instance }
|
||||
|
||||
describe '#submit_request!' do
|
||||
before { subject.submit_request!(test, metadata) }
|
||||
|
||||
context 'always' do
|
||||
let(:metadata) do
|
||||
{
|
||||
path_template: '/resource',
|
||||
http_verb: :get,
|
||||
parameters: []
|
||||
}
|
||||
end
|
||||
|
||||
it 'dispatches the request to the provided test object' do
|
||||
expect(test).to have_received(:get)
|
||||
end
|
||||
end
|
||||
|
||||
context 'given path parameters' do
|
||||
let(:metadata) do
|
||||
allow(test).to receive(:id).and_return(1)
|
||||
return {
|
||||
path_template: '/resource/{id}',
|
||||
http_verb: :get,
|
||||
parameters: [ { name: 'id', :in => :path, type: 'string' } ]
|
||||
}
|
||||
end
|
||||
|
||||
it 'builds the path from values on the test object' do
|
||||
expect(test).to have_received(:get).with('/resource/1', {}, {})
|
||||
end
|
||||
end
|
||||
|
||||
context 'given body parameters' do
|
||||
let(:metadata) do
|
||||
allow(test).to receive(:resource).and_return({ foo: 'bar' })
|
||||
return {
|
||||
path_template: '/resource',
|
||||
http_verb: :post,
|
||||
consumes: [ 'application/json' ],
|
||||
parameters: [ { name: 'resource', :in => :body, schema: { type: 'object' } } ]
|
||||
}
|
||||
end
|
||||
|
||||
it 'builds a body from value on the test object' do
|
||||
expect(test).to have_received(:post).with(
|
||||
'/resource',
|
||||
"{\"foo\":\"bar\"}",
|
||||
{ 'CONTENT_TYPE' => 'application/json' }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'given query parameters' do
|
||||
let(:metadata) do
|
||||
allow(test).to receive(:type).and_return('foo')
|
||||
return {
|
||||
path_template: '/resource',
|
||||
http_verb: :get,
|
||||
parameters: [ { name: 'type', :in => :query, type: 'string' } ]
|
||||
}
|
||||
end
|
||||
|
||||
it 'builds query params from values on the test object' do
|
||||
expect(test).to have_received(:get).with('/resource', { 'type' => 'foo' }, {})
|
||||
end
|
||||
end
|
||||
|
||||
context 'given header parameters' do
|
||||
let(:metadata) do
|
||||
allow(test).to receive(:date).and_return('2000-01-01')
|
||||
return {
|
||||
path_template: '/resource',
|
||||
http_verb: :get,
|
||||
produces: [ 'application/json' ],
|
||||
parameters: [ { name: 'Date', :in => :header, type: 'string' } ]
|
||||
}
|
||||
end
|
||||
|
||||
it 'builds request headers from values on the test object' do
|
||||
expect(test).to have_received(:get).with(
|
||||
'/resource',
|
||||
{},
|
||||
{ 'DATE' => '2000-01-01', 'ACCEPT' => 'application/json' }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#assert_response' do
|
||||
before { subject.assert_response!(test, metadata) }
|
||||
let(:metadata) { { response_code: '200' } }
|
||||
|
||||
it 'dispatches the assert to the provided test object' do
|
||||
expect(test).to have_received(:assert_response).with(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,139 +0,0 @@
|
||||
require 'rails_helper'
|
||||
require 'swagger_rails/testing/test_case_builder'
|
||||
|
||||
module SwaggerRails
|
||||
|
||||
describe TestCaseBuilder do
|
||||
subject { described_class.new(path, method, swagger) }
|
||||
let(:swagger) do
|
||||
file_path = File.join(Rails.root, 'config/swagger', 'v1/swagger.json')
|
||||
JSON.parse(File.read(file_path))
|
||||
end
|
||||
|
||||
describe '#test_data' do
|
||||
let(:test_data) { subject.test_data }
|
||||
|
||||
context 'swagger includes basePath' do
|
||||
before { swagger['basePath'] = '/foobar' }
|
||||
let(:path) { '/blogs' }
|
||||
let(:method) { 'post' }
|
||||
|
||||
it 'includes a path prefixed with basePath' do
|
||||
expect(test_data[:path]).to eq('/foobar/blogs')
|
||||
end
|
||||
end
|
||||
|
||||
context 'operation has path params' do
|
||||
let(:path) { '/blogs/{id}' }
|
||||
let(:method) { 'get' }
|
||||
|
||||
context 'by default' do
|
||||
it "includes a path built from 'default' values" do
|
||||
expect(test_data[:path]).to eq('/blogs/123')
|
||||
end
|
||||
end
|
||||
|
||||
context 'values explicitly set' do
|
||||
before { subject.set id: '456' }
|
||||
it 'includes a path built from set values' do
|
||||
expect(test_data[:path]).to eq('/blogs/456')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'operation has query params' do
|
||||
let(:path) { '/blogs' }
|
||||
let(:method) { 'get' }
|
||||
|
||||
context 'by default' do
|
||||
it "includes params built from 'default' values" do
|
||||
expect(test_data[:params]).to eq({ 'published' => 'true', 'keywords' => 'Ruby on Rails' })
|
||||
end
|
||||
end
|
||||
|
||||
context 'values explicitly set' do
|
||||
before { subject.set keywords: 'Java' }
|
||||
it 'includes params build from set values' do
|
||||
expect(test_data[:params]).to eq({ 'published' => 'true', 'keywords' => 'Java' })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'operation has body param' do
|
||||
let(:path) { '/blogs' }
|
||||
let(:method) { 'post' }
|
||||
|
||||
context 'by default' do
|
||||
it "includes params string based on schema 'example'" do
|
||||
expect(test_data[:params]).to eq({ 'title' => 'Test Blog', 'content' => 'Hello World' }.to_json)
|
||||
end
|
||||
end
|
||||
|
||||
context 'values explicitly set' do
|
||||
before { subject.set blog: { 'title' => 'foobar' } }
|
||||
it 'includes params string based on set value' do
|
||||
expect(test_data[:params]).to eq({ 'title' => 'foobar' }.to_json)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'operation has header params' do
|
||||
let(:path) { '/blogs' }
|
||||
let(:method) { 'post' }
|
||||
|
||||
context 'by default' do
|
||||
it "includes headers built from 'default' values" do
|
||||
expect(test_data[:headers]).to eq({
|
||||
'X-Forwarded-For' => 'client1',
|
||||
'CONTENT_TYPE' => 'application/json',
|
||||
'ACCEPT' => 'application/json'
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
context 'values explicitly params' do
|
||||
before { subject.set 'X-Forwarded-For' => '192.168.1.1' }
|
||||
it 'includes headers built from set values' do
|
||||
expect(test_data[:headers]).to eq({
|
||||
'X-Forwarded-For' => '192.168.1.1',
|
||||
'CONTENT_TYPE' => 'application/json',
|
||||
'ACCEPT' => 'application/json'
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'operation returns an object' do
|
||||
let(:path) { '/blogs' }
|
||||
let(:method) { 'post' }
|
||||
|
||||
context 'by default' do
|
||||
it "includes expected_response based on spec'd 2xx status" do
|
||||
expect(test_data[:expected_response][:status]).to eq(201)
|
||||
expect(test_data[:expected_response][:body]).to eq({ 'title' => 'Test Blog', 'content' => 'Hello World' })
|
||||
end
|
||||
end
|
||||
|
||||
context 'expected status explicitly set' do
|
||||
before { subject.expect 400 }
|
||||
it "includes expected_response based on set status" do
|
||||
expect(test_data[:expected_response][:status]).to eq(400)
|
||||
expect(test_data[:expected_response][:body]).to eq({ 'title' => [ 'is required' ] })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'operation returns an array' do
|
||||
let(:path) { '/blogs' }
|
||||
let(:method) { 'get' }
|
||||
|
||||
context 'by default' do
|
||||
it "includes expected_response based on spec'd 2xx status" do
|
||||
expect(test_data[:expected_response][:status]).to eq(200)
|
||||
expect(test_data[:expected_response][:body]).to eq([ { 'title' => 'Test Blog', 'content' => 'Hello World' } ])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,79 +0,0 @@
|
||||
require 'rails_helper'
|
||||
require 'swagger_rails/testing/test_visitor'
|
||||
|
||||
module SwaggerRails
|
||||
|
||||
describe TestVisitor do
|
||||
subject { described_class.new(swagger) }
|
||||
let(:swagger) do
|
||||
file_path = File.join(Rails.root, 'config/swagger', 'v1/swagger.json')
|
||||
JSON.parse(File.read(file_path))
|
||||
end
|
||||
let(:test) { spy('test') }
|
||||
|
||||
describe '#run_test' do
|
||||
before do
|
||||
allow(test).to receive(:response).and_return(OpenStruct.new(body: "{}"))
|
||||
end
|
||||
|
||||
context 'by default' do
|
||||
before { subject.run_test('/blogs', 'post', test) }
|
||||
|
||||
it "submits request based on 'default' and 'example' param values" do
|
||||
expect(test).to have_received(:post).with(
|
||||
'/blogs',
|
||||
{ 'title' => 'Test Blog', 'content' => 'Hello World' }.to_json,
|
||||
{ 'X-Forwarded-For' => 'client1', 'CONTENT_TYPE' => 'application/json', 'ACCEPT' => 'application/json' }
|
||||
)
|
||||
end
|
||||
|
||||
it "asserts response matches spec'd 2xx status" do
|
||||
expect(test).to have_received(:assert_response).with(201)
|
||||
end
|
||||
|
||||
it "asserts response body matches schema 'example' for 2xx status" do
|
||||
expect(test).to have_received(:assert_equal).with(
|
||||
{ 'title' => 'Test Blog', 'content' => 'Hello World' },
|
||||
{}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'param values explicitly provided' do
|
||||
before do
|
||||
subject.run_test('/blogs', 'post', test) do
|
||||
set blog: { 'title' => 'foobar' }
|
||||
set 'X-Forwarded-For' => '192.168.1.1'
|
||||
end
|
||||
end
|
||||
|
||||
it 'submits a request based on provided param values' do
|
||||
expect(test).to have_received(:post).with(
|
||||
'/blogs',
|
||||
{ 'title' => 'foobar' }.to_json,
|
||||
{ 'X-Forwarded-For' => '192.168.1.1', 'CONTENT_TYPE' => 'application/json', 'ACCEPT' => 'application/json' }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'expected status explicitly set' do
|
||||
before do
|
||||
subject.run_test('/blogs', 'post', test) do
|
||||
expect 400
|
||||
end
|
||||
end
|
||||
|
||||
it "asserts response matches set status" do
|
||||
expect(test).to have_received(:assert_response).with(400)
|
||||
end
|
||||
|
||||
it "asserts response body matches schema 'example' for set status" do
|
||||
expect(test).to have_received(:assert_equal).with(
|
||||
{ 'title' => [ 'is required' ] },
|
||||
{}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue
Block a user