From 701eccb35cb02b899dbc71b554903109d534cb96 Mon Sep 17 00:00:00 2001 From: Subin T P Date: Sat, 26 Sep 2020 02:32:34 +0530 Subject: [PATCH] Feature: Knowledge Base APIs (#1002) - Introduce models & migrations for portals, categories, folders and articles - CRUD API for portals - CRUD API for categories Addresses: #714 Co-authored-by: Sojan --- .../api/v1/accounts/kbase/base_controller.rb | 9 ++ .../accounts/kbase/categories_controller.rb | 32 ++++++ .../v1/accounts/kbase/portals_controller.rb | 32 ++++++ app/models/account.rb | 3 + app/models/kbase.rb | 5 + app/models/kbase/article.rb | 40 +++++++ app/models/kbase/category.rb | 29 +++++ app/models/kbase/folder.rb | 20 ++++ app/models/kbase/portal.rb | 30 +++++ .../kbase/categories/_category.json.jbuilder | 5 + .../kbase/categories/create.json.jbuilder | 3 + .../kbase/categories/index.json.jbuilder | 3 + .../kbase/categories/update.json.jbuilder | 3 + .../kbase/portals/_portal.json.jbuilder | 8 ++ .../kbase/portals/create.json.jbuilder | 3 + .../kbase/portals/index.json.jbuilder | 3 + .../kbase/portals/update.json.jbuilder | 3 + config/routes.rb | 9 ++ .../20200704135408_create_kbase_portals.rb | 17 +++ .../20200704135810_create_kbase_categories.rb | 13 +++ .../20200704140029_create_kbase_folders.rb | 11 ++ .../20200704140509_create_kbase_articles.rb | 18 +++ db/schema.rb | 47 ++++++++ spec/factories/kbase/articles.rb | 14 +++ spec/factories/kbase/categories.rb | 12 ++ spec/factories/kbase/folders.rb | 8 ++ spec/factories/kbase/portals.rb | 7 ++ spec/models/account_spec.rb | 2 + spec/models/kbase/article_spec.rb | 17 +++ spec/models/kbase/category_spec.rb | 15 +++ spec/models/kbase/folder_spec.rb | 15 +++ spec/models/kbase/portal_spec.rb | 16 +++ .../accounts/kbase/categories_request_spec.rb | 106 ++++++++++++++++++ .../v1/accounts/kbase/portals_request_spec.rb | 101 +++++++++++++++++ 34 files changed, 659 insertions(+) create mode 100644 app/controllers/api/v1/accounts/kbase/base_controller.rb create mode 100644 app/controllers/api/v1/accounts/kbase/categories_controller.rb create mode 100644 app/controllers/api/v1/accounts/kbase/portals_controller.rb create mode 100644 app/models/kbase.rb create mode 100644 app/models/kbase/article.rb create mode 100644 app/models/kbase/category.rb create mode 100644 app/models/kbase/folder.rb create mode 100644 app/models/kbase/portal.rb create mode 100644 app/views/api/v1/accounts/kbase/categories/_category.json.jbuilder create mode 100644 app/views/api/v1/accounts/kbase/categories/create.json.jbuilder create mode 100644 app/views/api/v1/accounts/kbase/categories/index.json.jbuilder create mode 100644 app/views/api/v1/accounts/kbase/categories/update.json.jbuilder create mode 100644 app/views/api/v1/accounts/kbase/portals/_portal.json.jbuilder create mode 100644 app/views/api/v1/accounts/kbase/portals/create.json.jbuilder create mode 100644 app/views/api/v1/accounts/kbase/portals/index.json.jbuilder create mode 100644 app/views/api/v1/accounts/kbase/portals/update.json.jbuilder create mode 100644 db/migrate/20200704135408_create_kbase_portals.rb create mode 100644 db/migrate/20200704135810_create_kbase_categories.rb create mode 100644 db/migrate/20200704140029_create_kbase_folders.rb create mode 100644 db/migrate/20200704140509_create_kbase_articles.rb create mode 100644 spec/factories/kbase/articles.rb create mode 100644 spec/factories/kbase/categories.rb create mode 100644 spec/factories/kbase/folders.rb create mode 100644 spec/factories/kbase/portals.rb create mode 100644 spec/models/kbase/article_spec.rb create mode 100644 spec/models/kbase/category_spec.rb create mode 100644 spec/models/kbase/folder_spec.rb create mode 100644 spec/models/kbase/portal_spec.rb create mode 100644 spec/requests/api/v1/accounts/kbase/categories_request_spec.rb create mode 100644 spec/requests/api/v1/accounts/kbase/portals_request_spec.rb diff --git a/app/controllers/api/v1/accounts/kbase/base_controller.rb b/app/controllers/api/v1/accounts/kbase/base_controller.rb new file mode 100644 index 000000000..f50140883 --- /dev/null +++ b/app/controllers/api/v1/accounts/kbase/base_controller.rb @@ -0,0 +1,9 @@ +class Api::V1::Accounts::Kbase::BaseController < Api::V1::Accounts::BaseController + before_action :portal + + private + + def portal + @portal ||= Current.account.kbase_portals.find_by(id: params[:portal_id]) + end +end diff --git a/app/controllers/api/v1/accounts/kbase/categories_controller.rb b/app/controllers/api/v1/accounts/kbase/categories_controller.rb new file mode 100644 index 000000000..e114ee5e4 --- /dev/null +++ b/app/controllers/api/v1/accounts/kbase/categories_controller.rb @@ -0,0 +1,32 @@ +class Api::V1::Accounts::Kbase::CategoriesController < Api::V1::Accounts::Kbase::BaseController + before_action :fetch_category, except: [:index, :create] + + def index + @categories = @portal.categories + end + + def create + @category = @portal.categories.create!(category_params) + end + + def update + @category.update!(category_params) + end + + def destroy + @category.destroy + head :ok + end + + private + + def fetch_category + @category = @portal.categories.find(params[:id]) + end + + def category_params + params.require(:category).permit( + :name, :description, :position + ) + end +end diff --git a/app/controllers/api/v1/accounts/kbase/portals_controller.rb b/app/controllers/api/v1/accounts/kbase/portals_controller.rb new file mode 100644 index 000000000..e0788b587 --- /dev/null +++ b/app/controllers/api/v1/accounts/kbase/portals_controller.rb @@ -0,0 +1,32 @@ +class Api::V1::Accounts::Kbase::PortalsController < Api::V1::Accounts::Kbase::BaseController + before_action :fetch_portal, except: [:index, :create] + + def index + @portals = Current.account.kbase_portals + end + + def create + @portal = Current.account.kbase_portals.create!(portal_params) + end + + def update + @portal.update!(portal_params) + end + + def destroy + @portal.destroy + head :ok + end + + private + + def fetch_portal + @portal = current_account.kbase_portals.find(params[:id]) + end + + def portal_params + params.require(:portal).permit( + :account_id, :color, :custom_domain, :header_text, :homepage_link, :name, :page_title, :slug + ) + end +end diff --git a/app/models/account.rb b/app/models/account.rb index 3c4415e08..6df7e2e03 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -48,6 +48,9 @@ class Account < ApplicationRecord has_many :labels, dependent: :destroy has_many :notification_settings, dependent: :destroy has_many :hooks, dependent: :destroy, class_name: 'Integrations::Hook' + has_many :kbase_portals, dependent: :destroy, class_name: '::Kbase::Portal' + has_many :kbase_categories, dependent: :destroy, class_name: '::Kbase::Category' + has_many :kbase_articles, dependent: :destroy, class_name: '::Kbase::Article' has_flags ACCOUNT_SETTINGS_FLAGS.merge(column: 'settings_flags').merge(DEFAULT_QUERY_SETTING) enum locale: LANGUAGES_CONFIG.map { |key, val| [val[:iso_639_1_code], key] }.to_h diff --git a/app/models/kbase.rb b/app/models/kbase.rb new file mode 100644 index 000000000..8045af6c4 --- /dev/null +++ b/app/models/kbase.rb @@ -0,0 +1,5 @@ +module Kbase + def self.table_name_prefix + 'kbase_' + end +end diff --git a/app/models/kbase/article.rb b/app/models/kbase/article.rb new file mode 100644 index 000000000..0f14f6709 --- /dev/null +++ b/app/models/kbase/article.rb @@ -0,0 +1,40 @@ +# == Schema Information +# +# Table name: kbase_articles +# +# id :bigint not null, primary key +# content :text +# description :text +# status :integer +# title :string +# views :integer +# created_at :datetime not null +# updated_at :datetime not null +# account_id :integer not null +# author_id :integer +# category_id :integer +# folder_id :integer +# portal_id :integer not null +# +class Kbase::Article < ApplicationRecord + belongs_to :account + belongs_to :category + belongs_to :portal + belongs_to :folder + belongs_to :author, class_name: 'User' + + before_validation :ensure_account_id + validates :account_id, presence: true + validates :category_id, presence: true + validates :author_id, presence: true + validates :title, presence: true + validates :content, presence: true + + enum status: { draft: 0, published: 1 } + + private + + def ensure_account_id + self.account_id = portal&.account_id + end +end diff --git a/app/models/kbase/category.rb b/app/models/kbase/category.rb new file mode 100644 index 000000000..a32331598 --- /dev/null +++ b/app/models/kbase/category.rb @@ -0,0 +1,29 @@ +# == Schema Information +# +# Table name: kbase_categories +# +# id :bigint not null, primary key +# description :text +# name :string +# position :integer +# created_at :datetime not null +# updated_at :datetime not null +# account_id :integer not null +# portal_id :integer not null +# +class Kbase::Category < ApplicationRecord + belongs_to :account + belongs_to :portal + has_many :folders, dependent: :destroy + has_many :articles, dependent: :nullify + + before_validation :ensure_account_id + validates :account_id, presence: true + validates :name, presence: true + + private + + def ensure_account_id + self.account_id = portal&.account_id + end +end diff --git a/app/models/kbase/folder.rb b/app/models/kbase/folder.rb new file mode 100644 index 000000000..887522b5d --- /dev/null +++ b/app/models/kbase/folder.rb @@ -0,0 +1,20 @@ +# == Schema Information +# +# Table name: kbase_folders +# +# id :bigint not null, primary key +# name :string +# created_at :datetime not null +# updated_at :datetime not null +# account_id :integer not null +# category_id :integer not null +# +class Kbase::Folder < ApplicationRecord + belongs_to :account + belongs_to :category + has_many :articles, dependent: :nullify + + validates :account_id, presence: true + validates :category_id, presence: true + validates :name, presence: true +end diff --git a/app/models/kbase/portal.rb b/app/models/kbase/portal.rb new file mode 100644 index 000000000..5401361c4 --- /dev/null +++ b/app/models/kbase/portal.rb @@ -0,0 +1,30 @@ +# == Schema Information +# +# Table name: kbase_portals +# +# id :bigint not null, primary key +# account_id :integer not null +# color :string +# custom_domain :string +# header_text :text +# homepage_link :string +# name :string not null +# page_title :string +# slug :string not null +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_kbase_portals_on_slug (slug) UNIQUE +# +class Kbase::Portal < ApplicationRecord + belongs_to :account + has_many :categories, dependent: :destroy + has_many :folders, through: :categories + has_many :articles, dependent: :destroy + + validates :account_id, presence: true + validates :name, presence: true + validates :slug, presence: true +end diff --git a/app/views/api/v1/accounts/kbase/categories/_category.json.jbuilder b/app/views/api/v1/accounts/kbase/categories/_category.json.jbuilder new file mode 100644 index 000000000..358420231 --- /dev/null +++ b/app/views/api/v1/accounts/kbase/categories/_category.json.jbuilder @@ -0,0 +1,5 @@ +json.id category.id +json.name category.name +json.description category.description +json.position category.position +json.account_id category.account_id diff --git a/app/views/api/v1/accounts/kbase/categories/create.json.jbuilder b/app/views/api/v1/accounts/kbase/categories/create.json.jbuilder new file mode 100644 index 000000000..932cd6a18 --- /dev/null +++ b/app/views/api/v1/accounts/kbase/categories/create.json.jbuilder @@ -0,0 +1,3 @@ +json.payload do + json.partial! 'category', category: @category +end diff --git a/app/views/api/v1/accounts/kbase/categories/index.json.jbuilder b/app/views/api/v1/accounts/kbase/categories/index.json.jbuilder new file mode 100644 index 000000000..89fa05200 --- /dev/null +++ b/app/views/api/v1/accounts/kbase/categories/index.json.jbuilder @@ -0,0 +1,3 @@ +json.payload do + json.array! @categories, partial: 'category', as: :category +end diff --git a/app/views/api/v1/accounts/kbase/categories/update.json.jbuilder b/app/views/api/v1/accounts/kbase/categories/update.json.jbuilder new file mode 100644 index 000000000..932cd6a18 --- /dev/null +++ b/app/views/api/v1/accounts/kbase/categories/update.json.jbuilder @@ -0,0 +1,3 @@ +json.payload do + json.partial! 'category', category: @category +end diff --git a/app/views/api/v1/accounts/kbase/portals/_portal.json.jbuilder b/app/views/api/v1/accounts/kbase/portals/_portal.json.jbuilder new file mode 100644 index 000000000..92ddc41ba --- /dev/null +++ b/app/views/api/v1/accounts/kbase/portals/_portal.json.jbuilder @@ -0,0 +1,8 @@ +json.id portal.id +json.color portal.color +json.custom_domain portal.custom_domain +json.header_text portal.header_text +json.homepage_link portal.homepage_link +json.name portal.name +json.page_title portal.page_title +json.slug portal.slug diff --git a/app/views/api/v1/accounts/kbase/portals/create.json.jbuilder b/app/views/api/v1/accounts/kbase/portals/create.json.jbuilder new file mode 100644 index 000000000..c46e46321 --- /dev/null +++ b/app/views/api/v1/accounts/kbase/portals/create.json.jbuilder @@ -0,0 +1,3 @@ +json.payload do + json.partial! 'portal', portal: @portal +end diff --git a/app/views/api/v1/accounts/kbase/portals/index.json.jbuilder b/app/views/api/v1/accounts/kbase/portals/index.json.jbuilder new file mode 100644 index 000000000..3e4553382 --- /dev/null +++ b/app/views/api/v1/accounts/kbase/portals/index.json.jbuilder @@ -0,0 +1,3 @@ +json.payload do + json.array! @portals, partial: 'portal', as: :portal +end diff --git a/app/views/api/v1/accounts/kbase/portals/update.json.jbuilder b/app/views/api/v1/accounts/kbase/portals/update.json.jbuilder new file mode 100644 index 000000000..c46e46321 --- /dev/null +++ b/app/views/api/v1/accounts/kbase/portals/update.json.jbuilder @@ -0,0 +1,3 @@ +json.payload do + json.partial! 'portal', portal: @portal +end diff --git a/config/routes.rb b/config/routes.rb index 3cc52387e..8db4acc4a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -98,6 +98,15 @@ Rails.application.routes.draw do resources :apps, only: [:index, :show] resource :slack, only: [:create, :update, :destroy], controller: 'slack' end + + namespace :kbase do + resources :portals do + resources :categories do + resources :folders + end + resources :articles + end + end end end # end of account scoped api routes diff --git a/db/migrate/20200704135408_create_kbase_portals.rb b/db/migrate/20200704135408_create_kbase_portals.rb new file mode 100644 index 000000000..3d460456e --- /dev/null +++ b/db/migrate/20200704135408_create_kbase_portals.rb @@ -0,0 +1,17 @@ +class CreateKbasePortals < ActiveRecord::Migration[6.0] + def change + create_table :kbase_portals do |t| + t.integer :account_id, null: false + t.string :name, null: false + t.string :slug, null: false + t.string :custom_domain + t.string :color + t.string :homepage_link + t.string :page_title + t.text :header_text + + t.index :slug, unique: true + t.timestamps + end + end +end diff --git a/db/migrate/20200704135810_create_kbase_categories.rb b/db/migrate/20200704135810_create_kbase_categories.rb new file mode 100644 index 000000000..22f33bc21 --- /dev/null +++ b/db/migrate/20200704135810_create_kbase_categories.rb @@ -0,0 +1,13 @@ +class CreateKbaseCategories < ActiveRecord::Migration[6.0] + def change + create_table :kbase_categories do |t| + t.integer :account_id, null: false + t.integer :portal_id, null: false + t.string :name + t.text :description + t.integer :position + + t.timestamps + end + end +end diff --git a/db/migrate/20200704140029_create_kbase_folders.rb b/db/migrate/20200704140029_create_kbase_folders.rb new file mode 100644 index 000000000..d2f9f5e02 --- /dev/null +++ b/db/migrate/20200704140029_create_kbase_folders.rb @@ -0,0 +1,11 @@ +class CreateKbaseFolders < ActiveRecord::Migration[6.0] + def change + create_table :kbase_folders do |t| + t.integer :account_id, null: false + t.integer :category_id, null: false + t.string :name + + t.timestamps + end + end +end diff --git a/db/migrate/20200704140509_create_kbase_articles.rb b/db/migrate/20200704140509_create_kbase_articles.rb new file mode 100644 index 000000000..2d2e12a1f --- /dev/null +++ b/db/migrate/20200704140509_create_kbase_articles.rb @@ -0,0 +1,18 @@ +class CreateKbaseArticles < ActiveRecord::Migration[6.0] + def change + create_table :kbase_articles do |t| + t.integer :account_id, null: false + t.integer :portal_id, null: false + t.integer :category_id + t.integer :folder_id + t.integer :author_id + t.string :title + t.text :description + t.text :content + t.integer :status + t.integer :views + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index bd8c4e7d1..ae2cbf2e1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -300,6 +300,53 @@ ActiveRecord::Schema.define(version: 2020_09_07_094912) do t.datetime "updated_at", precision: 6, null: false end + create_table "kbase_articles", force: :cascade do |t| + t.integer "account_id", null: false + t.integer "portal_id", null: false + t.integer "category_id" + t.integer "folder_id" + t.integer "author_id" + t.string "title" + t.text "description" + t.text "content" + t.integer "status" + t.integer "views" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + + create_table "kbase_categories", force: :cascade do |t| + t.integer "account_id", null: false + t.integer "portal_id", null: false + t.string "name" + t.text "description" + t.integer "position" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + + create_table "kbase_folders", force: :cascade do |t| + t.integer "account_id", null: false + t.integer "category_id", null: false + t.string "name" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + + create_table "kbase_portals", force: :cascade do |t| + t.integer "account_id", null: false + t.string "name", null: false + t.string "slug", null: false + t.string "custom_domain" + t.string "color" + t.string "homepage_link" + t.string "page_title" + t.text "header_text" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["slug"], name: "index_kbase_portals_on_slug", unique: true + end + create_table "labels", force: :cascade do |t| t.string "title" t.text "description" diff --git a/spec/factories/kbase/articles.rb b/spec/factories/kbase/articles.rb new file mode 100644 index 000000000..9c19d7c9e --- /dev/null +++ b/spec/factories/kbase/articles.rb @@ -0,0 +1,14 @@ +FactoryBot.define do + factory :kbase_article, class: 'Kbase::Article' do + account_id { 1 } + category_id { 1 } + folder_id { 1 } + author_id { 1 } + title { 'MyString' } + content { 'MyText' } + status { 1 } + views { 1 } + seo_title { 'MyString' } + seo { '' } + end +end diff --git a/spec/factories/kbase/categories.rb b/spec/factories/kbase/categories.rb new file mode 100644 index 000000000..6b4c47ce4 --- /dev/null +++ b/spec/factories/kbase/categories.rb @@ -0,0 +1,12 @@ +FactoryBot.define do + factory :kbase_category, class: 'Kbase::Category' do + portal { kbase_portal } + name { 'MyString' } + description { 'MyText' } + position { 1 } + + after(:build) do |category| + category.account ||= category.portal.account + end + end +end diff --git a/spec/factories/kbase/folders.rb b/spec/factories/kbase/folders.rb new file mode 100644 index 000000000..00cbabedd --- /dev/null +++ b/spec/factories/kbase/folders.rb @@ -0,0 +1,8 @@ +FactoryBot.define do + factory :kbase_folder, class: 'Kbase::Folder' do + account_id { 1 } + name { 'MyString' } + description { 'MyText' } + category_id { 1 } + end +end diff --git a/spec/factories/kbase/portals.rb b/spec/factories/kbase/portals.rb new file mode 100644 index 000000000..fb37b8b56 --- /dev/null +++ b/spec/factories/kbase/portals.rb @@ -0,0 +1,7 @@ +FactoryBot.define do + factory :kbase_portal, class: 'Kbase::Portal' do + account + name { Faker::Book.name } + slug { SecureRandom.hex } + end +end diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index 59929ae8f..111b0888a 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -17,4 +17,6 @@ RSpec.describe Account do it { is_expected.to have_many(:webhooks).dependent(:destroy) } it { is_expected.to have_many(:notification_settings).dependent(:destroy) } it { is_expected.to have_many(:events) } + it { is_expected.to have_many(:kbase_portals).dependent(:destroy) } + it { is_expected.to have_many(:kbase_categories).dependent(:destroy) } end diff --git a/spec/models/kbase/article_spec.rb b/spec/models/kbase/article_spec.rb new file mode 100644 index 000000000..14729b1ed --- /dev/null +++ b/spec/models/kbase/article_spec.rb @@ -0,0 +1,17 @@ +require 'rails_helper' + +RSpec.describe Kbase::Article, type: :model do + context 'with validations' do + it { is_expected.to validate_presence_of(:account_id) } + it { is_expected.to validate_presence_of(:category_id) } + it { is_expected.to validate_presence_of(:author_id) } + it { is_expected.to validate_presence_of(:title) } + it { is_expected.to validate_presence_of(:content) } + end + + describe 'associations' do + it { is_expected.to belong_to(:account) } + it { is_expected.to belong_to(:category) } + it { is_expected.to belong_to(:author) } + end +end diff --git a/spec/models/kbase/category_spec.rb b/spec/models/kbase/category_spec.rb new file mode 100644 index 000000000..4b84cb352 --- /dev/null +++ b/spec/models/kbase/category_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +RSpec.describe Kbase::Category, type: :model do + context 'with validations' do + it { is_expected.to validate_presence_of(:account_id) } + it { is_expected.to validate_presence_of(:name) } + end + + describe 'associations' do + it { is_expected.to belong_to(:account) } + it { is_expected.to belong_to(:portal) } + it { is_expected.to have_many(:folders) } + it { is_expected.to have_many(:articles) } + end +end diff --git a/spec/models/kbase/folder_spec.rb b/spec/models/kbase/folder_spec.rb new file mode 100644 index 000000000..4af97a644 --- /dev/null +++ b/spec/models/kbase/folder_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +RSpec.describe Kbase::Folder, type: :model do + context 'with validations' do + it { is_expected.to validate_presence_of(:account_id) } + it { is_expected.to validate_presence_of(:category_id) } + it { is_expected.to validate_presence_of(:name) } + end + + describe 'associations' do + it { is_expected.to belong_to(:account) } + it { is_expected.to belong_to(:category) } + it { is_expected.to have_many(:articles) } + end +end diff --git a/spec/models/kbase/portal_spec.rb b/spec/models/kbase/portal_spec.rb new file mode 100644 index 000000000..67f79bf81 --- /dev/null +++ b/spec/models/kbase/portal_spec.rb @@ -0,0 +1,16 @@ +require 'rails_helper' + +RSpec.describe Kbase::Portal, type: :model do + context 'with validations' do + it { is_expected.to validate_presence_of(:account_id) } + it { is_expected.to validate_presence_of(:slug) } + it { is_expected.to validate_presence_of(:name) } + end + + describe 'associations' do + it { is_expected.to belong_to(:account) } + it { is_expected.to have_many(:categories) } + it { is_expected.to have_many(:folders) } + it { is_expected.to have_many(:articles) } + end +end diff --git a/spec/requests/api/v1/accounts/kbase/categories_request_spec.rb b/spec/requests/api/v1/accounts/kbase/categories_request_spec.rb new file mode 100644 index 000000000..2c8f54241 --- /dev/null +++ b/spec/requests/api/v1/accounts/kbase/categories_request_spec.rb @@ -0,0 +1,106 @@ +require 'rails_helper' + +RSpec.describe 'Api::V1::Accounts::Kbase::Categories', type: :request do + let(:account) { create(:account) } + let(:agent) { create(:user, account: account, role: :agent) } + let!(:portal) { create(:kbase_portal, name: 'test_portal', account_id: account.id) } + let!(:category) { create(:kbase_category, name: 'category', portal: portal, account_id: account.id) } + + describe 'POST /api/v1/accounts/{account.id}/kbase/portals/{portal.id}/categories' do + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + post "/api/v1/accounts/#{account.id}/kbase/portals/#{portal.id}/categories", params: {} + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + it 'creates category' do + category_params = { + category: { + name: 'test_category', + description: 'test_description', + position: 1 + } + } + post "/api/v1/accounts/#{account.id}/kbase/portals/#{portal.id}/categories", + params: category_params, + headers: agent.create_new_auth_token + expect(response).to have_http_status(:success) + json_response = JSON.parse(response.body) + expect(json_response['payload']['name']).to eql('test_category') + end + end + end + + describe 'PUT /api/v1/accounts/{account.id}/kbase/portals/{portal.id}/categories/{category.id}' do + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + put "/api/v1/accounts/#{account.id}/kbase/portals/#{portal.id}/categories/#{category.id}", params: {} + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + it 'updates category' do + category_params = { + category: { + name: 'test_category_2', + description: 'test_description', + position: 1 + } + } + + expect(category.name).not_to eql(category_params[:category][:name]) + + put "/api/v1/accounts/#{account.id}/kbase/portals/#{portal.id}/categories/#{category.id}", + params: category_params, + headers: agent.create_new_auth_token + expect(response).to have_http_status(:success) + json_response = JSON.parse(response.body) + expect(json_response['payload']['name']).to eql(category_params[:category][:name]) + end + end + end + + describe 'DELETE /api/v1/accounts/{account.id}/kbase/portals/{portal.id}/categories/{category.id}' do + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + delete "/api/v1/accounts/#{account.id}/kbase/portals/#{portal.id}/categories/#{category.id}", params: {} + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + it 'deletes category' do + delete "/api/v1/accounts/#{account.id}/kbase/portals/#{portal.id}/categories/#{category.id}", + headers: agent.create_new_auth_token + expect(response).to have_http_status(:success) + deleted_category = Kbase::Category.find_by(id: category.id) + expect(deleted_category).to be nil + end + end + end + + describe 'GET /api/v1/accounts/{account.id}/kbase/portals/{portal.id}/categories' do + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + get "/api/v1/accounts/#{account.id}/kbase/portals/#{portal.id}/categories" + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + it 'get all portals' do + category2 = create(:kbase_category, name: 'test_category_2', portal: portal) + expect(category2.id).not_to be nil + + get "/api/v1/accounts/#{account.id}/kbase/portals/#{portal.id}/categories", + headers: agent.create_new_auth_token + expect(response).to have_http_status(:success) + json_response = JSON.parse(response.body) + expect(json_response['payload'].count).to be 2 + end + end + end +end diff --git a/spec/requests/api/v1/accounts/kbase/portals_request_spec.rb b/spec/requests/api/v1/accounts/kbase/portals_request_spec.rb new file mode 100644 index 000000000..9adf9cba6 --- /dev/null +++ b/spec/requests/api/v1/accounts/kbase/portals_request_spec.rb @@ -0,0 +1,101 @@ +require 'rails_helper' + +RSpec.describe 'Api::V1::Accounts::Kbase::Portals', type: :request do + let(:account) { create(:account) } + let(:agent) { create(:user, account: account, role: :agent) } + let!(:portal) { create(:kbase_portal, name: 'test_portal', account_id: account.id) } + + describe 'POST /api/v1/accounts/{account.id}/kbase/portals' do + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + post "/api/v1/accounts/#{account.id}/kbase/portals", params: {} + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + it 'creates portal' do + portal_params = { + portal: { + name: 'test_portal', + slug: 'test_kbase' + } + } + post "/api/v1/accounts/#{account.id}/kbase/portals", + params: portal_params, + headers: agent.create_new_auth_token + expect(response).to have_http_status(:success) + json_response = JSON.parse(response.body) + expect(json_response['payload']['name']).to eql('test_portal') + end + end + end + + describe 'PUT /api/v1/accounts/{account.id}/kbase/portals/{portal.id}' do + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + put "/api/v1/accounts/#{account.id}/kbase/portals/#{portal.id}", params: {} + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + it 'updates portal' do + portal_params = { + portal: { + name: 'updated_test_portal' + } + } + + expect(portal.name).to eql('test_portal') + + put "/api/v1/accounts/#{account.id}/kbase/portals/#{portal.id}", + params: portal_params, + headers: agent.create_new_auth_token + expect(response).to have_http_status(:success) + json_response = JSON.parse(response.body) + expect(json_response['payload']['name']).to eql(portal_params[:portal][:name]) + end + end + end + + describe 'DELETE /api/v1/accounts/{account.id}/kbase/portals/{portal.id}' do + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + delete "/api/v1/accounts/#{account.id}/kbase/portals/#{portal.id}", params: {} + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + it 'deletes portal' do + delete "/api/v1/accounts/#{account.id}/kbase/portals/#{portal.id}", + headers: agent.create_new_auth_token + expect(response).to have_http_status(:success) + deleted_portal = Kbase::Portal.find_by(id: portal.id) + expect(deleted_portal).to be nil + end + end + end + + describe 'GET /api/v1/accounts/{account.id}/kbase/portals' do + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + get "/api/v1/accounts/#{account.id}/kbase/portals" + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + it 'get all portals' do + portal2 = create(:kbase_portal, name: 'test_portal_2', account_id: account.id) + expect(portal2.id).not_to be nil + get "/api/v1/accounts/#{account.id}/kbase/portals", + headers: agent.create_new_auth_token + expect(response).to have_http_status(:success) + json_response = JSON.parse(response.body) + expect(json_response['payload'].count).to be 2 + end + end + end +end