diff --git a/rswag-specs/lib/rswag/specs/response_validator.rb b/rswag-specs/lib/rswag/specs/response_validator.rb index 7a04c37..3ee2266 100644 --- a/rswag-specs/lib/rswag/specs/response_validator.rb +++ b/rswag-specs/lib/rswag/specs/response_validator.rb @@ -13,6 +13,7 @@ module Rswag def validate!(response) validate_code!(response.code) + validate_headers!(response.headers) validate_body!(response.body) end @@ -24,6 +25,20 @@ module Rswag end end + def validate_headers!(headers) + header_schema = @api_metadata[:response][:headers] + return if header_schema.nil? + header_schema.each do |header_name, schema| + validate_header!(schema, header_name, headers[header_name.to_s]) + end + end + + def validate_header!(schema, header_name, header_value) + JSON::Validator.validate!(schema.merge(@global_metadata), header_value.to_json) + rescue JSON::Schema::ValidationError => ex + raise UnexpectedResponse, "Expected response headers #{header_name} to match schema: #{ex.message}" + end + def validate_body!(body) response_schema = @api_metadata[:response][:schema] return if response_schema.nil? @@ -34,7 +49,7 @@ module Rswag .merge(@global_metadata.slice(:definitions)) JSON::Validator.validate!(validation_schema, body) rescue JSON::Schema::ValidationError => ex - raise UnexpectedResponse, "Expected response body to match schema: #{ex.message}" + raise UnexpectedResponse, "Expected response body to match schema: #{ex.message}" end end end diff --git a/rswag-specs/spec/rswag/specs/response_validator_spec.rb b/rswag-specs/spec/rswag/specs/response_validator_spec.rb index c914264..e1d9d3f 100644 --- a/rswag-specs/spec/rswag/specs/response_validator_spec.rb +++ b/rswag-specs/spec/rswag/specs/response_validator_spec.rb @@ -66,6 +66,43 @@ module Rswag it { expect { call }.to raise_error UnexpectedResponse } end end + + context "'headers' provided" do + before do + api_metadata[:response][:headers] = { + 'X-Rate-Limit-Limit' => { + description: 'The number of allowed requests in the current period', + type: 'integer' + }, + 'X-Rate-Limit-Remaining' => { + description: 'The number of remaining requests in the current period', + type: 'integer' + }, + 'X-Rate-Limit-Reset' => { + description: 'The number of seconds left in the current period', + type: 'integer' + } + } + end + + context 'response code & body matches' do + let(:response) { OpenStruct.new(code: 200, body: '{}', headers: { + 'X-Rate-Limit-Limit' => 1, + 'X-Rate-Limit-Remaining' => 1, + 'X-Rate-Limit-Reset' => 1 + }) } + it { expect { call }.to_not raise_error } + end + + context 'response code matches & body does not' do + let(:response) { OpenStruct.new(code: 200, body: '{}', headers: { + 'X-Rate-Limit-Limit' => 'invalid', + 'X-Rate-Limit-Remaining' => 'invalid', + 'X-Rate-Limit-Reset' => 'invalid' + }) } + it { expect { call }.to raise_error UnexpectedResponse } + end + end end end end diff --git a/test-app/app/controllers/blogs_controller.rb b/test-app/app/controllers/blogs_controller.rb index dd1aca3..261d718 100644 --- a/test-app/app/controllers/blogs_controller.rb +++ b/test-app/app/controllers/blogs_controller.rb @@ -17,6 +17,10 @@ class BlogsController < ApplicationController # GET /blogs/1 def show @blog = Blog.find_by_id(params[:id]) + + fresh_when(@blog) + return unless stale?(@blog) + respond_with @blog, status: :not_found and return unless @blog respond_with @blog end diff --git a/test-app/spec/integration/blogs_spec.rb b/test-app/spec/integration/blogs_spec.rb index 588ddb8..7a49ce9 100644 --- a/test-app/spec/integration/blogs_spec.rb +++ b/test-app/spec/integration/blogs_spec.rb @@ -50,6 +50,10 @@ describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do produces 'application/json' response '200', 'blog found' do + header 'ETag', type: :string + header 'Last-Modified', type: :string + header 'Cache-Control', type: :string + schema '$ref' => '#/definitions/blog' response_examples 'application/json' => { diff --git a/test-app/swagger/v1/swagger.json b/test-app/swagger/v1/swagger.json index e2e0311..acbcd1e 100644 --- a/test-app/swagger/v1/swagger.json +++ b/test-app/swagger/v1/swagger.json @@ -89,8 +89,26 @@ "responses": { "200": { "description": "blog found", + "headers": { + "ETag": { + "type": "string" + }, + "Last-Modified": { + "type": "string" + }, + "Cache-Control": { + "type": "string" + } + }, "schema": { "$ref": "#/definitions/blog" + }, + "examples": { + "application/json": { + "id": 1, + "title": "Hello world!", + "content": "Hello world and hello universe. Thank you all very much!!!" + } } }, "404": {