DEV: Add rswag to aid in api documention (#9546)

DEV: Add rswag to aid in api documention (#9546)

Adding in rswag will allow us to write spec files to document and test our api.

diff --git a/.gitignore b/.gitignore
index d988109..bc22f48 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 f389e68..0cb02e3 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 c440694..925f81b 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 1be34d4..20306d3 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 0000000..0c82cfa
--- /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 0000000..5f77373
--- /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

GitHub sha: a93ef292

This commit appears in #9546 which was approved by eviltrout. It was merged by blake.