diff --git a/.gitignore b/.gitignore index d9881098bde..bc22f48bbd5 100644 --- a/.gitignore +++ b/.gitignore @@ -133,5 +133,8 @@ node_modules # ignore auto-generated plugin js assets /app/assets/javascripts/plugins/* +# ignore generated api documentation files +openapi/* + # ember-cli generated -dist +dist \ No newline at end of file diff --git a/.rubocop.yml b/.rubocop.yml index f389e688ca4..0cb02e3e975 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -179,6 +179,8 @@ RSpec/DescribedClassModuleWrapping: RSpec/EmptyExampleGroup: Enabled: true + Exclude: + - 'spec/requests/api/*' RSpec/EmptyLineAfterExample: Enabled: false # TODO diff --git a/Gemfile b/Gemfile index c440694fffb..925f81b86a0 100644 --- a/Gemfile +++ b/Gemfile @@ -179,6 +179,8 @@ group :test, :development do gem "rubocop-discourse", require: false gem "rubocop-rspec", require: false gem 'parallel_tests' + + gem 'rswag-specs' end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 1be34d465f5..20306d35328 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -158,6 +158,8 @@ GEM railties (>= 4.2.0) thor (>= 0.14, < 2.0) json (2.3.0) + json-schema (2.8.1) + addressable (>= 2.4) jwt (2.2.1) kgio (2.11.3) libv8 (7.3.492.27.1) @@ -337,6 +339,10 @@ GEM rspec-mocks (~> 3.8) rspec-support (~> 3.8) rspec-support (3.9.2) + rswag-specs (2.3.1) + activesupport (>= 3.1, < 7.0) + json-schema (~> 2.2) + railties (>= 3.1, < 7.0) rtlit (0.0.5) rubocop (0.82.0) jaro_winkler (~> 1.5.1) @@ -524,6 +530,7 @@ DEPENDENCIES rspec rspec-html-matchers rspec-rails (= 4.0.0.beta2) + rswag-specs rtlit rubocop rubocop-discourse diff --git a/spec/requests/api/categories_spec.rb b/spec/requests/api/categories_spec.rb new file mode 100644 index 00000000000..0c82cfa3892 --- /dev/null +++ b/spec/requests/api/categories_spec.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true +require 'swagger_helper' + +describe 'categories' do + + let(:admin) { Fabricate(:admin) } + + before do + Jobs.run_immediately! + sign_in(admin) + end + + path '/categories.json' do + + post 'Creates a category' do + before do + Jobs.run_immediately! + sign_in(admin) + end + tags 'Category' + consumes 'application/json' + parameter name: :category, in: :body, schema: { + type: :object, + properties: { + name: { type: :string }, + color: { type: :string }, + text_color: { type: :string }, + }, + required: [ 'name', 'color', 'text_color' ] + } + + produces 'application/json' + response '200', 'category created' do + schema type: :object, properties: { + category: { + type: :object, + properties: { + id: { type: :integer }, + name: { type: :string }, + color: { type: :string }, + }, + required: ["id"] + } + }, required: ["category"] + + let(:category) { { name: 'todo', color: 'f94cb0', text_color: '412763' } } + run_test! + end + end + + get 'Retreives a list of categories' do + tags 'Category' + produces 'application/json' + + response '200', 'categories response' do + schema type: :object, properties: { + category_list: { + type: :object, + properties: { + can_create_category: { type: :boolean }, + can_create_topic: { type: :boolean }, + draft: { type: :string, nullable: true }, + draft_key: { type: :string }, + draft_sequence: { type: :integer }, + categories: { type: :array }, + }, required: ["categories"] + } + }, required: ["category_list"] + run_test! + end + end + end +end diff --git a/spec/swagger_helper.rb b/spec/swagger_helper.rb new file mode 100644 index 00000000000..5f7737384d8 --- /dev/null +++ b/spec/swagger_helper.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.configure do |config| + # Specify a root folder where Swagger JSON files are generated + # NOTE: If you're using the rswag-api to serve API descriptions, you'll need + # to ensure that it's configured to serve Swagger from the same folder + config.swagger_root = Rails.root.join('openapi').to_s + + # Define one or more Swagger documents and provide global metadata for each one + # When you run the 'rswag:specs:swaggerize' rake task, the complete Swagger will + # be generated at the provided relative path under swagger_root + # By default, the operations defined in spec files are added to the first + # document below. You can override this behavior by adding a swagger_doc tag to the + # the root example_group in your specs, e.g. describe '...', swagger_doc: 'v2/swagger.json' + config.swagger_docs = { + 'openapi.yaml' => { + openapi: '3.0.3', + info: { + title: 'Discourse API Documentation', + version: 'latest' + }, + paths: {}, + servers: [ + { + url: 'https://{defaultHost}', + variables: { + defaultHost: { + default: 'discourse.example.com' + } + } + } + ] + } + } + + # Specify the format of the output Swagger file when running 'rswag:specs:swaggerize'. + # The swagger_docs configuration option has the filename including format in + # the key, this may want to be changed to avoid putting yaml in json files. + # Defaults to json. Accepts ':json' and ':yaml'. + config.swagger_format = :yaml +end