diff --git a/app/controllers/api/v1/inventory_checklist_items_controller.rb b/app/controllers/api/v1/inventory_checklist_items_controller.rb new file mode 100644 index 000000000..999a69486 --- /dev/null +++ b/app/controllers/api/v1/inventory_checklist_items_controller.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +module Api + module V1 + class InventoryChecklistItemsController < BaseController + before_action :load_team + before_action :load_inventory + before_action :load_inventory_column + before_action :check_column_type + before_action :load_inventory_checklist_item, only: %i(show update destroy) + before_action :check_manage_permissions, only: %i(create update destroy) + + def index + checklist_items = @inventory_column.repository_checklist_items + .page(params.dig(:page, :number)) + .per(params.dig(:page, :size)) + render jsonapi: checklist_items, each_serializer: InventoryChecklistItemSerializer + end + + def create + checklist_item = @inventory_column.repository_checklist_items + .create!(inventory_checklist_item_params) + render jsonapi: checklist_item, + serializer: InventoryChecklistItemSerializer, + status: :created + end + + def show + render jsonapi: @inventory_checklist_item, + serializer: InventoryChecklistItemSerializer + end + + def update + @inventory_checklist_item.attributes = update_inventory_checklist_item_params + if @inventory_checklist_item.changed? && @inventory_checklist_item.save! + render jsonapi: @inventory_checklist_item, + serializer: InventoryChecklistItemSerializer + else + render body: nil, status: :no_content + end + end + + def destroy + @inventory_checklist_item.destroy! + render body: nil + end + + private + + def check_column_type + raise TypeError unless @inventory_column.data_type == 'RepositoryChecklistValue' + end + + def load_inventory_checklist_item + @inventory_checklist_item = @inventory_column.repository_checklist_items.find(params.require(:id)) + end + + def check_manage_permissions + unless can_manage_repository_column?(@inventory_column) + raise PermissionError.new(RepositoryChecklistItem, :manage) + end + end + + def inventory_checklist_item_params + raise TypeError unless params.require(:data).require(:type) == 'inventory_checklist_items' + + params.require(:data).require(:attributes) + params.permit(data: { attributes: %i(data) })[:data].merge( + created_by: @current_user, + last_modified_by: @current_user, + repository: @inventory + ) + end + + def update_inventory_checklist_item_params + raise IDMismatchError unless params.require(:data).require(:id).to_i == params[:id].to_i + + inventory_checklist_item_params[:attributes] + end + end + end +end diff --git a/app/models/repository_cell.rb b/app/models/repository_cell.rb index b834b42c6..cd6988725 100644 --- a/app/models/repository_cell.rb +++ b/app/models/repository_cell.rb @@ -13,94 +13,94 @@ class RepositoryCell < ApplicationRecord includes(:repository_cell) .where(repository_cells: { value_type: 'RepositoryTextValue' }) end), - optional: true, foreign_key: :value_id + optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_number_value, (lambda do includes(:repository_cell) .where(repository_cells: { value_type: 'RepositoryNumberValue' }) end), - optional: true, foreign_key: :value_id + optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_date_value, (lambda do includes(:repository_cell) .where(repository_cells: { value_type: 'RepositoryDateTimeValueBase' }) end), - optional: true, foreign_key: :value_id + optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_list_value, (lambda do includes(:repository_cell) .where(repository_cells: { value_type: 'RepositoryListValue' }) end), - optional: true, foreign_key: :value_id + optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_asset_value, (lambda do includes(:repository_cell) .where(repository_cells: { value_type: 'RepositoryAssetValue' }) end), - optional: true, foreign_key: :value_id + optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_status_value, (lambda do includes(:repository_cell) .where(repository_cells: { value_type: 'RepositoryStatusValue' }) end), - optional: true, foreign_key: :value_id + optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_checklist_value, (lambda do includes(:repository_cell) .where(repository_cells: { value_type: 'RepositoryChecklistValue' }) end), - optional: true, foreign_key: :value_id + optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_date_time_value_base, (lambda do includes(:repository_cell) .where(repository_cells: { value_type: 'RepositoryDateTimeValueBase' }) end), - optional: true, foreign_key: :value_id + optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_date_time_value, (lambda do includes(:repository_cell) .where(repository_cells: { value_type: 'RepositoryDateTimeValueBase' }) end), - optional: true, foreign_key: :value_id + optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_time_value, (lambda do includes(:repository_cell) .where(repository_cells: { value_type: 'RepositoryDateTimeValueBase' }) end), - optional: true, foreign_key: :value_id + optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_date_time_range_value_base, (lambda do includes(:repository_cell) .where(repository_cells: { value_type: 'RepositoryDateTimeRangeValueBase' }) end), - optional: true, foreign_key: :value_id + optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_date_time_range_value, (lambda do includes(:repository_cell) .where(repository_cells: { value_type: 'RepositoryDateTimeRangeValueBase' }) end), - optional: true, foreign_key: :value_id + optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_date_range_value, (lambda do includes(:repository_cell) .where(repository_cells: { value_type: 'RepositoryDateTimeRangeValueBase' }) end), - optional: true, foreign_key: :value_id + optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_time_range_value, (lambda do includes(:repository_cell) .where(repository_cells: { value_type: 'RepositoryDateTimeRangeValueBase' }) end), - optional: true, foreign_key: :value_id + optional: true, foreign_key: :value_id, inverse_of: :repository_cell validates :repository_column, inclusion: { in: (lambda do |cell| diff --git a/app/models/repository_checklist_value.rb b/app/models/repository_checklist_value.rb index 0641f1b0d..bfde69c25 100644 --- a/app/models/repository_checklist_value.rb +++ b/app/models/repository_checklist_value.rb @@ -30,11 +30,15 @@ class RepositoryChecklistValue < ApplicationRecord end def data_changed?(new_data) - JSON.parse(new_data) != repository_checklist_items.pluck(:id) + if new_data.is_a?(String) + JSON.parse(new_data) != repository_checklist_items.pluck(:id) + else + new_data != repository_checklist_items.pluck(:id) + end end def update_data!(new_data, user) - item_ids = JSON.parse(new_data) + item_ids = new_data.is_a?(String) ? JSON.parse(new_data) : new_data return destroy! if item_ids.blank? self.repository_checklist_items = repository_cell.repository_column @@ -45,11 +49,12 @@ class RepositoryChecklistValue < ApplicationRecord end def self.new_with_payload(payload, attributes) + item_ids = payload.is_a?(String) ? JSON.parse(payload) : payload value = new(attributes) value.repository_checklist_items = value.repository_cell .repository_column .repository_checklist_items - .where(id: JSON.parse(payload)) + .where(id: item_ids) value end diff --git a/app/models/repository_date_range_value.rb b/app/models/repository_date_range_value.rb index e42a12003..5a65d1cc2 100644 --- a/app/models/repository_date_range_value.rb +++ b/app/models/repository_date_range_value.rb @@ -4,7 +4,7 @@ class RepositoryDateRangeValue < RepositoryDateTimeRangeValueBase PRELOAD_INCLUDE = :repository_date_range_value def data_changed?(new_data) - data = JSON.parse(new_data).symbolize_keys + data = new_data.is_a?(String) ? JSON.parse(new_data).symbolize_keys : new_data st = Time.zone.parse(data[:start_time]) et = Time.zone.parse(data[:end_time]) st.to_date != start_time.to_date || et.to_date != end_time.to_date @@ -15,7 +15,7 @@ class RepositoryDateRangeValue < RepositoryDateTimeRangeValueBase end def self.new_with_payload(payload, attributes) - data = JSON.parse(payload).symbolize_keys + data = payload.is_a?(String) ? JSON.parse(payload).symbolize_keys : payload value = new(attributes) value.start_time = Time.zone.parse(data[:start_time]) diff --git a/app/models/repository_date_time_range_value.rb b/app/models/repository_date_time_range_value.rb index 99e4587db..a7201af79 100644 --- a/app/models/repository_date_time_range_value.rb +++ b/app/models/repository_date_time_range_value.rb @@ -4,7 +4,7 @@ class RepositoryDateTimeRangeValue < RepositoryDateTimeRangeValueBase PRELOAD_INCLUDE = :repository_date_time_range_value def data_changed?(new_data) - data = JSON.parse(new_data).symbolize_keys + data = new_data.is_a?(String) ? JSON.parse(new_data).symbolize_keys : new_data st = Time.zone.parse(data[:start_time]) et = Time.zone.parse(data[:end_time]) st.to_i != start_time.to_i || et.to_i != end_time.to_i @@ -15,7 +15,7 @@ class RepositoryDateTimeRangeValue < RepositoryDateTimeRangeValueBase end def self.new_with_payload(payload, attributes) - data = JSON.parse(payload).symbolize_keys + data = payload.is_a?(String) ? JSON.parse(payload).symbolize_keys : payload value = new(attributes) value.start_time = Time.zone.parse(data[:start_time]) diff --git a/app/models/repository_date_time_range_value_base.rb b/app/models/repository_date_time_range_value_base.rb index dbbae4c09..698c2e6a9 100644 --- a/app/models/repository_date_time_range_value_base.rb +++ b/app/models/repository_date_time_range_value_base.rb @@ -27,7 +27,7 @@ class RepositoryDateTimeRangeValueBase < ApplicationRecord end def update_data!(new_data, user) - data = JSON.parse(new_data).symbolize_keys + data = new_data.is_a?(String) ? JSON.parse(new_data).symbolize_keys : new_data self.start_time = Time.zone.parse(data[:start_time]) self.end_time = Time.zone.parse(data[:end_time]) self.last_modified_by = user diff --git a/app/models/repository_date_time_value_base.rb b/app/models/repository_date_time_value_base.rb index 9408b46d0..941cf1564 100644 --- a/app/models/repository_date_time_value_base.rb +++ b/app/models/repository_date_time_value_base.rb @@ -7,7 +7,7 @@ class RepositoryDateTimeValueBase < ApplicationRecord inverse_of: :created_repository_date_time_values belongs_to :last_modified_by, foreign_key: :last_modified_by_id, class_name: 'User', optional: true, inverse_of: :modified_repository_date_time_values - has_one :repository_cell, as: :value, dependent: :destroy, inverse_of: :repository_date_time_value + has_one :repository_cell, as: :value, dependent: :destroy accepts_nested_attributes_for :repository_cell validates :repository_cell, :data, :type, presence: true diff --git a/app/models/repository_text_value.rb b/app/models/repository_text_value.rb index 9d34d8553..154006bfc 100644 --- a/app/models/repository_text_value.rb +++ b/app/models/repository_text_value.rb @@ -1,9 +1,13 @@ # frozen_string_literal: true class RepositoryTextValue < ApplicationRecord - belongs_to :created_by, foreign_key: :created_by_id, class_name: 'User' - belongs_to :last_modified_by, foreign_key: :last_modified_by_id, class_name: 'User' - has_one :repository_cell, as: :value, dependent: :destroy, inverse_of: :value + belongs_to :created_by, foreign_key: :created_by_id, + class_name: 'User', + inverse_of: :created_repository_text_values + belongs_to :last_modified_by, foreign_key: :last_modified_by_id, + class_name: 'User', + inverse_of: :modified_repository_text_values + has_one :repository_cell, as: :value, dependent: :destroy accepts_nested_attributes_for :repository_cell validates :repository_cell, presence: true diff --git a/app/models/repository_time_range_value.rb b/app/models/repository_time_range_value.rb index 43a63e984..e062d538c 100644 --- a/app/models/repository_time_range_value.rb +++ b/app/models/repository_time_range_value.rb @@ -4,7 +4,7 @@ class RepositoryTimeRangeValue < RepositoryDateTimeRangeValueBase PRELOAD_INCLUDE = :repository_time_range_value def data_changed?(new_data) - data = JSON.parse(new_data).symbolize_keys + data = new_data.is_a?(String) ? JSON.parse(new_data).symbolize_keys : new_data st = Time.zone.parse(data[:start_time]) et = Time.zone.parse(data[:end_time]) @@ -16,7 +16,7 @@ class RepositoryTimeRangeValue < RepositoryDateTimeRangeValueBase end def self.new_with_payload(payload, attributes) - data = JSON.parse(payload).symbolize_keys + data = payload.is_a?(String) ? JSON.parse(payload).symbolize_keys : payload value = new(attributes) value.start_time = Time.zone.parse(data[:start_time]) diff --git a/app/models/user.rb b/app/models/user.rb index 261a31aea..9a8d5fcbf 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -19,15 +19,6 @@ class User < ApplicationRecord has_one_attached :avatar - # has_attached_file :avatar, - # styles: { - # medium: Constants::MEDIUM_PIC_FORMAT, - # thumb: Constants::THUMB_PIC_FORMAT, - # icon: Constants::ICON_PIC_FORMAT, - # icon_small: Constants::ICON_SMALL_PIC_FORMAT - # }, - # default_url: Constants::DEFAULT_AVATAR_URL - auto_strip_attributes :full_name, :initials, nullify: false validates :full_name, presence: true, @@ -39,10 +30,6 @@ class User < ApplicationRecord presence: true, length: { maximum: Constants::EMAIL_MAX_LENGTH } - # validates_attachment :avatar, - # :content_type => { :content_type => ["image/jpeg", "image/png"] }, - # size: { less_than: Constants::AVATAR_MAX_SIZE_MB.megabyte, - # message: I18n.t('client_api.user.avatar_too_big') } validate :time_zone_check store_accessor :settings, :time_zone, :notifications_settings @@ -274,6 +261,16 @@ class User < ApplicationRecord foreign_key: 'last_modified_by_id', inverse_of: :last_modified_by, dependent: :nullify + has_many :created_repository_text_values, + class_name: 'RepositoryTextValue', + foreign_key: 'created_by_id', + inverse_of: :created_by, + dependent: :nullify + has_many :modified_repository_text_values, + class_name: 'RepositoryTextValue', + foreign_key: 'last_modified_by_id', + inverse_of: :last_modified_by, + dependent: :nullify has_many :user_notifications, inverse_of: :user has_many :notifications, through: :user_notifications diff --git a/app/serializers/api/v1/inventory_cell_serializer.rb b/app/serializers/api/v1/inventory_cell_serializer.rb index ab6dac081..27c617581 100644 --- a/app/serializers/api/v1/inventory_cell_serializer.rb +++ b/app/serializers/api/v1/inventory_cell_serializer.rb @@ -10,14 +10,14 @@ module Api def value ActiveModelSerializers::SerializableResource.new( object.value, - class_name: object.value_type, + class_name: object.repository_column.data_type, namespace: Api::V1, adapter: :attribute ).as_json end def value_type - Extends::API_REPOSITORY_DATA_TYPE_MAPPINGS[object.value_type] + Extends::API_REPOSITORY_DATA_TYPE_MAPPINGS[object.repository_column.data_type] end end end diff --git a/app/serializers/api/v1/inventory_checklist_item_serializer.rb b/app/serializers/api/v1/inventory_checklist_item_serializer.rb new file mode 100644 index 000000000..6054b30ea --- /dev/null +++ b/app/serializers/api/v1/inventory_checklist_item_serializer.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Api + module V1 + class InventoryChecklistItemSerializer < ActiveModel::Serializer + type :inventory_checklist_items + attributes :id, :data + end + end +end diff --git a/app/serializers/api/v1/inventory_column_serializer.rb b/app/serializers/api/v1/inventory_column_serializer.rb index e2e3a6a52..fa4ae6f64 100644 --- a/app/serializers/api/v1/inventory_column_serializer.rb +++ b/app/serializers/api/v1/inventory_column_serializer.rb @@ -13,6 +13,14 @@ module Api object.data_type == 'RepositoryListValue' && !instance_options[:hide_list_items] end) + has_many :repository_checklist_items, + key: :inventory_checklist_items, + serializer: InventoryChecklistItemSerializer, + class_name: 'RepositoryChecklistItem', + if: (lambda do + object.data_type == 'RepositoryChecklistValue' && + !instance_options[:hide_list_items] + end) has_many :repository_status_items, key: :repository_status_items, serializer: InventoryStatusItemSerializer, diff --git a/app/serializers/api/v1/repository_checklist_value_serializer.rb b/app/serializers/api/v1/repository_checklist_value_serializer.rb new file mode 100644 index 000000000..c881a5288 --- /dev/null +++ b/app/serializers/api/v1/repository_checklist_value_serializer.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Api + module V1 + class RepositoryChecklistValueSerializer < ActiveModel::Serializer + attribute :inventory_checklist_item_ids do + object.repository_checklist_items.pluck(:id) + end + attribute :inventory_checklist_item_names do + object.repository_checklist_items.pluck(:data) + end + end + end +end diff --git a/app/serializers/api/v1/repository_date_range_value_serializer.rb b/app/serializers/api/v1/repository_date_range_value_serializer.rb new file mode 100644 index 000000000..0aee8064d --- /dev/null +++ b/app/serializers/api/v1/repository_date_range_value_serializer.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Api + module V1 + class RepositoryDateRangeValueSerializer < ActiveModel::Serializer + attribute :formatted, key: :date_range + end + end +end diff --git a/app/serializers/api/v1/repository_date_time_range_value_serializer.rb b/app/serializers/api/v1/repository_date_time_range_value_serializer.rb new file mode 100644 index 000000000..27549c5f7 --- /dev/null +++ b/app/serializers/api/v1/repository_date_time_range_value_serializer.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Api + module V1 + class RepositoryDateTimeRangeValueSerializer < ActiveModel::Serializer + attribute :formatted, key: :date_time_range + end + end +end diff --git a/app/serializers/api/v1/repository_date_time_value_serializer.rb b/app/serializers/api/v1/repository_date_time_value_serializer.rb new file mode 100644 index 000000000..f13f9df9b --- /dev/null +++ b/app/serializers/api/v1/repository_date_time_value_serializer.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Api + module V1 + class RepositoryDateTimeValueSerializer < ActiveModel::Serializer + attribute :formatted, key: :date_time + end + end +end diff --git a/app/serializers/api/v1/repository_date_value_serializer.rb b/app/serializers/api/v1/repository_date_value_serializer.rb new file mode 100644 index 000000000..33276f51a --- /dev/null +++ b/app/serializers/api/v1/repository_date_value_serializer.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Api + module V1 + class RepositoryDateValueSerializer < ActiveModel::Serializer + attribute :formatted, key: :date + end + end +end diff --git a/app/serializers/api/v1/repository_status_value_serializer.rb b/app/serializers/api/v1/repository_status_value_serializer.rb new file mode 100644 index 000000000..21b2ca2f7 --- /dev/null +++ b/app/serializers/api/v1/repository_status_value_serializer.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Api + module V1 + class RepositoryStatusValueSerializer < ActiveModel::Serializer + attribute :repository_status_item_id, key: :inventory_status_item_id + attribute :inventory_status_item_icon do + object.repository_status_item.icon + end + attribute :inventory_status_item_name do + object.repository_status_item.status + end + end + end +end diff --git a/app/serializers/api/v1/repository_time_range_value_serializer.rb b/app/serializers/api/v1/repository_time_range_value_serializer.rb new file mode 100644 index 000000000..f8155dd43 --- /dev/null +++ b/app/serializers/api/v1/repository_time_range_value_serializer.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Api + module V1 + class RepositoryTimeRangeValueSerializer < ActiveModel::Serializer + attribute :formatted, key: :time_range + end + end +end diff --git a/app/serializers/api/v1/repository_time_value_serializer.rb b/app/serializers/api/v1/repository_time_value_serializer.rb new file mode 100644 index 000000000..b61e78c7b --- /dev/null +++ b/app/serializers/api/v1/repository_time_value_serializer.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Api + module V1 + class RepositoryTimeValueSerializer < ActiveModel::Serializer + attribute :formatted, key: :time + end + end +end diff --git a/config/initializers/extends.rb b/config/initializers/extends.rb index 8d7f4b902..5b1668aa0 100644 --- a/config/initializers/extends.rb +++ b/config/initializers/extends.rb @@ -94,7 +94,13 @@ class Extends API_REPOSITORY_DATA_TYPE_MAPPINGS = { 'RepositoryTextValue' => 'text', 'RepositoryDateValue' => 'date', + 'RepositoryTimeValue' => 'time', + 'RepositoryDateTimeValue' => 'date_time', + 'RepositoryDateRangeValue' => 'date_range', + 'RepositoryTimeRangeValue' => 'time_range', + 'RepositoryDateTimeRangeValue' => 'date_time_range', 'RepositoryListValue' => 'list', + 'RepositoryChecklistValue' => 'checklist', 'RepositoryAssetValue' => 'file', 'RepositoryStatusValue' => 'status' } diff --git a/config/routes.rb b/config/routes.rb index 94a8503c1..92e41d41c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -665,6 +665,10 @@ Rails.application.routes.draw do only: %i(index create show update destroy), path: 'list_items', as: :list_items + resources :inventory_checklist_items, + only: %i(index create show update destroy), + path: 'checklist_items', + as: :checklist_items resources :inventory_status_items, only: %i(index create show update destroy), path: 'status_items', diff --git a/spec/factories/repositor_date_time_range_values.rb b/spec/factories/repositor_date_time_range_values.rb index c1e132252..d24d77b1c 100644 --- a/spec/factories/repositor_date_time_range_values.rb +++ b/spec/factories/repositor_date_time_range_values.rb @@ -13,6 +13,7 @@ FactoryBot.define do class: 'RepositoryDateTimeRangeValue' do after(:build) do |value| value.repository_cell ||= build(:repository_cell, :date_time_range_value, repository_date_time_range_value: value) + value.repository_cell.value = value end end @@ -21,6 +22,7 @@ FactoryBot.define do class: 'RepositoryTimeRangeValue' do after(:build) do |value| value.repository_cell ||= build(:repository_cell, :time_range_value, repository_time_range_value: value) + value.repository_cell.value = value end end @@ -29,6 +31,7 @@ FactoryBot.define do class: 'RepositoryDateRangeValue' do after(:build) do |value| value.repository_cell ||= build(:repository_cell, :date_range_value, repository_date_range_value: value) + value.repository_cell.value = value end end end diff --git a/spec/factories/repository_date_time_values.rb b/spec/factories/repository_date_time_values.rb index b3cd82f42..4f997e61a 100644 --- a/spec/factories/repository_date_time_values.rb +++ b/spec/factories/repository_date_time_values.rb @@ -10,18 +10,21 @@ FactoryBot.define do factory :repository_date_time_value, parent: :repository_date_time_value_base, class: 'RepositoryDateTimeValue' do after(:build) do |value| value.repository_cell ||= build(:repository_cell, :date_time_value, repository_date_time_value: value) + value.repository_cell.value = value end end factory :repository_time_value, parent: :repository_date_time_value_base, class: 'RepositoryTimeValue' do after(:build) do |value| value.repository_cell ||= build(:repository_cell, :time_value, repository_time_value: value) + value.repository_cell.value = value end end factory :repository_date_value, parent: :repository_date_time_value_base, class: 'RepositoryDateValue' do after(:build) do |value| value.repository_cell ||= build(:repository_cell, :date_value, repository_date_value: value) + value.repository_cell.value = value end end end diff --git a/spec/factories/repository_status_items.rb b/spec/factories/repository_status_items.rb index 11e357853..76c62f7a4 100644 --- a/spec/factories/repository_status_items.rb +++ b/spec/factories/repository_status_items.rb @@ -2,7 +2,7 @@ FactoryBot.define do factory :repository_status_item do - sequence(:icon) { |n| "icon-#{n}" } + sequence(:icon) { '😀' } sequence(:status) { |n| "status-#{n}" } repository repository_column diff --git a/spec/factories/repository_text_values.rb b/spec/factories/repository_text_values.rb index bb0bb0627..b959f328c 100644 --- a/spec/factories/repository_text_values.rb +++ b/spec/factories/repository_text_values.rb @@ -9,6 +9,7 @@ FactoryBot.define do repository_text_value.repository_cell ||= build(:repository_cell, :text_value, repository_text_value: repository_text_value) + repository_text_value.repository_cell.value = repository_text_value end end end diff --git a/spec/models/repository_text_value_spec.rb b/spec/models/repository_text_value_spec.rb index 33dadbbdb..9e4ba3680 100644 --- a/spec/models/repository_text_value_spec.rb +++ b/spec/models/repository_text_value_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe RepositoryTextValue, type: :model do - let(:repository_text_value) { build :repository_text_value } + let(:repository_text_value) { create :repository_text_value } it 'is valid' do expect(repository_text_value).to be_valid diff --git a/spec/requests/api/v1/inventory_cells_controller_spec.rb b/spec/requests/api/v1/inventory_cells_controller_spec.rb index 9ad248b68..444642cbe 100644 --- a/spec/requests/api/v1/inventory_cells_controller_spec.rb +++ b/spec/requests/api/v1/inventory_cells_controller_spec.rb @@ -28,22 +28,65 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do second_list_item = create(:repository_list_item, repository: @valid_inventory, repository_column: @list_column, data: Faker::Name.unique.name) + @status_column = create(:repository_column, repository: @valid_inventory, data_type: :RepositoryStatusValue) + status_item = create(:repository_status_item, + repository: @valid_inventory, + repository_column: @status_column) + second_status_item = create(:repository_status_item, + repository: @valid_inventory, + repository_column: @status_column) + @checklist_column = create(:repository_column, name: Faker::Name.unique.name, + repository: @valid_inventory, data_type: :RepositoryChecklistValue) + checklist_items = + create_list(:repository_checklist_item, 3, repository: @valid_inventory, repository_column: @checklist_column) + checklist_item = + create(:repository_checklist_item, repository: @valid_inventory, + repository_column: @checklist_column, data: Faker::Name.unique.name) @file_column = create(:repository_column, name: Faker::Name.unique.name, repository: @valid_inventory, data_type: :RepositoryAssetValue) asset = create(:asset) + @date_column = create(:repository_column, repository: @valid_inventory, data_type: :RepositoryDateValue) + @time_column = create(:repository_column, repository: @valid_inventory, data_type: :RepositoryTimeValue) + @date_time_column = create(:repository_column, repository: @valid_inventory, data_type: :RepositoryDateTimeValue) + @date_range_column = create(:repository_column, repository: @valid_inventory, data_type: :RepositoryDateRangeValue) + @time_range_column = create(:repository_column, repository: @valid_inventory, data_type: :RepositoryTimeRangeValue) + @date_time_range_column = create(:repository_column, + repository: @valid_inventory, data_type: :RepositoryDateTimeRangeValue) @valid_item = create(:repository_row, repository: @valid_inventory) create(:repository_text_value, data: Faker::Name.name, - repository_cell_attributes: - { repository_row: @valid_item, repository_column: @text_column }) + repository_cell_attributes: { repository_row: @valid_item, repository_column: @text_column }) create(:repository_list_value, repository_list_item: list_item, - repository_cell_attributes: - { repository_row: @valid_item, repository_column: @list_column }) + repository_cell_attributes: { repository_row: @valid_item, repository_column: @list_column }) + create(:repository_status_value, repository_status_item: status_item, + repository_cell_attributes: { repository_row: @valid_item, repository_column: @status_column }) + create(:repository_checklist_value, repository_checklist_items: checklist_items, + repository_cell_attributes: { repository_row: @valid_item, repository_column: @checklist_column }) create(:repository_asset_value, asset: asset, - repository_cell_attributes: - { repository_row: @valid_item, repository_column: @file_column }) + repository_cell_attributes: { repository_row: @valid_item, repository_column: @file_column }) + create(:repository_date_value, + data: Time.zone.today, + repository_cell_attributes: { repository_row: @valid_item, repository_column: @date_column }) + create(:repository_time_value, + data: Time.zone.now, + repository_cell_attributes: { repository_row: @valid_item, repository_column: @time_column }) + create(:repository_date_time_value, + data: DateTime.now, + repository_cell_attributes: { repository_row: @valid_item, repository_column: @date_time_column }) + create(:repository_date_range_value, + start_time: Time.zone.today, + end_time: Time.zone.today + 1.day, + repository_cell_attributes: { repository_row: @valid_item, repository_column: @date_range_column }) + create(:repository_time_range_value, + start_time: Time.zone.now, + end_time: Time.zone.now + 1.hour, + repository_cell_attributes: { repository_row: @valid_item, repository_column: @time_range_column }) + create(:repository_date_time_range_value, + start_time: DateTime.now, + end_time: DateTime.now + 1.day, + repository_cell_attributes: { repository_row: @valid_item, repository_column: @date_time_range_column }) @valid_headers = { 'Authorization': 'Bearer ' + generate_token(@user.id), @@ -67,6 +110,24 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do } } } + @valid_status_body = { + data: { + type: 'inventory_cells', + attributes: { + column_id: @status_column.id, + value: status_item.id + } + } + } + @valid_checklist_body = { + data: { + type: 'inventory_cells', + attributes: { + column_id: @checklist_column.id, + value: checklist_items.pluck(:id) + } + } + } @valid_file_body = { data: { type: 'inventory_cells', @@ -79,10 +140,72 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do } } } + @valid_date_body = { + data: { + type: 'inventory_cells', + attributes: { + column_id: @date_column.id, + value: Time.zone.today + } + } + } + @valid_time_body = { + data: { + type: 'inventory_cells', + attributes: { + column_id: @time_column.id, + value: Time.zone.now + } + } + } + @valid_date_time_body = { + data: { + type: 'inventory_cells', + attributes: { + column_id: @date_time_column.id, + value: DateTime.now + } + } + } + @valid_date_range_body = { + data: { + type: 'inventory_cells', + attributes: { + column_id: @date_range_column.id, + value: { + start_time: Time.zone.today, + end_time: Time.zone.today + 1.day + } + } + } + } + @valid_time_range_body = { + data: { + type: 'inventory_cells', + attributes: { + column_id: @time_range_column.id, + value: { + start_time: Time.zone.now, + end_time: Time.zone.now + 1.hour + } + } + } + } + @valid_date_time_range_body = { + data: { + type: 'inventory_cells', + attributes: { + column_id: @date_time_range_column.id, + value: { + start_time: DateTime.now, + end_time: DateTime.now + 1.day + } + } + } + } @update_text_body = { data: { - id: @valid_item.repository_cells - .where(repository_column: @text_column).first.id, + id: @valid_item.repository_cells.where(repository_column: @text_column).first.id, type: 'inventory_cells', attributes: { column_id: @text_column.id, @@ -92,8 +215,7 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do } @update_list_body = { data: { - id: @valid_item.repository_cells - .where(repository_column: @list_column).first.id, + id: @valid_item.repository_cells.where(repository_column: @list_column).first.id, type: 'inventory_cells', attributes: { column_id: @list_column.id, @@ -101,10 +223,29 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do } } } + @update_status_body = { + data: { + id: @valid_item.repository_cells.where(repository_column: @status_column).first.id, + type: 'inventory_cells', + attributes: { + column_id: @status_column.id, + value: second_status_item.id + } + } + } + @update_checklist_body = { + data: { + id: @valid_item.repository_cells.where(repository_column: @checklist_column).first.id, + type: 'inventory_cells', + attributes: { + column_id: @list_column.id, + value: [checklist_item.id] + } + } + } @update_file_body = { data: { - id: @valid_item.repository_cells - .where(repository_column: @file_column).first.id, + id: @valid_item.repository_cells.where(repository_column: @file_column).first.id, type: 'inventory_cells', attributes: { column_id: @file_column.id, @@ -115,6 +256,75 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do } } } + @update_date_body = { + data: { + id: @valid_item.repository_cells.where(repository_column: @date_column).first.id, + type: 'inventory_cells', + attributes: { + column_id: @date_column.id, + value: Time.zone.today + 2.days + } + } + } + @update_time_body = { + data: { + id: @valid_item.repository_cells.where(repository_column: @time_column).first.id, + type: 'inventory_cells', + attributes: { + column_id: @time_column.id, + value: Time.zone.now + 2.hours + } + } + } + @update_date_time_body = { + data: { + id: @valid_item.repository_cells.where(repository_column: @date_time_column).first.id, + type: 'inventory_cells', + attributes: { + column_id: @date_time_column.id, + value: DateTime.now + 2.hours + } + } + } + @update_date_range_body = { + data: { + id: @valid_item.repository_cells.where(repository_column: @date_range_column).first.id, + type: 'inventory_cells', + attributes: { + column_id: @date_range_column.id, + value: { + start_time: Time.zone.today, + end_time: Time.zone.today + 2.days + } + } + } + } + @update_time_range_body = { + data: { + id: @valid_item.repository_cells.where(repository_column: @time_range_column).first.id, + type: 'inventory_cells', + attributes: { + column_id: @time_range_column.id, + value: { + start_time: Time.zone.now, + end_time: Time.zone.now + 2.hours + } + } + } + } + @update_date_time_range_body = { + data: { + id: @valid_item.repository_cells.where(repository_column: @date_time_range_column).first.id, + type: 'inventory_cells', + attributes: { + column_id: @date_time_range_column.id, + value: { + start_time: DateTime.now, + end_time: DateTime.now + 2.hours + } + } + } + } end describe 'GET inventory_cells, #index' do @@ -123,7 +333,8 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do get api_v1_team_inventory_item_cells_path( team_id: @team.id, inventory_id: @valid_inventory.id, - item_id: @valid_item.id + item_id: @valid_item.id, + page: { size: 100 } ), headers: @valid_headers expect { hash_body = json }.not_to raise_exception expect(hash_body[:data]).to match( @@ -241,6 +452,42 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do ) end + it 'Response with correct inventory cell, status cell' do + hash_body = nil + empty_item = create(:repository_row, repository: @valid_inventory) + post api_v1_team_inventory_item_cells_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: empty_item.id + ), params: @valid_status_body.to_json, headers: @valid_headers + expect(response).to have_http_status 201 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(RepositoryCell.last, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + + it 'Response with correct inventory cell, checklist cell' do + hash_body = nil + empty_item = create(:repository_row, repository: @valid_inventory) + post api_v1_team_inventory_item_cells_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: empty_item.id + ), params: @valid_checklist_body.to_json, headers: @valid_headers + expect(response).to have_http_status 201 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(RepositoryCell.last, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + it 'Response with correct inventory cell, file cell' do hash_body = nil empty_item = create(:repository_row, repository: @valid_inventory) @@ -259,6 +506,114 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do ) end + it 'Response with correct inventory cell, date cell' do + hash_body = nil + empty_item = create(:repository_row, repository: @valid_inventory) + post api_v1_team_inventory_item_cells_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: empty_item.id + ), params: @valid_date_body.to_json, headers: @valid_headers + expect(response).to have_http_status 201 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(RepositoryCell.last, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + + it 'Response with correct inventory cell, time cell' do + hash_body = nil + empty_item = create(:repository_row, repository: @valid_inventory) + post api_v1_team_inventory_item_cells_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: empty_item.id + ), params: @valid_time_body.to_json, headers: @valid_headers + expect(response).to have_http_status 201 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(RepositoryCell.last, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + + it 'Response with correct inventory cell, date_time cell' do + hash_body = nil + empty_item = create(:repository_row, repository: @valid_inventory) + post api_v1_team_inventory_item_cells_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: empty_item.id + ), params: @valid_date_time_body.to_json, headers: @valid_headers + expect(response).to have_http_status 201 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(RepositoryCell.last, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + + it 'Response with correct inventory cell, date_range cell' do + hash_body = nil + empty_item = create(:repository_row, repository: @valid_inventory) + post api_v1_team_inventory_item_cells_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: empty_item.id + ), params: @valid_date_range_body.to_json, headers: @valid_headers + expect(response).to have_http_status 201 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(RepositoryCell.last, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + + it 'Response with correct inventory cell, time_range cell' do + hash_body = nil + empty_item = create(:repository_row, repository: @valid_inventory) + post api_v1_team_inventory_item_cells_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: empty_item.id + ), params: @valid_time_range_body.to_json, headers: @valid_headers + expect(response).to have_http_status 201 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(RepositoryCell.last, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + + it 'Response with correct inventory cell, date_time_range cell' do + hash_body = nil + empty_item = create(:repository_row, repository: @valid_inventory) + post api_v1_team_inventory_item_cells_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: empty_item.id + ), params: @valid_date_time_range_body.to_json, headers: @valid_headers + expect(response).to have_http_status 201 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(RepositoryCell.last, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + it 'When invalid request, payload mismatches column type' do hash_body = nil invalid_file_body = @valid_file_body.dup @@ -318,15 +673,13 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do team_id: @team.id, inventory_id: @valid_inventory.id, item_id: @valid_item.id, - id: @valid_item.repository_cells - .where(repository_column: @text_column).first.id + id: @valid_item.repository_cells.where(repository_column: @text_column).first.id ), params: @update_text_body.to_json, headers: @valid_headers expect(response).to have_http_status 200 expect { hash_body = json }.not_to raise_exception expect(hash_body[:data]).to match( ActiveModelSerializers::SerializableResource - .new(@valid_item.repository_cells - .where(repository_column: @text_column).first, + .new(@valid_item.repository_cells.where(repository_column: @text_column).first, serializer: Api::V1::InventoryCellSerializer) .as_json[:data] ) @@ -338,15 +691,50 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do team_id: @team.id, inventory_id: @valid_inventory.id, item_id: @valid_item.id, - id: @valid_item.repository_cells - .where(repository_column: @list_column).first.id + id: @valid_item.repository_cells.where(repository_column: @list_column).first.id ), params: @update_list_body.to_json, headers: @valid_headers expect(response).to have_http_status 200 expect { hash_body = json }.not_to raise_exception expect(hash_body[:data]).to match( ActiveModelSerializers::SerializableResource - .new(@valid_item.repository_cells - .where(repository_column: @list_column).first, + .new(@valid_item.repository_cells.where(repository_column: @list_column).first, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + + it 'Response with correct inventory cell, status cell' do + hash_body = nil + patch api_v1_team_inventory_item_cell_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: @valid_item.id, + id: @valid_item.repository_cells.where(repository_column: @status_column).first.id + ), params: @update_status_body.to_json, headers: @valid_headers + expect(response).to have_http_status 200 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@valid_item.repository_cells.where(repository_column: @status_column).first, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + + it 'Response with correct inventory cell, checklist cell' do + hash_body = nil + patch api_v1_team_inventory_item_cell_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: @valid_item.id, + id: @valid_item.repository_cells + .where(repository_column: @checklist_column).first.id + ), params: @update_checklist_body.to_json, headers: @valid_headers + expect(response).to have_http_status 200 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@valid_item.repository_cells.where(repository_column: @checklist_column).first, serializer: Api::V1::InventoryCellSerializer) .as_json[:data] ) @@ -358,15 +746,121 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do team_id: @team.id, inventory_id: @valid_inventory.id, item_id: @valid_item.id, - id: @valid_item.repository_cells - .where(repository_column: @file_column).first.id + id: @valid_item.repository_cells.where(repository_column: @file_column).first.id ), params: @update_file_body.to_json, headers: @valid_headers expect(response).to have_http_status 200 expect { hash_body = json }.not_to raise_exception expect(hash_body[:data]).to match( ActiveModelSerializers::SerializableResource - .new(@valid_item.repository_cells - .where(repository_column: @file_column).first, + .new(@valid_item.repository_cells.where(repository_column: @file_column).first, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + + it 'Response with correct inventory cell, date cell' do + hash_body = nil + patch api_v1_team_inventory_item_cell_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: @valid_item.id, + id: @valid_item.repository_cells.where(repository_column: @date_column).first.id + ), params: @update_date_body.to_json, headers: @valid_headers + expect(response).to have_http_status 200 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@valid_item.repository_cells.where(repository_column: @date_column).first, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + + it 'Response with correct inventory cell, time cell' do + hash_body = nil + patch api_v1_team_inventory_item_cell_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: @valid_item.id, + id: @valid_item.repository_cells.where(repository_column: @time_column).first.id + ), params: @update_time_body.to_json, headers: @valid_headers + expect(response).to have_http_status 200 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@valid_item.repository_cells.where(repository_column: @time_column).first, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + + it 'Response with correct inventory cell, date_time cell' do + hash_body = nil + patch api_v1_team_inventory_item_cell_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: @valid_item.id, + id: @valid_item.repository_cells.where(repository_column: @date_time_column).first.id + ), params: @update_date_time_body.to_json, headers: @valid_headers + expect(response).to have_http_status 200 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@valid_item.repository_cells.where(repository_column: @date_time_column).first, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + + it 'Response with correct inventory cell, date_range cell' do + hash_body = nil + patch api_v1_team_inventory_item_cell_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: @valid_item.id, + id: @valid_item.repository_cells.where(repository_column: @date_range_column).first.id + ), params: @update_date_range_body.to_json, headers: @valid_headers + expect(response).to have_http_status 200 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@valid_item.repository_cells.where(repository_column: @date_range_column).first, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + + it 'Response with correct inventory cell, time_range cell' do + hash_body = nil + patch api_v1_team_inventory_item_cell_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: @valid_item.id, + id: @valid_item.repository_cells.where(repository_column: @time_range_column).first.id + ), params: @update_time_range_body.to_json, headers: @valid_headers + expect(response).to have_http_status 200 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@valid_item.repository_cells.where(repository_column: @time_range_column).first, + serializer: Api::V1::InventoryCellSerializer) + .as_json[:data] + ) + end + + it 'Response with correct inventory cell, date_time_range cell' do + hash_body = nil + patch api_v1_team_inventory_item_cell_path( + team_id: @team.id, + inventory_id: @valid_inventory.id, + item_id: @valid_item.id, + id: @valid_item.repository_cells.where(repository_column: @date_time_range_column).first.id + ), params: @update_date_time_range_body.to_json, headers: @valid_headers + expect(response).to have_http_status 200 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@valid_item.repository_cells.where(repository_column: @date_time_range_column).first, serializer: Api::V1::InventoryCellSerializer) .as_json[:data] ) @@ -380,8 +874,7 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do team_id: @team.id, inventory_id: @valid_inventory.id, item_id: @valid_item.id, - id: @valid_item.repository_cells - .where(repository_column: @file_column).first.id + id: @valid_item.repository_cells.where(repository_column: @file_column).first.id ), params: invalid_file_body.to_json, headers: @valid_headers expect(response).to have_http_status 400 expect { hash_body = json }.not_to raise_exception diff --git a/spec/requests/api/v1/inventory_checklist_items_controller_spec.rb b/spec/requests/api/v1/inventory_checklist_items_controller_spec.rb new file mode 100644 index 000000000..2144bb59b --- /dev/null +++ b/spec/requests/api/v1/inventory_checklist_items_controller_spec.rb @@ -0,0 +1,379 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Api::V1::InventoryChecklistItemsController', type: :request do + before :all do + @user = create(:user) + @teams = create_list(:team, 2, created_by: @user) + create(:user_team, user: @user, team: @teams.first, role: 2) + + @valid_inventory = create(:repository, name: Faker::Name.unique.name, + created_by: @user, team: @teams.first) + + @wrong_inventory = create(:repository, name: Faker::Name.unique.name, + created_by: @user, team: @teams.second) + create(:repository_column, name: Faker::Name.unique.name, + repository: @wrong_inventory, data_type: :RepositoryTextValue) + + @text_column = create(:repository_column, name: Faker::Name.unique.name, + repository: @valid_inventory, data_type: :RepositoryTextValue) + @checklist_column = create(:repository_column, name: Faker::Name.unique.name, + repository: @valid_inventory, data_type: :RepositoryChecklistValue) + @wrong_checklist_column = create(:repository_column, + name: Faker::Name.unique.name, + repository: @wrong_inventory, + data_type: :RepositoryChecklistValue) + create_list(:repository_checklist_item, 10, repository: @valid_inventory, + repository_column: @checklist_column) + create(:repository_checklist_item, repository: @wrong_inventory, + repository_column: @wrong_checklist_column) + + @valid_headers = + { 'Authorization': 'Bearer ' + generate_token(@user.id) } + end + + describe 'GET inventory_checklist_items, #index' do + it 'Response with correct inventory list items, default per page' do + hash_body = nil + get api_v1_team_inventory_column_checklist_items_path( + team_id: @teams.first.id, + inventory_id: @teams.first.repositories.first.id, + column_id: @checklist_column.id + ), headers: @valid_headers + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@checklist_column.repository_checklist_items.limit(10), + each_serializer: Api::V1::InventoryChecklistItemSerializer) + .as_json[:data] + ) + end + + it 'When invalid request, user in not member of the team' do + hash_body = nil + get api_v1_team_inventory_column_checklist_items_path( + team_id: @wrong_inventory.team.id, + inventory_id: @wrong_inventory.id, + column_id: @wrong_inventory.repository_columns.first.id + ), headers: @valid_headers + expect(response).to have_http_status(403) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 403) + end + + it 'When invalid request, non existing inventory' do + hash_body = nil + get api_v1_team_inventory_column_checklist_items_path( + team_id: @teams.first.id, + inventory_id: 123, + column_id: 999 + ), headers: @valid_headers + expect(response).to have_http_status(404) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 404) + end + + it 'When invalid request, repository from another team' do + hash_body = nil + get api_v1_team_inventory_column_checklist_items_path( + team_id: @teams.first.id, + inventory_id: @wrong_inventory.id, + column_id: @checklist_column.id + ), headers: @valid_headers + expect(response).to have_http_status(404) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 404) + end + + it 'When invalid request, items from text column' do + hash_body = nil + get api_v1_team_inventory_column_checklist_items_path( + team_id: @teams.first.id, + inventory_id: @valid_inventory.id, + column_id: @text_column.id + ), headers: @valid_headers + expect(response).to have_http_status(400) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 400) + end + end + + describe 'GET inventory_checklist_items, #show' do + it 'Response with correct inventory list item' do + hash_body = nil + get api_v1_team_inventory_column_checklist_item_path( + id: @checklist_column.repository_checklist_items.first.id, + team_id: @teams.first.id, + inventory_id: @teams.first.repositories.first.id, + column_id: @checklist_column.id + ), headers: @valid_headers + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@checklist_column.repository_checklist_items.first, + serializer: Api::V1::InventoryChecklistItemSerializer) + .as_json[:data] + ) + end + + it 'When invalid request, non existing list item' do + hash_body = nil + get api_v1_team_inventory_column_checklist_item_path( + id: 999, + team_id: @teams.first.id, + inventory_id: @teams.first.repositories.first.id, + column_id: @checklist_column.id + ), headers: @valid_headers + expect(response).to have_http_status(404) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 404) + end + + it 'When invalid request, list item from another column' do + hash_body = nil + get api_v1_team_inventory_column_checklist_items_path( + id: @wrong_checklist_column.repository_checklist_items.first.id, + team_id: @teams.first.id, + inventory_id: @wrong_inventory.id, + column_id: @checklist_column.id + ), headers: @valid_headers + expect(response).to have_http_status(404) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 404) + end + end + + describe 'POST inventory_checklist_item, #create' do + before :all do + @valid_headers['Content-Type'] = 'application/vnd.api+json' + @request_body = { + data: { + type: 'inventory_checklist_items', + attributes: { data: Faker::Name.unique.name } + } + } + end + + it 'Response with correct inventory list item' do + hash_body = nil + post api_v1_team_inventory_column_checklist_items_path( + team_id: @teams.first.id, + inventory_id: @valid_inventory.id, + column_id: @checklist_column + ), params: @request_body.to_json, headers: @valid_headers + expect(response).to have_http_status 201 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(RepositoryChecklistItem.last, + serializer: Api::V1::InventoryChecklistItemSerializer) + .as_json[:data] + ) + end + + it 'When invalid request, user in not member of the team' do + hash_body = nil + post api_v1_team_inventory_column_checklist_items_path( + team_id: @teams.second.id, + inventory_id: @valid_inventory.id, + column_id: @checklist_column + ), params: @request_body.to_json, headers: @valid_headers + expect(response).to have_http_status 403 + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 403) + end + + it 'When invalid request, non existing inventory' do + hash_body = nil + post api_v1_team_inventory_column_checklist_items_path( + team_id: @teams.first.id, + inventory_id: 123, + column_id: @checklist_column + ), params: @request_body.to_json, headers: @valid_headers + expect(response).to have_http_status 404 + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 404) + end + + it 'When invalid request, repository from another team' do + hash_body = nil + post api_v1_team_inventory_column_checklist_items_path( + team_id: @teams.first.id, + inventory_id: @wrong_inventory.id, + column_id: @checklist_column + ), params: @request_body.to_json, headers: @valid_headers + expect(response).to have_http_status(404) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 404) + end + + it 'When invalid request, incorrect type' do + invalid_request_body = @request_body.deep_dup + invalid_request_body[:data][:type] = 'repository_rows' + hash_body = nil + post api_v1_team_inventory_column_checklist_items_path( + team_id: @teams.first.id, + inventory_id: @valid_inventory.id, + column_id: @checklist_column + ), params: invalid_request_body.to_json, headers: @valid_headers + expect(response).to have_http_status(400) + expect { hash_body = json }.to_not raise_exception + expect(hash_body['errors'][0]).to include('status': 400) + end + + it 'When invalid request, missing type param' do + invalid_request_body = @request_body.deep_dup + invalid_request_body[:data].delete(:type) + hash_body = nil + post api_v1_team_inventory_column_checklist_items_path( + team_id: @teams.first.id, + inventory_id: @valid_inventory.id, + column_id: @checklist_column + ), params: invalid_request_body.to_json, headers: @valid_headers + expect(response).to have_http_status(400) + expect { hash_body = json }.to_not raise_exception + expect(hash_body['errors'][0]).to include('status': 400) + end + + it 'When invalid request, missing attributes values' do + hash_body = nil + invalid_request_body = @request_body.deep_dup + invalid_request_body[:data][:attributes].delete(:data) + post api_v1_team_inventory_column_checklist_items_path( + team_id: @teams.first.id, + inventory_id: @valid_inventory.id, + column_id: @checklist_column + ), params: invalid_request_body.to_json, headers: @valid_headers + expect(response).to have_http_status(400) + expect { hash_body = json }.to_not raise_exception + expect(hash_body['errors'][0]).to include('status': 400) + end + end + + describe 'PUT inventory_checklist_item, #update' do + before :all do + @valid_headers['Content-Type'] = 'application/vnd.api+json' + @request_body = { + data: { + id: @checklist_column.repository_checklist_items.first.id, + type: 'inventory_checklist_items', + attributes: { data: 'Updated' } + } + } + end + + it 'Response with correct inventory list item' do + hash_body = nil + item_id = @checklist_column.repository_checklist_items.first.id + put api_v1_team_inventory_column_checklist_item_path( + id: item_id, + team_id: @teams.first.id, + inventory_id: @valid_inventory.id, + column_id: @checklist_column + ), params: @request_body.to_json, headers: @valid_headers + expect(response).to have_http_status 200 + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@checklist_column.repository_checklist_items.find(item_id), + serializer: Api::V1::InventoryChecklistItemSerializer) + .as_json[:data] + ) + expect(@checklist_column.repository_checklist_items.find(item_id).data).to match('Updated') + end + + it 'When invalid request, incorrect type' do + invalid_request_body = @request_body.deep_dup + invalid_request_body[:data][:type] = 'repository_rows' + hash_body = nil + put api_v1_team_inventory_column_checklist_item_path( + id: @checklist_column.repository_checklist_items.first.id, + team_id: @teams.first.id, + inventory_id: @valid_inventory.id, + column_id: @checklist_column + ), params: invalid_request_body.to_json, headers: @valid_headers + expect(response).to have_http_status(400) + expect { hash_body = json }.to_not raise_exception + expect(hash_body['errors'][0]).to include('status': 400) + end + + it 'When invalid request, missing attributes values' do + hash_body = nil + invalid_request_body = @request_body.deep_dup + invalid_request_body[:data][:attributes].delete(:data) + put api_v1_team_inventory_column_checklist_item_path( + id: @checklist_column.repository_checklist_items.first.id, + team_id: @teams.first.id, + inventory_id: @valid_inventory.id, + column_id: @checklist_column + ), params: invalid_request_body.to_json, headers: @valid_headers + expect(response).to have_http_status(400) + expect { hash_body = json }.to_not raise_exception + expect(hash_body['errors'][0]).to include('status': 400) + end + + it 'When invalid request, non existing item' do + hash_body = nil + invalid_request_body = @request_body.deep_dup + invalid_request_body[:id] = 999 + put api_v1_team_inventory_column_checklist_item_path( + id: 999, + team_id: @teams.first.id, + inventory_id: @valid_inventory.id, + column_id: @checklist_column + ), params: invalid_request_body.to_json, headers: @valid_headers + expect(response).to have_http_status(404) + expect { hash_body = json }.to_not raise_exception + expect(hash_body['errors'][0]).to include('status': 404) + end + end + + describe 'DELETE inventory_checklist_item, #destroy' do + it 'Destroys inventory list item' do + deleted_id = @checklist_column.repository_checklist_items.last.id + delete api_v1_team_inventory_column_checklist_item_path( + id: deleted_id, + team_id: @teams.first.id, + inventory_id: @valid_inventory.id, + column_id: @checklist_column.id + ), headers: @valid_headers + expect(response).to have_http_status(200) + expect(RepositoryChecklistItem.where(id: deleted_id)).to_not exist + end + + it 'Invalid request, non existing inventory list item' do + delete api_v1_team_inventory_column_checklist_item_path( + id: 1001, + team_id: @teams.first.id, + inventory_id: @valid_inventory.id, + column_id: @checklist_column.id + ), headers: @valid_headers + expect(response).to have_http_status(404) + end + + it 'When invalid request, incorrect repository' do + deleted_id = @checklist_column.repository_checklist_items.last.id + delete api_v1_team_inventory_column_checklist_item_path( + id: deleted_id, + team_id: @teams.first.id, + inventory_id: 9999, + column_id: @checklist_column.id + ), headers: @valid_headers + expect(response).to have_http_status(404) + expect(RepositoryChecklistItem.where(id: deleted_id)).to exist + end + + it 'When invalid request, repository from another team' do + deleted_id = @checklist_column.repository_checklist_items.last.id + delete api_v1_team_inventory_column_checklist_item_path( + id: deleted_id, + team_id: @teams.second.id, + inventory_id: @valid_inventory.id, + column_id: @checklist_column.id + ), headers: @valid_headers + expect(response).to have_http_status(403) + expect(RepositoryChecklistItem.where(id: deleted_id)).to exist + end + end +end