mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-07 05:34:55 +08:00
Add forms controllers [SCI-11354]
This commit is contained in:
parent
7ffb664dad
commit
8c57e28078
18 changed files with 873 additions and 0 deletions
77
app/controllers/form_fields_controller.rb
Normal file
77
app/controllers/form_fields_controller.rb
Normal file
|
@ -0,0 +1,77 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class FormFieldsController < ApplicationController
|
||||
before_action :load_form
|
||||
before_action :load_form_field, only: %i(update destroy)
|
||||
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
@form_field = FormField.new(
|
||||
form_field_params.merge(
|
||||
{
|
||||
form: @form,
|
||||
created_by: current_user,
|
||||
last_modified_by: current_user,
|
||||
position: @form.form_fields.length
|
||||
}
|
||||
)
|
||||
)
|
||||
if @form_field.save
|
||||
render json: @form_field, serializer: FormFieldSerializer, user: current_user
|
||||
else
|
||||
render json: { error: @form_field.errors.full_messages }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
if @form_field.update(form_field_params.merge({ last_modified_by: current_user }))
|
||||
render json: @form_field, serializer: FormFieldSerializer, user: current_user
|
||||
else
|
||||
render json: { error: @form_field.errors.full_messages }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
ActiveRecord::Base.transaction do
|
||||
if @form_field.discard
|
||||
render json: {}
|
||||
else
|
||||
render json: { error: @storage_location.errors.full_messages }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def reorder
|
||||
ActiveRecord::Base.transaction do
|
||||
params.permit(form_field_positions: %i(position id))[:form_field_positions].each do |data|
|
||||
form_field = @form.form_fields.find(data['id'].to_i)
|
||||
form_field.insert_at(data['position'].to_i)
|
||||
end
|
||||
end
|
||||
|
||||
render json: params[:form_field_positions], status: :ok
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
render json: { errors: form_field.errors }, status: :conflict
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_form
|
||||
@form = Form.find_by(id: params[:form_id])
|
||||
|
||||
return render_404 unless @form
|
||||
end
|
||||
|
||||
def load_form_field
|
||||
@form_field = @form.form_fields.find_by(id: params[:id])
|
||||
|
||||
return render_404 unless @form_field
|
||||
end
|
||||
|
||||
def form_field_params
|
||||
params.require(:form_field).permit(:name, :description, { data: [%i(type)] }, :required, :allow_not_applicable, :uid)
|
||||
end
|
||||
end
|
131
app/controllers/forms_controller.rb
Normal file
131
app/controllers/forms_controller.rb
Normal file
|
@ -0,0 +1,131 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class FormsController < ApplicationController
|
||||
before_action :load_form, only: %i(show update publish unpublish)
|
||||
|
||||
def index
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json do
|
||||
forms = Lists::FormsService.new(current_user, current_team, params).call
|
||||
render json: forms,
|
||||
each_serializer: Lists::FormSerializer,
|
||||
user: current_user
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
respond_to do |format|
|
||||
format.json { render json: @form, serializer: Lists::FormSerializer, include: %i(form_fields), user: current_user }
|
||||
format.html
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
@form = Form.new(
|
||||
name: I18n.t('forms.default_name'),
|
||||
team: current_team,
|
||||
created_by: current_user,
|
||||
last_modified_by: current_user
|
||||
)
|
||||
|
||||
if @form.save
|
||||
render json: @form, serializer: Lists::FormSerializer, user: current_user
|
||||
else
|
||||
render json: { error: @form.errors.full_messages }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
if @form.update(form_params.merge({ last_modified_by: current_user }))
|
||||
render json: @form, serializer: Lists::FormSerializer, user: current_user
|
||||
else
|
||||
render json: { error: @form.errors.full_messages }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def publish
|
||||
ActiveRecord::Base.transaction do
|
||||
@form.update!(
|
||||
published_by: current_user,
|
||||
published_on: DateTime.now
|
||||
)
|
||||
|
||||
render json: @form, serializer: Lists::FormSerializer, user: current_user
|
||||
end
|
||||
end
|
||||
|
||||
def unpublish
|
||||
ActiveRecord::Base.transaction do
|
||||
@form.update!(
|
||||
published_by: nil,
|
||||
published_on: nil
|
||||
)
|
||||
|
||||
render json: @form, serializer: Lists::FormSerializer, user: current_user
|
||||
end
|
||||
end
|
||||
|
||||
def archive
|
||||
forms = current_team.forms.active.where(id: params[:form_ids])
|
||||
return render_404 if forms.blank?
|
||||
|
||||
counter = 0
|
||||
|
||||
forms.each do |form|
|
||||
form.transaction do
|
||||
form.archive!(current_user)
|
||||
counter += 1
|
||||
rescue StandardError => e
|
||||
Rails.logger.error e.message
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
|
||||
if counter.positive?
|
||||
render json: { message: t('forms.archived.success_flash', number: counter) }
|
||||
else
|
||||
render json: { message: t('forms.archived.error_flash') }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def restore
|
||||
forms = current_team.forms.archived.where(id: params[:form_ids])
|
||||
return render_404 if forms.blank?
|
||||
|
||||
counter = 0
|
||||
|
||||
forms.each do |form|
|
||||
form.transaction do
|
||||
form.restore!(current_user)
|
||||
counter += 1
|
||||
rescue StandardError => e
|
||||
Rails.logger.error e.message
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
|
||||
if counter.positive?
|
||||
render json: { message: t('forms.restored.success_flash', number: counter) }
|
||||
else
|
||||
render json: { message: t('forms.restored.error_flash') }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_form
|
||||
@form = Form.find_by(id: params[:id])
|
||||
|
||||
return render_404 unless @form
|
||||
end
|
||||
|
||||
def form_params
|
||||
params.require(:form).permit(:name, :description)
|
||||
end
|
||||
end
|
18
app/models/form.rb
Normal file
18
app/models/form.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Form < ApplicationRecord
|
||||
include ArchivableModel
|
||||
|
||||
belongs_to :team
|
||||
belongs_to :parent, class_name: 'Form', optional: true
|
||||
belongs_to :created_by, class_name: 'User'
|
||||
belongs_to :last_modified_by, class_name: 'User'
|
||||
belongs_to :published_by, class_name: 'User', optional: true
|
||||
belongs_to :archived_by, class_name: 'User', optional: true
|
||||
belongs_to :restored_by, class_name: 'User', optional: true
|
||||
|
||||
has_many :form_fields, inverse_of: :form, dependent: :destroy
|
||||
|
||||
validates :name, length: { minimum: Constants::NAME_MIN_LENGTH, maximum: Constants::NAME_MAX_LENGTH }
|
||||
validates :description, length: { maximum: Constants::NAME_MAX_LENGTH }
|
||||
end
|
15
app/models/form_field.rb
Normal file
15
app/models/form_field.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class FormField < ApplicationRecord
|
||||
include Discard::Model
|
||||
|
||||
belongs_to :form
|
||||
belongs_to :created_by, class_name: 'User'
|
||||
belongs_to :last_modified_by, class_name: 'User'
|
||||
|
||||
validates :name, length: { minimum: Constants::NAME_MIN_LENGTH, maximum: Constants::NAME_MAX_LENGTH }
|
||||
validates :description, length: { maximum: Constants::NAME_MAX_LENGTH }
|
||||
validates :position, presence: true, uniqueness: { scope: :form }
|
||||
|
||||
acts_as_list scope: :form, top_of_list: 0, sequential_updates: true
|
||||
end
|
|
@ -73,6 +73,7 @@ class Team < ApplicationRecord
|
|||
dependent: :destroy
|
||||
has_many :shareable_links, inverse_of: :team, dependent: :destroy
|
||||
has_many :storage_locations, dependent: :destroy
|
||||
has_many :forms, dependent: :destroy
|
||||
|
||||
attr_accessor :without_templates
|
||||
|
||||
|
|
9
app/serializers/form_field_serializer.rb
Normal file
9
app/serializers/form_field_serializer.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class FormFieldSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :description, :updated_at, :type, :required, :allow_not_applicable, :uid, :position
|
||||
|
||||
def type
|
||||
object.data[:type]
|
||||
end
|
||||
end
|
21
app/serializers/lists/form_serializer.rb
Normal file
21
app/serializers/lists/form_serializer.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Lists
|
||||
class FormSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :description, :published_on, :published_by, :updated_at
|
||||
|
||||
has_many :form_fields, key: :form_fields, serializer: FormFieldSerializer
|
||||
|
||||
def published_by
|
||||
object.published_by&.full_name
|
||||
end
|
||||
|
||||
def published_on
|
||||
I18n.l(object.published_on, format: :full) if object.published_on
|
||||
end
|
||||
|
||||
def updated_at
|
||||
I18n.l(object.updated_at, format: :full) if object.updated_at
|
||||
end
|
||||
end
|
||||
end
|
16
app/services/lists/forms_service.rb
Normal file
16
app/services/lists/forms_service.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Lists
|
||||
class FormsService < BaseService
|
||||
def initialize(user, team, params)
|
||||
super(nil, params, user: user)
|
||||
@team = team
|
||||
end
|
||||
|
||||
def fetch_records
|
||||
@records = Form.where(team: @team)
|
||||
end
|
||||
|
||||
def filter_records; end
|
||||
end
|
||||
end
|
|
@ -1054,6 +1054,15 @@ en:
|
|||
add_user_generic_error: "An error occurred. "
|
||||
can_add_user_to_project: "Can not add user to the project."
|
||||
|
||||
forms:
|
||||
default_name: "Untitled form"
|
||||
restored:
|
||||
success_flash: "<strong>%{number}</strong> form(s) successfully restored."
|
||||
error_flash: "Failed to restore form(s)."
|
||||
archived:
|
||||
success_flash: "<strong>%{number}</strong> form(s) successfully archived."
|
||||
error_flash: "Failed to archive form(s)."
|
||||
|
||||
label_templates:
|
||||
types:
|
||||
fluics_label_template: 'Fluics'
|
||||
|
|
|
@ -850,6 +850,24 @@ Rails.application.routes.draw do
|
|||
end
|
||||
end
|
||||
|
||||
resources :forms, only: %i(index show create update) do
|
||||
member do
|
||||
post :publish
|
||||
post :unpublish
|
||||
end
|
||||
|
||||
collection do
|
||||
post :archive
|
||||
post :restore
|
||||
end
|
||||
|
||||
resources :form_fields, only: %i(create update destroy) do
|
||||
collection do
|
||||
post :reorder
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
get 'search' => 'search#index'
|
||||
get 'search/new' => 'search#new', as: :new_search
|
||||
resource :search, only: [], controller: :search do
|
||||
|
|
41
db/migrate/20241209074134_create_forms.rb
Normal file
41
db/migrate/20241209074134_create_forms.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateForms < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
create_table :forms do |t|
|
||||
t.string :name
|
||||
t.string :description
|
||||
t.references :team, index: true, foreign_key: { to_table: :teams }
|
||||
t.references :created_by, index: true, foreign_key: { to_table: :users }
|
||||
t.references :last_modified_by, index: true, foreign_key: { to_table: :users }
|
||||
t.references :parent, index: true, foreign_key: { to_table: :forms }
|
||||
t.references :published_by, index: true, foreign_key: { to_table: :users }
|
||||
t.datetime :published_on
|
||||
t.boolean :archived, default: false, null: false
|
||||
t.datetime :archived_on
|
||||
t.datetime :restored_on
|
||||
t.references :archived_by, index: true, foreign_key: { to_table: :users }
|
||||
t.references :restored_by, index: true, foreign_key: { to_table: :users }
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
create_table :form_fields do |t|
|
||||
t.references :form, index: true, foreign_key: { to_table: :forms }
|
||||
t.references :created_by, index: true, foreign_key: { to_table: :users }
|
||||
t.references :last_modified_by, index: true, foreign_key: { to_table: :users }
|
||||
t.string :name
|
||||
t.string :description
|
||||
t.integer :position, null: false
|
||||
t.jsonb :data, null: false, default: {}
|
||||
t.boolean :required, default: false, null: false
|
||||
t.boolean :allow_not_applicable, default: false, null: false
|
||||
t.string :uid
|
||||
t.datetime :discarded_at, index: true
|
||||
|
||||
t.index %i(form_id position), unique: true
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
56
db/schema.rb
56
db/schema.rb
|
@ -224,6 +224,52 @@ ActiveRecord::Schema[7.0].define(version: 2024_10_28_105317) do
|
|||
t.index ["restored_by_id"], name: "index_experiments_on_restored_by_id"
|
||||
end
|
||||
|
||||
create_table "form_fields", force: :cascade do |t|
|
||||
t.bigint "form_id"
|
||||
t.bigint "created_by_id"
|
||||
t.bigint "last_modified_by_id"
|
||||
t.string "name"
|
||||
t.string "description"
|
||||
t.integer "position", null: false
|
||||
t.jsonb "data", default: {}, null: false
|
||||
t.boolean "required", default: false, null: false
|
||||
t.boolean "allow_not_applicable", default: false, null: false
|
||||
t.string "uid"
|
||||
t.datetime "discarded_at"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["created_by_id"], name: "index_form_fields_on_created_by_id"
|
||||
t.index ["discarded_at"], name: "index_form_fields_on_discarded_at"
|
||||
t.index ["form_id", "position"], name: "index_form_fields_on_form_id_and_position", unique: true
|
||||
t.index ["form_id"], name: "index_form_fields_on_form_id"
|
||||
t.index ["last_modified_by_id"], name: "index_form_fields_on_last_modified_by_id"
|
||||
end
|
||||
|
||||
create_table "forms", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.string "description"
|
||||
t.bigint "team_id"
|
||||
t.bigint "created_by_id"
|
||||
t.bigint "last_modified_by_id"
|
||||
t.bigint "parent_id"
|
||||
t.bigint "published_by_id"
|
||||
t.datetime "published_on"
|
||||
t.boolean "archived", default: false, null: false
|
||||
t.datetime "archived_on"
|
||||
t.datetime "restored_on"
|
||||
t.bigint "archived_by_id"
|
||||
t.bigint "restored_by_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["archived_by_id"], name: "index_forms_on_archived_by_id"
|
||||
t.index ["created_by_id"], name: "index_forms_on_created_by_id"
|
||||
t.index ["last_modified_by_id"], name: "index_forms_on_last_modified_by_id"
|
||||
t.index ["parent_id"], name: "index_forms_on_parent_id"
|
||||
t.index ["published_by_id"], name: "index_forms_on_published_by_id"
|
||||
t.index ["restored_by_id"], name: "index_forms_on_restored_by_id"
|
||||
t.index ["team_id"], name: "index_forms_on_team_id"
|
||||
end
|
||||
|
||||
create_table "hidden_repository_cell_reminders", force: :cascade do |t|
|
||||
t.bigint "repository_cell_id", null: false
|
||||
t.bigint "user_id", null: false
|
||||
|
@ -1409,6 +1455,16 @@ ActiveRecord::Schema[7.0].define(version: 2024_10_28_105317) do
|
|||
add_foreign_key "experiments", "users", column: "created_by_id"
|
||||
add_foreign_key "experiments", "users", column: "last_modified_by_id"
|
||||
add_foreign_key "experiments", "users", column: "restored_by_id"
|
||||
add_foreign_key "form_fields", "forms"
|
||||
add_foreign_key "form_fields", "users", column: "created_by_id"
|
||||
add_foreign_key "form_fields", "users", column: "last_modified_by_id"
|
||||
add_foreign_key "forms", "forms", column: "parent_id"
|
||||
add_foreign_key "forms", "teams"
|
||||
add_foreign_key "forms", "users", column: "archived_by_id"
|
||||
add_foreign_key "forms", "users", column: "created_by_id"
|
||||
add_foreign_key "forms", "users", column: "last_modified_by_id"
|
||||
add_foreign_key "forms", "users", column: "published_by_id"
|
||||
add_foreign_key "forms", "users", column: "restored_by_id"
|
||||
add_foreign_key "hidden_repository_cell_reminders", "repository_cells"
|
||||
add_foreign_key "hidden_repository_cell_reminders", "users"
|
||||
add_foreign_key "label_templates", "teams"
|
||||
|
|
137
spec/controllers/form_fields_controller_spec.rb
Normal file
137
spec/controllers/form_fields_controller_spec.rb
Normal file
|
@ -0,0 +1,137 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe FormFieldsController, type: :controller do
|
||||
login_user
|
||||
|
||||
include_context 'reference_project_structure'
|
||||
|
||||
let!(:form) { create :form, team: team }
|
||||
let!(:form_field) { create :form_field, form: form }
|
||||
let!(:form_fields) { create_list :form_field, 5, form: form }
|
||||
|
||||
describe 'POST create' do
|
||||
let(:action) { post :create, params: params, format: :json }
|
||||
let(:params) do
|
||||
{
|
||||
form_id: form.id,
|
||||
form_field: {
|
||||
name: Faker::Name.unique.name,
|
||||
description: Faker::Lorem.sentence,
|
||||
data: { type: 'text' },
|
||||
required: true,
|
||||
allow_not_applicable: true,
|
||||
uid: Faker::Name.unique.name
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns success response' do
|
||||
action
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.media_type).to eq 'application/json'
|
||||
response_body = JSON.parse(response.body)
|
||||
expect(response_body['data']['attributes']['name']).to eq params[:form_field][:name]
|
||||
expect(response_body['data']['attributes']['description']).to eq params[:form_field][:description]
|
||||
expect(response_body['data']['attributes']['required']).to eq params[:form_field][:required]
|
||||
expect(response_body['data']['attributes']['allow_not_applicable']).to eq params[:form_field][:allow_not_applicable]
|
||||
expect(response_body['data']['attributes']['uid']).to eq params[:form_field][:uid]
|
||||
expect(response_body['data']['attributes']['position']).to eq(form_fields.length + 1)
|
||||
end
|
||||
|
||||
it 'invalid params' do
|
||||
params[:form_field][:name] = ''
|
||||
action
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT create' do
|
||||
let(:action) { put :update, params: params, format: :json }
|
||||
let(:params) do
|
||||
{
|
||||
form_id: form.id,
|
||||
id: form_field.id,
|
||||
form_field: {
|
||||
name: Faker::Name.unique.name,
|
||||
description: Faker::Lorem.sentence,
|
||||
data: { type: 'text' },
|
||||
required: true,
|
||||
allow_not_applicable: true,
|
||||
uid: Faker::Name.unique.name
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns success response' do
|
||||
action
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.media_type).to eq 'application/json'
|
||||
response_body = JSON.parse(response.body)
|
||||
expect(response_body['data']['attributes']['name']).to eq params[:form_field][:name]
|
||||
expect(response_body['data']['attributes']['description']).to eq params[:form_field][:description]
|
||||
expect(response_body['data']['attributes']['required']).to eq params[:form_field][:required]
|
||||
expect(response_body['data']['attributes']['allow_not_applicable']).to eq params[:form_field][:allow_not_applicable]
|
||||
expect(response_body['data']['attributes']['uid']).to eq params[:form_field][:uid]
|
||||
expect(response_body['data']['attributes']['position']).to eq(form_field.position)
|
||||
end
|
||||
|
||||
it 'invalid params' do
|
||||
params[:form_field][:name] = ''
|
||||
action
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE destroy' do
|
||||
|
||||
let(:action) { delete :destroy, params: params }
|
||||
let(:params) do
|
||||
{
|
||||
form_id: form.id,
|
||||
id: form_field.id,
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns success response' do
|
||||
action
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
|
||||
it 'invalid id' do
|
||||
params[:id] = -1
|
||||
action
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST reorder' do
|
||||
|
||||
let(:action) { delete :reorder, params: params }
|
||||
let(:params) do
|
||||
{
|
||||
form_id: form.id,
|
||||
form_field_positions: form_positions
|
||||
}
|
||||
end
|
||||
|
||||
let(:form_positions) do
|
||||
positions = form.form_fields.pluck(:position).reverse
|
||||
form.form_fields.pluck(:id).each_with_index.map do |id, i|
|
||||
{ id: id, position: positions[i] }
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns success response' do
|
||||
action
|
||||
expect(response).to have_http_status(:success)
|
||||
|
||||
new_form_fields_order = form.form_fields.order(position: :asc).pluck(:id, :position)
|
||||
|
||||
expect(new_form_fields_order).to(
|
||||
eq(form_positions.map(&:values).sort { |a, b| a[1] <=> b[1] })
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
185
spec/controllers/forms_controller_spec.rb
Normal file
185
spec/controllers/forms_controller_spec.rb
Normal file
|
@ -0,0 +1,185 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe FormsController, type: :controller do
|
||||
login_user
|
||||
|
||||
include_context 'reference_project_structure'
|
||||
|
||||
let!(:form) { create :form, team: team }
|
||||
let!(:form2) { create :form, team: team }
|
||||
let!(:form_field) { create :form_field, form: form2}
|
||||
|
||||
describe '#index' do
|
||||
let(:params) { { team: team.id } }
|
||||
|
||||
it 'returns success response' do
|
||||
get :index, params: params, format: :json
|
||||
expect(response).to have_http_status(:success)
|
||||
|
||||
response_body = JSON.parse(response.body)
|
||||
|
||||
expect(response_body).to match_array(
|
||||
JSON.parse(
|
||||
ActiveModelSerializers::SerializableResource
|
||||
.new(team.forms,
|
||||
each_serializer: Lists::FormSerializer)
|
||||
.to_json
|
||||
)
|
||||
)
|
||||
expect(response_body['data'].length).to eq 2
|
||||
expect(response.body).to include(form.name)
|
||||
expect(response.body).to include(form2.name)
|
||||
expect(response.body).not_to include(form_field.name)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#show' do
|
||||
it 'unsuccessful response with non existing id' do
|
||||
get :show, format: :json, params: { id: -1 }
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
|
||||
it 'successful response' do
|
||||
get :show, format: :json, params: { id: form2.id }
|
||||
expect(response).to have_http_status(:success)
|
||||
|
||||
response_body = JSON.parse(response.body)
|
||||
expect(response_body).to match_array(
|
||||
JSON.parse(
|
||||
ActiveModelSerializers::SerializableResource
|
||||
.new(form2,
|
||||
serializer: Lists::FormSerializer,
|
||||
include: :form_fields)
|
||||
.to_json
|
||||
)
|
||||
)
|
||||
|
||||
expect(response_body['included'].first['attributes']['name']).to eq form_field.name
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST create' do
|
||||
let(:action) { post :create, format: :json }
|
||||
|
||||
it 'returns success response' do
|
||||
action
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.media_type).to eq 'application/json'
|
||||
response_body = JSON.parse(response.body)
|
||||
expect(response_body['data']['attributes']['name']).to eq I18n.t('forms.default_name')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT update' do
|
||||
let(:action) { put :update, params: params, format: :json }
|
||||
let(:params) do
|
||||
{
|
||||
id: form.id,
|
||||
form: {
|
||||
name: 'Renamed form',
|
||||
description: 'test description'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns success response' do
|
||||
action
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.media_type).to eq 'application/json'
|
||||
response_body = JSON.parse(response.body)
|
||||
expect(response_body['data']['attributes']['name']).to eq params[:form][:name]
|
||||
expect(response_body['data']['attributes']['description']).to eq params[:form][:description]
|
||||
end
|
||||
|
||||
it 'incorrect id' do
|
||||
get :update, format: :json, params: { id: -1 }
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe 'POST publish' do
|
||||
let(:action) { put :publish, params: params, format: :json }
|
||||
let(:params) do
|
||||
{
|
||||
id: form.id,
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns success response' do
|
||||
action
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.media_type).to eq 'application/json'
|
||||
response_body = JSON.parse(response.body)
|
||||
|
||||
expect(response_body['data']['attributes']['published_by']).to eq user.full_name
|
||||
expect(response_body['data']['attributes']['published_on']).not_to eq nil
|
||||
end
|
||||
|
||||
it 'incorrect id' do
|
||||
get :publish, format: :json, params: { id: -1 }
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST unpublish' do
|
||||
let(:action) { put :unpublish, params: params, format: :json }
|
||||
let(:params) do
|
||||
{
|
||||
id: form.id,
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns success response' do
|
||||
action
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.media_type).to eq 'application/json'
|
||||
response_body = JSON.parse(response.body)
|
||||
|
||||
expect(response_body['data']['attributes']['published_by']).to eq nil
|
||||
expect(response_body['data']['attributes']['published_on']).to eq nil
|
||||
end
|
||||
|
||||
it 'incorrect id' do
|
||||
get :unpublish, format: :json, params: { id: -1 }
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST archive' do
|
||||
let(:action) { put :archive, params: params, format: :json }
|
||||
let(:params) do
|
||||
{
|
||||
form_ids: [form.id]
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns success response' do
|
||||
expect(form.archived?).to eq false
|
||||
action
|
||||
expect(response).to have_http_status(:success)
|
||||
form.reload
|
||||
expect(form.archived?).to eq true
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST restore' do
|
||||
let!(:form_archived) { create :form, :archived, team: team }
|
||||
let(:action) { put :restore, params: params, format: :json }
|
||||
let(:params) do
|
||||
{
|
||||
form_ids: [form_archived.id]
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns success response' do
|
||||
expect(form_archived.archived?).to eq true
|
||||
action
|
||||
expect(response).to have_http_status(:success)
|
||||
form_archived.reload
|
||||
expect(form_archived.archived?).to eq false
|
||||
end
|
||||
end
|
||||
end
|
12
spec/factories/form_fields.rb
Normal file
12
spec/factories/form_fields.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :form_field do
|
||||
name { Faker::Name.unique.name }
|
||||
description { Faker::Lorem.sentence }
|
||||
sequence(:position) { |n| n - 1 }
|
||||
association :created_by, factory: :user
|
||||
association :last_modified_by, factory: :user
|
||||
association :form
|
||||
end
|
||||
end
|
18
spec/factories/forms.rb
Normal file
18
spec/factories/forms.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :form do
|
||||
name { Faker::Name.unique.name }
|
||||
description { Faker::Lorem.sentence }
|
||||
association :created_by, factory: :user
|
||||
association :last_modified_by, factory: :user
|
||||
team { create :team, created_by: created_by }
|
||||
archived { false }
|
||||
|
||||
trait :archived do
|
||||
archived { true }
|
||||
archived_on { Time.zone.now }
|
||||
archived_by { created_by }
|
||||
end
|
||||
end
|
||||
end
|
52
spec/models/form_field_spec.rb
Normal file
52
spec/models/form_field_spec.rb
Normal file
|
@ -0,0 +1,52 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe FormField, type: :model do
|
||||
let(:form_field) { build :form_field }
|
||||
|
||||
it 'is valid' do
|
||||
expect(form_field).to be_valid
|
||||
end
|
||||
|
||||
it 'should be of class form field' do
|
||||
expect(subject.class).to eq FormField
|
||||
end
|
||||
|
||||
describe 'Database table' do
|
||||
it { should have_db_column :id }
|
||||
it { should have_db_column :name }
|
||||
it { should have_db_column :description }
|
||||
it { should have_db_column :form_id }
|
||||
it { should have_db_column :created_by_id }
|
||||
it { should have_db_column :last_modified_by_id }
|
||||
it { should have_db_column :position }
|
||||
it { should have_db_column :data }
|
||||
it { should have_db_column :required }
|
||||
it { should have_db_column :allow_not_applicable }
|
||||
it { should have_db_column :uid }
|
||||
it { should have_db_column :created_at }
|
||||
it { should have_db_column :updated_at }
|
||||
it { should have_db_column :discarded_at }
|
||||
end
|
||||
|
||||
describe 'Relations' do
|
||||
it { should belong_to(:form) }
|
||||
it { should belong_to(:created_by).class_name('User') }
|
||||
it { should belong_to(:last_modified_by).class_name('User') }
|
||||
end
|
||||
|
||||
describe 'Validations' do
|
||||
it { should validate_presence_of :position }
|
||||
describe '#name' do
|
||||
it do
|
||||
is_expected.to(validate_length_of(:name).is_at_least(Constants::NAME_MIN_LENGTH).is_at_most(Constants::NAME_MAX_LENGTH))
|
||||
end
|
||||
end
|
||||
describe '#description' do
|
||||
it do
|
||||
is_expected.to(validate_length_of(:description).is_at_most(Constants::NAME_MAX_LENGTH))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
57
spec/models/form_spec.rb
Normal file
57
spec/models/form_spec.rb
Normal file
|
@ -0,0 +1,57 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Form, type: :model do
|
||||
let(:form) { build :form }
|
||||
|
||||
it 'is valid' do
|
||||
expect(form).to be_valid
|
||||
end
|
||||
|
||||
it 'should be of class Form' do
|
||||
expect(subject.class).to eq Form
|
||||
end
|
||||
|
||||
describe 'Database table' do
|
||||
it { should have_db_column :id }
|
||||
it { should have_db_column :name }
|
||||
it { should have_db_column :description }
|
||||
it { should have_db_column :team_id }
|
||||
it { should have_db_column :created_by_id }
|
||||
it { should have_db_column :last_modified_by_id }
|
||||
it { should have_db_column :parent_id }
|
||||
it { should have_db_column :published_by_id }
|
||||
it { should have_db_column :published_on }
|
||||
it { should have_db_column :archived }
|
||||
it { should have_db_column :archived_on }
|
||||
it { should have_db_column :archived_by_id }
|
||||
it { should have_db_column :restored_by_id }
|
||||
it { should have_db_column :restored_on }
|
||||
it { should have_db_column :created_at }
|
||||
it { should have_db_column :updated_at }
|
||||
end
|
||||
|
||||
describe 'Relations' do
|
||||
it { should belong_to(:team) }
|
||||
it { should belong_to(:created_by).class_name('User') }
|
||||
it { should belong_to(:last_modified_by).class_name('User') }
|
||||
it { should belong_to(:parent).class_name('Form').optional }
|
||||
it { should belong_to(:archived_by).class_name('User').optional }
|
||||
it { should belong_to(:restored_by).class_name('User').optional }
|
||||
it { should have_many :form_fields }
|
||||
end
|
||||
|
||||
describe 'Validations' do
|
||||
describe '#name' do
|
||||
it do
|
||||
is_expected.to(validate_length_of(:name).is_at_least(Constants::NAME_MIN_LENGTH).is_at_most(Constants::NAME_MAX_LENGTH))
|
||||
end
|
||||
end
|
||||
describe '#description' do
|
||||
it do
|
||||
is_expected.to(validate_length_of(:description).is_at_most(Constants::NAME_MAX_LENGTH))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue