mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-09-20 14:45:56 +08:00
adds unit specs for datatable service [fixes SCI-2068]
This commit is contained in:
parent
26883af386
commit
4f951f6679
|
@ -16,7 +16,6 @@ class MyModulesController < ApplicationController
|
|||
before_action :load_repository, only: %i(assign_repository_records
|
||||
unassign_repository_records
|
||||
repository_index)
|
||||
before_action :load_columns_mappings, only: :repository_index
|
||||
before_action :check_manage_permissions,
|
||||
only: %i(update destroy description due_date)
|
||||
before_action :check_view_info_permissions, only: :show
|
||||
|
@ -373,11 +372,11 @@ class MyModulesController < ApplicationController
|
|||
page = (params[:start].to_i / per_page) + 1
|
||||
records = RepositoryDatatableService.new(@repository,
|
||||
params,
|
||||
@columns_mappings,
|
||||
current_user,
|
||||
@my_module)
|
||||
@assigned_rows = records.assigned_rows
|
||||
@repository_row_count = records.repository_rows.count
|
||||
@columns_mappings = records.mappings
|
||||
@repository_rows = records.repository_rows.page(page).per(per_page)
|
||||
render 'repository_rows/index.json'
|
||||
end
|
||||
|
@ -602,16 +601,6 @@ class MyModulesController < ApplicationController
|
|||
render_403 unless can_read_team?(@repository.team)
|
||||
end
|
||||
|
||||
def load_columns_mappings
|
||||
# Make mappings of custom columns, so we have same id for every column
|
||||
i = 5
|
||||
@columns_mappings = {}
|
||||
@repository.repository_columns.order(:id).each do |column|
|
||||
@columns_mappings[column.id] = i.to_s
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
def check_manage_permissions
|
||||
render_403 unless can_manage_module?(@my_module)
|
||||
end
|
||||
|
|
|
@ -6,7 +6,6 @@ class RepositoryRowsController < ApplicationController
|
|||
before_action :load_info_modal_vars, only: :show
|
||||
before_action :load_vars, only: %i(edit update)
|
||||
before_action :load_repository, only: %i(create delete_records index)
|
||||
before_action :load_columns_mappings, only: :index
|
||||
before_action :check_create_permissions, only: :create
|
||||
before_action :check_edit_permissions, only: %i(edit update)
|
||||
before_action :check_destroy_permissions, only: :delete_records
|
||||
|
@ -17,10 +16,10 @@ class RepositoryRowsController < ApplicationController
|
|||
page = (params[:start].to_i / per_page) + 1
|
||||
records = RepositoryDatatableService.new(@repository,
|
||||
params,
|
||||
@columns_mappings,
|
||||
current_user)
|
||||
@assigned_rows = records.assigned_rows
|
||||
@repository_row_count = records.repository_rows.count
|
||||
@columns_mappings = records.mappings
|
||||
@repository_rows = records.repository_rows.page(page).per(per_page)
|
||||
end
|
||||
|
||||
|
@ -255,16 +254,6 @@ class RepositoryRowsController < ApplicationController
|
|||
render_403 unless can_read_team?(@repository.team)
|
||||
end
|
||||
|
||||
def load_columns_mappings
|
||||
# Make mappings of custom columns, so we have same id for every column
|
||||
i = 5
|
||||
@columns_mappings = {}
|
||||
@repository.repository_columns.order(:id).each do |column|
|
||||
@columns_mappings[column.id] = i.to_s
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
def check_create_permissions
|
||||
render_403 unless can_manage_repository_rows?(@repository.team)
|
||||
end
|
||||
|
|
|
@ -1,332 +0,0 @@
|
|||
require 'active_record'
|
||||
|
||||
class RepositoryDatatable < CustomDatatable
|
||||
include ActionView::Helpers::TextHelper
|
||||
include SamplesHelper
|
||||
include InputSanitizeHelper
|
||||
include Rails.application.routes.url_helpers
|
||||
include ActionView::Helpers::UrlHelper
|
||||
include ApplicationHelper
|
||||
include ActiveRecord::Sanitization::ClassMethods
|
||||
|
||||
ASSIGNED_SORT_COL = 'assigned'.freeze
|
||||
|
||||
REPOSITORY_TABLE_DEFAULT_STATE = {
|
||||
'time' => 0,
|
||||
'start' => 0,
|
||||
'length' => 5,
|
||||
'order' => [[2, 'desc']],
|
||||
'search' => { 'search' => '',
|
||||
'smart' => true,
|
||||
'regex' => false,
|
||||
'caseInsensitive' => true },
|
||||
'columns' => [],
|
||||
'assigned' => 'assigned',
|
||||
'ColReorder' => [*0..4]
|
||||
}
|
||||
5.times do
|
||||
REPOSITORY_TABLE_DEFAULT_STATE['columns'] << {
|
||||
'visible' => true,
|
||||
'search' => { 'search' => '',
|
||||
'smart' => true,
|
||||
'regex' => false,
|
||||
'caseInsensitive' => true }
|
||||
}
|
||||
end
|
||||
REPOSITORY_TABLE_DEFAULT_STATE.freeze
|
||||
|
||||
def initialize(view,
|
||||
repository,
|
||||
my_module = nil,
|
||||
user = nil)
|
||||
super(view)
|
||||
@repository = repository
|
||||
@team = repository.team
|
||||
@my_module = my_module
|
||||
@user = user
|
||||
end
|
||||
|
||||
# Define sortable columns, so 1st column will be sorted by attribute
|
||||
# in sortable_columns[0]
|
||||
def sortable_columns
|
||||
sort_array = [
|
||||
ASSIGNED_SORT_COL,
|
||||
'RepositoryRow.name',
|
||||
'RepositoryRow.created_at',
|
||||
'User.full_name'
|
||||
]
|
||||
|
||||
sort_array.push(*repository_columns_sort_by)
|
||||
@sortable_columns = sort_array
|
||||
end
|
||||
|
||||
# Define attributes on which we perform search
|
||||
def searchable_columns
|
||||
search_array = [
|
||||
'RepositoryRow.name',
|
||||
'RepositoryRow.created_at',
|
||||
'User.full_name'
|
||||
]
|
||||
|
||||
# search_array.push(*repository_columns_sort_by)
|
||||
@searchable_columns ||= filter_search_array search_array
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# filters the search array by checking if the the column is visible
|
||||
def filter_search_array(input_array)
|
||||
param_index = 2
|
||||
filtered_array = []
|
||||
input_array.each do |col|
|
||||
next if columns_params.to_a[param_index].nil?
|
||||
params_col =
|
||||
columns_params.to_a.find { |v| v[1]['data'] == param_index.to_s }
|
||||
filtered_array.push(col) unless params_col[1]['searchable'] == 'false'
|
||||
param_index += 1
|
||||
end
|
||||
filtered_array
|
||||
end
|
||||
|
||||
# Get array of columns to sort by (for custom columns)
|
||||
def repository_columns_sort_by
|
||||
array = []
|
||||
@repository.repository_columns.count.times do
|
||||
array << 'RepositoryCell.value'
|
||||
end
|
||||
array
|
||||
end
|
||||
|
||||
# Returns json of current repository rows (already paginated)
|
||||
def data
|
||||
records.map do |record|
|
||||
row = {
|
||||
'DT_RowId': record.id,
|
||||
'1': assigned_row(record),
|
||||
'2': escape_input(record.name),
|
||||
'3': I18n.l(record.created_at, format: :full),
|
||||
'4': escape_input(record.created_by.full_name),
|
||||
'recordEditUrl':
|
||||
Rails.application.routes.url_helpers
|
||||
.edit_repository_repository_row_path(@repository,
|
||||
record.id),
|
||||
'recordUpdateUrl':
|
||||
Rails.application.routes.url_helpers
|
||||
.repository_repository_row_path(@repository, record.id),
|
||||
'recordInfoUrl':
|
||||
Rails.application.routes.url_helpers.repository_row_path(record.id)
|
||||
}
|
||||
|
||||
# Add custom columns
|
||||
record.repository_cells.each do |cell|
|
||||
row[@columns_mappings[cell.repository_column.id]] =
|
||||
custom_auto_link(
|
||||
display_tooltip(cell.value.data,
|
||||
Constants::NAME_MAX_LENGTH),
|
||||
simple_format: true,
|
||||
team: @team
|
||||
)
|
||||
end
|
||||
row
|
||||
end
|
||||
end
|
||||
|
||||
def assigned_row(record)
|
||||
if @assigned_rows && @assigned_rows.include?(record)
|
||||
"<span class='circle'> </span>"
|
||||
else
|
||||
"<span class='circle disabled'> </span>"
|
||||
end
|
||||
end
|
||||
|
||||
# Query database for records (this will be later paginated and filtered)
|
||||
# after that "data" function will return json
|
||||
def get_raw_records
|
||||
repository_rows = RepositoryRow
|
||||
.preload(
|
||||
:repository_columns,
|
||||
:created_by,
|
||||
repository_cells: :value
|
||||
)
|
||||
.joins(:created_by)
|
||||
.where(repository: @repository)
|
||||
|
||||
# Make mappings of custom columns, so we have same id for every column
|
||||
i = 5
|
||||
@columns_mappings = {}
|
||||
@repository.repository_columns.order(:id).each do |column|
|
||||
@columns_mappings[column.id] = i.to_s
|
||||
i += 1
|
||||
end
|
||||
|
||||
if @my_module
|
||||
@assigned_rows = @my_module.repository_rows
|
||||
.preload(
|
||||
:repository_columns,
|
||||
:created_by,
|
||||
repository_cells: :value
|
||||
)
|
||||
.joins(:created_by)
|
||||
.where(repository: @repository)
|
||||
return @assigned_rows if dt_params[:assigned] == 'assigned'
|
||||
else
|
||||
@assigned_rows = repository_rows.joins(
|
||||
'INNER JOIN my_module_repository_rows ON
|
||||
(repository_rows.id = my_module_repository_rows.repository_row_id)'
|
||||
)
|
||||
end
|
||||
|
||||
repository_rows
|
||||
end
|
||||
|
||||
# Override default behaviour
|
||||
# Don't filter and paginate records when sorting by custom column - everything
|
||||
# is done in sort_records method - you might ask why, well if you want the
|
||||
# number of samples/all samples it's dependant upon sort_record query
|
||||
def fetch_records
|
||||
records = get_raw_records
|
||||
records = filter_records(records) if dt_params[:search].present? &&
|
||||
dt_params[:search][:value].present?
|
||||
records = sort_records(records) if order_params.present?
|
||||
records = paginate_records(records) unless dt_params[:length].present? &&
|
||||
dt_params[:length] == '-1'
|
||||
escape_special_chars
|
||||
records
|
||||
end
|
||||
|
||||
# Overriden to make it work for custom columns, because they are polymorphic
|
||||
# NOTE: Function assumes the provided records/rows are only from the current
|
||||
# repository!
|
||||
def filter_records(repo_rows)
|
||||
return repo_rows unless dt_params[:search].present? &&
|
||||
dt_params[:search][:value].present?
|
||||
search_val = dt_params[:search][:value]
|
||||
|
||||
filtered_rows = repo_rows.find_by_sql(
|
||||
"SELECT DISTINCT repository_rows.*
|
||||
FROM repository_rows
|
||||
INNER JOIN (
|
||||
SELECT users.*
|
||||
FROM users
|
||||
) AS users
|
||||
ON users.id = repository_rows.created_by_id
|
||||
LEFT OUTER JOIN (
|
||||
SELECT repository_cells.repository_row_id,
|
||||
repository_text_values.data AS text_value,
|
||||
to_char(repository_date_values.data, 'DD.MM.YYYY HH24:MI')
|
||||
AS date_value
|
||||
FROM repository_cells
|
||||
INNER JOIN repository_text_values
|
||||
ON repository_text_values.id = repository_cells.value_id
|
||||
FULL OUTER JOIN repository_date_values
|
||||
ON repository_date_values.id = repository_cells.value_id
|
||||
) AS values
|
||||
ON values.repository_row_id = repository_rows.id
|
||||
WHERE repository_rows.repository_id = #{@repository.id}
|
||||
AND (repository_rows.name ILIKE '%#{search_val}%'
|
||||
OR to_char(repository_rows.created_at, 'DD.MM.YYYY HH24:MI')
|
||||
ILIKE '%#{search_val}%'
|
||||
OR users.full_name ILIKE '%#{search_val}%'
|
||||
OR text_value ILIKE '%#{search_val}%'
|
||||
OR date_value ILIKE '%#{search_val}%')"
|
||||
)
|
||||
repo_rows.where(id: filtered_rows)
|
||||
end
|
||||
|
||||
# Override default sort method if needed
|
||||
def sort_records(records)
|
||||
if sort_column(order_params) == ASSIGNED_SORT_COL
|
||||
# If "assigned" column is sorted when viewing assigned items
|
||||
return records if @my_module && dt_params[:assigned] == 'assigned'
|
||||
# If "assigned" column is sorted
|
||||
direction = sort_null_direction(order_params)
|
||||
if @my_module
|
||||
# Depending on the sort, order nulls first or
|
||||
# nulls last on repository_cells association
|
||||
records.joins(
|
||||
"LEFT OUTER JOIN my_module_repository_rows ON
|
||||
(repository_rows.id = my_module_repository_rows.repository_row_id
|
||||
AND (my_module_repository_rows.my_module_id = #{@my_module.id} OR
|
||||
my_module_repository_rows.id IS NULL))"
|
||||
).order("my_module_repository_rows.id NULLS #{direction}")
|
||||
else
|
||||
sort_assigned_records(records, order_params['dir'])
|
||||
end
|
||||
elsif sorting_by_custom_column
|
||||
ci = sortable_displayed_columns[
|
||||
order_params['column'].to_i - 1
|
||||
]
|
||||
column_id = @columns_mappings.key((ci.to_i + 1).to_s)
|
||||
dir = sort_direction(order_params)
|
||||
|
||||
records.joins(
|
||||
"LEFT OUTER JOIN (SELECT repository_cells.repository_row_id,
|
||||
repository_text_values.data AS value FROM repository_cells
|
||||
INNER JOIN repository_text_values
|
||||
ON repository_text_values.id = repository_cells.value_id
|
||||
WHERE repository_cells.repository_column_id = #{column_id}) AS values
|
||||
ON values.repository_row_id = repository_rows.id"
|
||||
).order("values.value #{dir}")
|
||||
else
|
||||
super(records)
|
||||
end
|
||||
end
|
||||
|
||||
def sort_null_direction(item)
|
||||
val = sort_direction(item)
|
||||
val == 'ASC' ? 'LAST' : 'FIRST'
|
||||
end
|
||||
|
||||
def inverse_sort_direction(item)
|
||||
val = sort_direction(item)
|
||||
val == 'ASC' ? 'DESC' : 'ASC'
|
||||
end
|
||||
|
||||
def sorting_by_custom_column
|
||||
sort_column(order_params) == 'repository_cells.value'
|
||||
end
|
||||
|
||||
# Escapes special characters in search query
|
||||
def escape_special_chars
|
||||
if dt_params[:search].present?
|
||||
dt_params[:search][:value] = ActiveRecord::Base
|
||||
.__send__(:sanitize_sql_like,
|
||||
dt_params[:search][:value])
|
||||
end
|
||||
end
|
||||
|
||||
def new_sort_column(item)
|
||||
coli = item[:column].to_i - 1
|
||||
model, column = sortable_columns[sortable_displayed_columns[coli].to_i]
|
||||
.split('.')
|
||||
|
||||
return model if model == ASSIGNED_SORT_COL
|
||||
[model.constantize.table_name, column].join('.')
|
||||
end
|
||||
|
||||
def generate_sortable_displayed_columns
|
||||
sort_order = RepositoryTableState.load_state(@user, @repository)
|
||||
.first['ColReorder']
|
||||
sort_order.shift
|
||||
sort_order.map! { |i| (i.to_i - 1).to_s }
|
||||
|
||||
@sortable_displayed_columns = sort_order
|
||||
end
|
||||
|
||||
def sort_assigned_records(records, direction)
|
||||
assigned = records.joins(:my_module_repository_rows).distinct.pluck(:id)
|
||||
unassigned = records.where.not(id: assigned).pluck(:id)
|
||||
if direction == 'asc'
|
||||
ids = assigned + unassigned
|
||||
elsif direction == 'desc'
|
||||
ids = unassigned + assigned
|
||||
end
|
||||
|
||||
order_by_index = ActiveRecord::Base.send(
|
||||
:sanitize_sql_array,
|
||||
["position((',' || repository_rows.id || ',') in ?)",
|
||||
ids.join(',') + ',']
|
||||
)
|
||||
records.order(order_by_index)
|
||||
end
|
||||
end
|
|
@ -43,7 +43,7 @@ class RepositoryTableState < ApplicationRecord
|
|||
else
|
||||
# add column
|
||||
index = repository_state['columns'].count
|
||||
repository_state['columns'][index] = RepositoryDatatable::
|
||||
repository_state['columns'][index] = Constants::
|
||||
REPOSITORY_TABLE_DEFAULT_STATE['columns'].first
|
||||
repository_state['ColReorder'].insert(2, index.to_s)
|
||||
end
|
||||
|
@ -52,12 +52,12 @@ class RepositoryTableState < ApplicationRecord
|
|||
end
|
||||
|
||||
def self.create_state(user, repository)
|
||||
default_columns_num = RepositoryDatatable::
|
||||
default_columns_num = Constants::
|
||||
REPOSITORY_TABLE_DEFAULT_STATE['columns'].count
|
||||
repository_state =
|
||||
RepositoryDatatable::REPOSITORY_TABLE_DEFAULT_STATE.deep_dup
|
||||
Constants::REPOSITORY_TABLE_DEFAULT_STATE.deep_dup
|
||||
repository.repository_columns.each_with_index do |_, index|
|
||||
repository_state['columns'] << RepositoryDatatable::
|
||||
repository_state['columns'] << Constants::
|
||||
REPOSITORY_TABLE_DEFAULT_STATE['columns'].first
|
||||
repository_state['ColReorder'] << (default_columns_num + index)
|
||||
end
|
||||
|
|
|
@ -1,19 +1,28 @@
|
|||
class RepositoryDatatableService
|
||||
|
||||
attr_reader :repository_rows, :assigned_rows
|
||||
attr_reader :repository_rows, :assigned_rows, :mappings
|
||||
|
||||
def initialize(repository, params, mappings, user, my_module = nil)
|
||||
@mappings = mappings
|
||||
def initialize(repository, params, user, my_module = nil)
|
||||
@repository = repository
|
||||
@mappings = mappings
|
||||
@user = user
|
||||
@my_module = my_module
|
||||
@params = params
|
||||
create_columns_mappings
|
||||
process_query
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_columns_mappings
|
||||
# Make mappings of custom columns, so we have same id for every column
|
||||
i = 5
|
||||
@mappings = {}
|
||||
@repository.repository_columns.order(:id).each do |column|
|
||||
@mappings[column.id] = i.to_s
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
def process_query
|
||||
contitions = build_conditions(@params)
|
||||
order_obj = contitions[:order_by_column]
|
||||
|
|
|
@ -75,7 +75,7 @@ Rails.application.configure do
|
|||
config.assets.raise_runtime_errors = true
|
||||
|
||||
# Only log info and higher on development
|
||||
config.log_level = :debug
|
||||
config.log_level = :info
|
||||
|
||||
# Only allow Better Errors to work on trusted ip, use ifconfig to see which
|
||||
# one you use and put it into application.yml!
|
||||
|
|
|
@ -859,6 +859,31 @@ class Constants
|
|||
]
|
||||
}.freeze
|
||||
|
||||
# Repository default table state
|
||||
REPOSITORY_TABLE_DEFAULT_STATE = {
|
||||
'time' => 0,
|
||||
'start' => 0,
|
||||
'length' => 5,
|
||||
'order' => [[2, 'desc']],
|
||||
'search' => { 'search' => '',
|
||||
'smart' => true,
|
||||
'regex' => false,
|
||||
'caseInsensitive' => true },
|
||||
'columns' => [],
|
||||
'assigned' => 'assigned',
|
||||
'ColReorder' => [*0..4]
|
||||
}
|
||||
5.times do
|
||||
REPOSITORY_TABLE_DEFAULT_STATE['columns'] << {
|
||||
'visible' => true,
|
||||
'search' => { 'search' => '',
|
||||
'smart' => true,
|
||||
'regex' => false,
|
||||
'caseInsensitive' => true }
|
||||
}
|
||||
end
|
||||
REPOSITORY_TABLE_DEFAULT_STATE.freeze
|
||||
|
||||
EXPORTABLE_ZIP_EXPIRATION_DAYS = 7
|
||||
|
||||
# Very basic regex to check for validity of emails
|
||||
|
|
|
@ -7,6 +7,13 @@ describe RepositoryRowsController, type: :controller do
|
|||
let!(:team) { create :team, created_by: user }
|
||||
let!(:user_team) { create :user_team, team: team, user: user }
|
||||
let!(:repository) { create :repository, team: team, created_by: user }
|
||||
let!(:repository_state) do
|
||||
RepositoryTableState.create(
|
||||
repository: repository,
|
||||
user: user,
|
||||
state: Constants::REPOSITORY_TABLE_DEFAULT_STATE
|
||||
)
|
||||
end
|
||||
let!(:repository_row) do
|
||||
create :repository_row, repository: repository,
|
||||
created_by: user,
|
||||
|
@ -41,4 +48,71 @@ describe RepositoryRowsController, type: :controller do
|
|||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
end
|
||||
|
||||
context '#index' do
|
||||
before do
|
||||
repository.repository_rows.destroy_all
|
||||
110.times do |index|
|
||||
create :repository_row, name: "row (#{index})",
|
||||
repository: repository,
|
||||
created_by: user,
|
||||
last_modified_by: user
|
||||
end
|
||||
end
|
||||
|
||||
describe 'json object' do
|
||||
it 'returns a valid object' do
|
||||
params = { order: { 0 => { column: '3', dir: 'asc' } },
|
||||
drow: '0',
|
||||
search: { value: '' },
|
||||
length: '10',
|
||||
start: '1',
|
||||
repository_id: repository.id }
|
||||
get :index, params: params, format: :json
|
||||
|
||||
expect(response.status).to eq 200
|
||||
expect(response).to match_response_schema('repository_row_datatables')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'pagination' do
|
||||
it 'returns first 10 records' do
|
||||
params = { order: { 0 => { column: '3', dir: 'asc' } },
|
||||
drow: '0',
|
||||
search: { value: '' },
|
||||
length: '10',
|
||||
start: '1',
|
||||
repository_id: repository.id }
|
||||
get :index, params: params, format: :json
|
||||
response_body = JSON.parse(response.body)
|
||||
expect(response_body['data'].length).to eq 10
|
||||
expect(response_body['data'].first['2']).to eq 'row (0)'
|
||||
end
|
||||
|
||||
it 'returns next 10 records' do
|
||||
params = { order: { 0 => { column: '3', dir: 'asc' } },
|
||||
drow: '0',
|
||||
search: { value: '' },
|
||||
length: '10',
|
||||
start: '11',
|
||||
repository_id: repository.id }
|
||||
get :index, params: params, format: :json
|
||||
response_body = JSON.parse(response.body)
|
||||
expect(response_body['data'].length).to eq 10
|
||||
expect(response_body['data'].first['2']).to eq 'row (10)'
|
||||
end
|
||||
|
||||
it 'returns first 25 records' do
|
||||
params = { order: { 0 => { column: '2', dir: 'desc' } },
|
||||
drow: '0',
|
||||
search: { value: '' },
|
||||
length: '25',
|
||||
start: '1',
|
||||
repository_id: repository.id }
|
||||
get :index, params: params, format: :json
|
||||
response_body = JSON.parse(response.body)
|
||||
expect(response_body['data'].length).to eq 25
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe SearchRepository, type: :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
116
spec/services/repository_datatable_service_spec.rb
Normal file
116
spec/services/repository_datatable_service_spec.rb
Normal file
|
@ -0,0 +1,116 @@
|
|||
require 'rails_helper'
|
||||
|
||||
describe RepositoryDatatableService do
|
||||
let!(:team) { create :team }
|
||||
let!(:user) { create :user, email: 'user_one@asdf.com' }
|
||||
let!(:repository) do
|
||||
create :repository, name: 'my repo', created_by: user, team: team
|
||||
end
|
||||
let!(:repository_column) do
|
||||
create :repository_column, name: 'My column', data_type: :RepositoryListValue
|
||||
end
|
||||
let!(:repository_state) do
|
||||
RepositoryTableState.create(
|
||||
repository: repository,
|
||||
user: user,
|
||||
state: Constants::REPOSITORY_TABLE_DEFAULT_STATE
|
||||
)
|
||||
end
|
||||
let!(:repository_row) do
|
||||
create :repository_row, name: 'A row',
|
||||
repository: repository,
|
||||
created_by: user,
|
||||
last_modified_by: user
|
||||
end
|
||||
let!(:repository_row_two) do
|
||||
create :repository_row, name: 'B row',
|
||||
repository: repository,
|
||||
created_by: user,
|
||||
last_modified_by: user
|
||||
end
|
||||
let!(:list_item) do
|
||||
create :repository_list_item, data: 'bug',
|
||||
repository: repository,
|
||||
repository_column: repository_column,
|
||||
created_by: user,
|
||||
last_modified_by: user
|
||||
end
|
||||
let!(:repository_list_value) do
|
||||
create :repository_list_value, repository_list_item: list_item,
|
||||
created_by: user,
|
||||
last_modified_by: user,
|
||||
repository_cell_attributes: {
|
||||
repository_column: repository_column,
|
||||
repository_row: repository_row
|
||||
}
|
||||
end
|
||||
|
||||
context 'object' do
|
||||
let(:params) do
|
||||
{ order: { 0 => { column: '2', dir: 'asc' } }, search: { value: 'row' } }
|
||||
end
|
||||
let(:subject) { RepositoryDatatableService.new(repository, params, user) }
|
||||
|
||||
describe '#build_conditions/1' do
|
||||
it 'parsers the contitions' do
|
||||
contitions = subject.send(:build_conditions, params)
|
||||
expect(contitions[:search_value]).to eq 'row'
|
||||
expect(contitions[:order_by_column]).to eq({ column: 2, dir: 'asc' })
|
||||
end
|
||||
end
|
||||
|
||||
describe '#sortable_columns' do
|
||||
it 'returns an array of all columns that are sortable' do
|
||||
columns = subject.send(:sortable_columns)
|
||||
expect(columns.length).to eq 5
|
||||
end
|
||||
end
|
||||
|
||||
describe '#sort_null_direction' do
|
||||
it 'returns LAST if value is ascending' do
|
||||
result = subject.send(:sort_null_direction, 'ASC')
|
||||
expect(result).to eq 'LAST'
|
||||
end
|
||||
|
||||
it 'returns FIRST if value is not ascending' do
|
||||
result = subject.send(:sort_null_direction, 'DESC')
|
||||
expect(result).to eq 'FIRST'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'ordering' do
|
||||
it 'is ordered by row name asc' do
|
||||
params = { order: { 0 => { column: '2', dir: 'asc' } },
|
||||
search: { value: '' } }
|
||||
subject = RepositoryDatatableService.new(repository, params, user)
|
||||
expect(subject.repository_rows.first.name).to eq 'A row'
|
||||
expect(subject.repository_rows.last.name).to eq 'B row'
|
||||
end
|
||||
|
||||
it 'is ordered by row name desc' do
|
||||
params = { order: { 0 => { column: '2', dir: 'desc' } },
|
||||
search: { value: '' } }
|
||||
subject = RepositoryDatatableService.new(repository, params, user)
|
||||
expect(subject.repository_rows.first.name).to eq 'B row'
|
||||
expect(subject.repository_rows.last.name).to eq 'A row'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'search' do
|
||||
before do
|
||||
create :repository_row, name: 'test',
|
||||
repository: repository,
|
||||
created_by: user,
|
||||
last_modified_by: user
|
||||
end
|
||||
|
||||
it 'returns only the searched entity' do
|
||||
params = { order: { 0 => { column: '2', dir: 'desc' } },
|
||||
search: { value: 'test' } }
|
||||
subject = RepositoryDatatableService.new(repository, params, user)
|
||||
expect(subject.repository_rows.first.name).to eq 'test'
|
||||
expect(subject.repository_rows.count).to eq 1
|
||||
end
|
||||
end
|
||||
end
|
25
spec/support/api/schemas/repository_row_datatables.json
Normal file
25
spec/support/api/schemas/repository_row_datatables.json
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"type": "object",
|
||||
"required": ["draw", "recordsTotal", "recordsFiltered", "data"],
|
||||
"properties": {
|
||||
"draw": { "type": "integer" },
|
||||
"recordsTotal": { "type": "integer" },
|
||||
"recordsFiltered": { "type": "integer" },
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items":{
|
||||
"required": ["DT_RowId", "1", "2", "3", "4", "recordEditUrl", "recordUpdateUrl", "recordInfoUrl"],
|
||||
"properties": {
|
||||
"DT_RowId": { "type": "integer" },
|
||||
"1": { "type": "string" },
|
||||
"2": { "type": "string" },
|
||||
"3": { "type": "string" },
|
||||
"4": { "type": "string" },
|
||||
"recordEditUrl": { "type": "string" },
|
||||
"recordUpdateUrl": { "type": "string" },
|
||||
"recordInfoUrl": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue