From c889b676f80565b4b65dfe45d53e93cb6ff9d885 Mon Sep 17 00:00:00 2001 From: Blake Erickson Date: Thu, 21 Jan 2021 18:23:23 -0700 Subject: [PATCH] DEV: Updates to api docs schema validation (#11801) - Read in schemas from actual json files instead of a ruby hash. This is helpful because we will be automatically generating .json schema files from json responses and don't want to manually write ruby hash schema files. - Create a helper method for rspec schema validation tests to dry up code --- .../json/tag_group_create_request.json | 12 +++ .../json/tag_group_create_response.json | 51 ++++++++++++ spec/requests/api/schemas/schema_loader.rb | 18 +++++ .../requests/api/schemas/tag_group_schemas.rb | 77 ------------------- spec/requests/api/shared/shared_examples.rb | 28 +++---- spec/requests/api/tags_spec.rb | 8 +- 6 files changed, 99 insertions(+), 95 deletions(-) create mode 100644 spec/requests/api/schemas/json/tag_group_create_request.json create mode 100644 spec/requests/api/schemas/json/tag_group_create_response.json create mode 100644 spec/requests/api/schemas/schema_loader.rb delete mode 100644 spec/requests/api/schemas/tag_group_schemas.rb diff --git a/spec/requests/api/schemas/json/tag_group_create_request.json b/spec/requests/api/schemas/json/tag_group_create_request.json new file mode 100644 index 00000000000..2e364e13d92 --- /dev/null +++ b/spec/requests/api/schemas/json/tag_group_create_request.json @@ -0,0 +1,12 @@ +{ + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] +} diff --git a/spec/requests/api/schemas/json/tag_group_create_response.json b/spec/requests/api/schemas/json/tag_group_create_response.json new file mode 100644 index 00000000000..7d04b1663f8 --- /dev/null +++ b/spec/requests/api/schemas/json/tag_group_create_response.json @@ -0,0 +1,51 @@ +{ + "type": "object", + "additionalProperties": false, + "properties": { + "tag_group": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag_names": { + "type": "array", + "items": [ + + ] + }, + "parent_tag_name": { + "type": "array", + "items": [ + + ] + }, + "one_per_topic": { + "type": "boolean" + }, + "permissions": { + "type": "object", + "properties": { + "everyone": { + "type": "integer" + } + } + } + }, + "required": [ + "id", + "name", + "tag_names", + "parent_tag_name", + "one_per_topic", + "permissions" + ] + } + }, + "required": [ + "tag_group" + ] +} diff --git a/spec/requests/api/schemas/schema_loader.rb b/spec/requests/api/schemas/schema_loader.rb new file mode 100644 index 00000000000..872e47d74a0 --- /dev/null +++ b/spec/requests/api/schemas/schema_loader.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'json' + +module SpecSchemas + + class SpecLoader + + def initialize(filename) + @filename = filename + end + + def load + JSON.parse(File.read(File.join(__dir__, "json", "#{@filename}.json"))) + end + end + +end diff --git a/spec/requests/api/schemas/tag_group_schemas.rb b/spec/requests/api/schemas/tag_group_schemas.rb deleted file mode 100644 index 86fd718de61..00000000000 --- a/spec/requests/api/schemas/tag_group_schemas.rb +++ /dev/null @@ -1,77 +0,0 @@ -# frozen_string_literal: true - -module SpecSchemas - - class TagGroupCreateRequest - def schemer - schema = { - 'type' => 'object', - 'additionalProperties' => false, - 'properties' => { - 'name' => { - 'type' => 'string', - } - }, - 'required' => ['name'] - } - end - end - - class TagGroupResponse - def schemer - schema = { - 'type' => 'object', - 'additionalProperties' => false, - 'properties' => { - 'tag_group' => { - 'type' => 'object', - 'properties' => { - 'id' => { - 'type' => 'integer', - }, - 'name' => { - 'type' => 'string', - }, - 'tag_names' => { - 'type' => 'array', - 'items' => { - 'type' => 'string' - } - }, - 'parent_tag_name' => { - 'type' => 'array', - 'items' => { - 'type' => 'string' - } - }, - 'one_per_topic' => { - 'type' => 'boolean', - }, - 'permissions' => { - 'type' => 'object', - 'properties' => { - 'everyone' => { - 'type' => 'integer', - 'example' => 1 - } - } - } - }, - 'required' => [ - 'id', - 'name', - 'tag_names', - 'parent_tag_name', - 'one_per_topic', - 'permissions' - ] - } - }, - 'required' => [ - 'tag_group' - ] - } - end - end - -end diff --git a/spec/requests/api/shared/shared_examples.rb b/spec/requests/api/shared/shared_examples.rb index a4361e27583..f6e732dce54 100644 --- a/spec/requests/api/shared/shared_examples.rb +++ b/spec/requests/api/shared/shared_examples.rb @@ -5,6 +5,16 @@ RSpec.shared_examples "a JSON endpoint" do |expected_response_status| submit_request(example.metadata) end + def expect_schema_valid(schemer, params) + valid = schemer.valid?(params) + unless valid # for debugging + puts + puts "RESPONSE: #{params}" + puts "VALIDATION DETAILS: #{schemer.validate(params).to_a[0]["details"]}" + end + expect(valid).to eq(true) + end + describe "response status" do it "returns expected response status" do expect(response.status).to eq(expected_response_status) @@ -13,13 +23,8 @@ RSpec.shared_examples "a JSON endpoint" do |expected_response_status| describe "request body" do it "matches the documented request schema" do |example| - schemer = JSONSchemer.schema(expected_request_schema.schemer) - valid = schemer.valid?(params) - unless valid # for debugging - puts params - puts schemer.validate(params).to_a[0]["details"] - end - expect(valid).to eq(true) + schemer = JSONSchemer.schema(expected_request_schema) + expect_schema_valid(schemer, params) end end @@ -28,14 +33,9 @@ RSpec.shared_examples "a JSON endpoint" do |expected_response_status| it "matches the documented response schema" do |example| schemer = JSONSchemer.schema( - expected_response_schema.schemer, + expected_response_schema, ) - valid = schemer.valid?(json_response) - unless valid # for debugging - puts json_response - puts schemer.validate(json_response).to_a[0]["details"] - end - expect(valid).to eq(true) + expect_schema_valid(schemer, json_response) end end end diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb index e599af201ae..b868135b202 100644 --- a/spec/requests/api/tags_spec.rb +++ b/spec/requests/api/tags_spec.rb @@ -60,17 +60,17 @@ describe 'tags' do post 'Creates a tag group' do tags 'Tags' consumes 'application/json' - expected_request_schema = SpecSchemas::TagGroupCreateRequest.new + expected_request_schema = SpecSchemas::SpecLoader.new('tag_group_create_request').load - parameter name: :params, in: :body, schema: expected_request_schema.schemer + parameter name: :params, in: :body, schema: expected_request_schema produces 'application/json' response '200', 'tag group created' do - expected_response_schema = SpecSchemas::TagGroupResponse.new + expected_response_schema = SpecSchemas::SpecLoader.new('tag_group_create_response').load let(:params) { { 'name' => 'todo' } } - schema(expected_response_schema.schemer) + schema(expected_response_schema) it_behaves_like "a JSON endpoint", 200 do let(:expected_response_schema) { expected_response_schema }