ajax-datatables-rails 0.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.codeclimate.yml +8 -0
- data/.github/workflows/ci.yml +128 -0
- data/.gitignore +23 -0
- data/.rspec +1 -0
- data/.rubocop.yml +58 -0
- data/Appraisals +28 -0
- data/CHANGELOG.md +102 -7
- data/Gemfile +4 -1
- data/Guardfile +16 -0
- data/LICENSE +17 -18
- data/README.md +595 -404
- data/Rakefile +4 -2
- data/ajax-datatables-rails.gemspec +41 -25
- data/appraisal.yml +56 -0
- data/bin/_guard-core +29 -0
- data/bin/appraisal +29 -0
- data/bin/bundle +114 -0
- data/bin/guard +29 -0
- data/bin/rackup +27 -0
- data/bin/rake +29 -0
- data/bin/rspec +29 -0
- data/bin/rubocop +29 -0
- data/config.ru +7 -0
- data/doc/migrate.md +97 -0
- data/doc/webpack.md +55 -0
- data/gemfiles/rails_5.2.8.gemfile +21 -0
- data/gemfiles/rails_6.0.6.gemfile +21 -0
- data/gemfiles/rails_6.1.7.gemfile +21 -0
- data/gemfiles/rails_7.0.4.gemfile +21 -0
- data/lib/ajax-datatables-rails/active_record.rb +7 -0
- data/lib/ajax-datatables-rails/base.rb +114 -149
- data/lib/ajax-datatables-rails/datatable/column/date_filter.rb +68 -0
- data/lib/ajax-datatables-rails/datatable/column/order.rb +29 -0
- data/lib/ajax-datatables-rails/datatable/column/search.rb +125 -0
- data/lib/ajax-datatables-rails/datatable/column.rb +123 -0
- data/lib/ajax-datatables-rails/datatable/datatable.rb +91 -0
- data/lib/ajax-datatables-rails/datatable/simple_order.rb +59 -0
- data/lib/ajax-datatables-rails/datatable/simple_search.rb +23 -0
- data/lib/ajax-datatables-rails/datatable.rb +6 -0
- data/lib/ajax-datatables-rails/error.rb +9 -0
- data/lib/ajax-datatables-rails/orm/active_record.rb +60 -0
- data/lib/ajax-datatables-rails/orm.rb +6 -0
- data/lib/ajax-datatables-rails/version.rb +15 -1
- data/lib/ajax-datatables-rails.rb +11 -7
- data/lib/generators/rails/datatable_generator.rb +11 -22
- data/lib/generators/rails/templates/datatable.rb +13 -15
- data/spec/ajax-datatables-rails/base_spec.rb +223 -0
- data/spec/ajax-datatables-rails/datatable/column_spec.rb +222 -0
- data/spec/ajax-datatables-rails/datatable/datatable_spec.rb +127 -0
- data/spec/ajax-datatables-rails/datatable/simple_order_spec.rb +62 -0
- data/spec/ajax-datatables-rails/datatable/simple_search_spec.rb +19 -0
- data/spec/ajax-datatables-rails/orm/active_record_filter_records_spec.rb +639 -0
- data/spec/ajax-datatables-rails/orm/active_record_paginate_records_spec.rb +67 -0
- data/spec/ajax-datatables-rails/orm/active_record_sort_records_spec.rb +80 -0
- data/spec/dummy/app/assets/config/manifest.js +0 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/routes.rb +5 -0
- data/spec/dummy/config/storage.yml +3 -0
- data/spec/dummy/db/schema.rb +13 -0
- data/spec/dummy/log/.gitignore +1 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/user.rb +11 -0
- data/spec/install_oracle.sh +18 -0
- data/spec/spec_helper.rb +85 -6
- data/spec/support/datatables/complex_datatable.rb +33 -0
- data/spec/support/datatables/complex_datatable_array.rb +16 -0
- data/spec/support/datatables/datatable_cond_date.rb +7 -0
- data/spec/support/datatables/datatable_cond_numeric.rb +53 -0
- data/spec/support/datatables/datatable_cond_proc.rb +13 -0
- data/spec/support/datatables/datatable_cond_string.rb +43 -0
- data/spec/support/datatables/datatable_cond_unknown.rb +7 -0
- data/spec/support/datatables/datatable_custom_column.rb +17 -0
- data/spec/support/datatables/datatable_order_nulls_last.rb +7 -0
- data/spec/support/helpers/params.rb +80 -0
- data/spec/support/models/user.rb +7 -0
- metadata +249 -48
- data/lib/ajax-datatables-rails/config.rb +0 -25
- data/lib/ajax-datatables-rails/extensions/kaminari.rb +0 -12
- data/lib/ajax-datatables-rails/extensions/simple_paginator.rb +0 -12
- data/lib/ajax-datatables-rails/extensions/will_paginate.rb +0 -12
- data/lib/ajax-datatables-rails/models.rb +0 -6
- data/lib/generators/datatable/config_generator.rb +0 -17
- data/lib/generators/datatable/templates/ajax_datatables_rails_config.rb +0 -7
- data/spec/ajax-datatables-rails/ajax_datatables_rails_spec.rb +0 -351
- data/spec/ajax-datatables-rails/kaminari_spec.rb +0 -35
- data/spec/ajax-datatables-rails/models_spec.rb +0 -10
- data/spec/ajax-datatables-rails/simple_paginator_spec.rb +0 -32
- data/spec/ajax-datatables-rails/will_paginate_spec.rb +0 -28
- data/spec/schema.rb +0 -35
- data/spec/test_models.rb +0 -21
@@ -0,0 +1,223 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe AjaxDatatablesRails::Base do
|
6
|
+
|
7
|
+
describe 'an instance' do
|
8
|
+
it 'requires a hash of params' do
|
9
|
+
expect { described_class.new }.to raise_error ArgumentError
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'accepts an options hash' do
|
13
|
+
datatable = described_class.new(sample_params, foo: 'bar')
|
14
|
+
expect(datatable.options).to eq(foo: 'bar')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'User API' do
|
19
|
+
describe '#view_columns' do
|
20
|
+
context 'when method is not defined by the user' do
|
21
|
+
it 'raises an error' do
|
22
|
+
datatable = described_class.new(sample_params)
|
23
|
+
expect { datatable.view_columns }.to raise_error NotImplementedError
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'child class implements view_columns' do
|
28
|
+
it 'expects a hash based defining columns' do
|
29
|
+
datatable = ComplexDatatable.new(sample_params)
|
30
|
+
expect(datatable.view_columns).to be_a(Hash)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#get_raw_records' do
|
36
|
+
context 'when method is not defined by the user' do
|
37
|
+
it 'raises an error' do
|
38
|
+
datatable = described_class.new(sample_params)
|
39
|
+
expect { datatable.get_raw_records }.to raise_error NotImplementedError
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#data' do
|
45
|
+
context 'when method is not defined by the user' do
|
46
|
+
it 'raises an error' do
|
47
|
+
datatable = described_class.new(sample_params)
|
48
|
+
expect { datatable.data }.to raise_error NotImplementedError
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when data is defined as a hash' do
|
53
|
+
let(:datatable) { ComplexDatatable.new(sample_params) }
|
54
|
+
|
55
|
+
it 'returns an array of hashes' do
|
56
|
+
create_list(:user, 5)
|
57
|
+
expect(datatable.data).to be_a(Array)
|
58
|
+
expect(datatable.data.size).to eq 5
|
59
|
+
item = datatable.data.first
|
60
|
+
expect(item).to be_a(Hash)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'htmls escape data' do
|
64
|
+
create(:user, first_name: 'Name "><img src=x onerror=alert("first_name")>', last_name: 'Name "><img src=x onerror=alert("last_name")>')
|
65
|
+
data = datatable.send(:sanitize_data, datatable.data)
|
66
|
+
item = data.first
|
67
|
+
expect(item[:first_name]).to eq 'Name "><img src=x onerror=alert("first_name")>'
|
68
|
+
expect(item[:last_name]).to eq 'Name "><img src=x onerror=alert("last_name")>'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when data is defined as a array' do
|
73
|
+
let(:datatable) { ComplexDatatableArray.new(sample_params) }
|
74
|
+
|
75
|
+
it 'returns an array of arrays' do
|
76
|
+
create_list(:user, 5)
|
77
|
+
expect(datatable.data).to be_a(Array)
|
78
|
+
expect(datatable.data.size).to eq 5
|
79
|
+
item = datatable.data.first
|
80
|
+
expect(item).to be_a(Array)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'htmls escape data' do
|
84
|
+
create(:user, first_name: 'Name "><img src=x onerror=alert("first_name")>', last_name: 'Name "><img src=x onerror=alert("last_name")>')
|
85
|
+
data = datatable.send(:sanitize_data, datatable.data)
|
86
|
+
item = data.first
|
87
|
+
expect(item[2]).to eq 'Name "><img src=x onerror=alert("first_name")>'
|
88
|
+
expect(item[3]).to eq 'Name "><img src=x onerror=alert("last_name")>'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'ORM API' do
|
95
|
+
context 'when ORM is not implemented' do
|
96
|
+
let(:datatable) { AjaxDatatablesRails::Base.new(sample_params) }
|
97
|
+
|
98
|
+
describe '#fetch_records' do
|
99
|
+
it 'raises an error if it does not include an ORM module' do
|
100
|
+
expect { datatable.fetch_records }.to raise_error NotImplementedError
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '#filter_records' do
|
105
|
+
it 'raises an error if it does not include an ORM module' do
|
106
|
+
expect { datatable.filter_records([]) }.to raise_error NotImplementedError
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#sort_records' do
|
111
|
+
it 'raises an error if it does not include an ORM module' do
|
112
|
+
expect { datatable.sort_records([]) }.to raise_error NotImplementedError
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '#paginate_records' do
|
117
|
+
it 'raises an error if it does not include an ORM module' do
|
118
|
+
expect { datatable.paginate_records([]) }.to raise_error NotImplementedError
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'when ORM is implemented' do
|
124
|
+
describe 'it allows method override' do
|
125
|
+
let(:datatable) do
|
126
|
+
datatable = Class.new(ComplexDatatable) do
|
127
|
+
def filter_records(records)
|
128
|
+
raise NotImplementedError.new('FOO')
|
129
|
+
end
|
130
|
+
|
131
|
+
def sort_records(records)
|
132
|
+
raise NotImplementedError.new('FOO')
|
133
|
+
end
|
134
|
+
|
135
|
+
def paginate_records(records)
|
136
|
+
raise NotImplementedError.new('FOO')
|
137
|
+
end
|
138
|
+
end
|
139
|
+
datatable.new(sample_params)
|
140
|
+
end
|
141
|
+
|
142
|
+
describe '#fetch_records' do
|
143
|
+
it 'calls #get_raw_records' do
|
144
|
+
expect(datatable).to receive(:get_raw_records) { User.all }
|
145
|
+
datatable.fetch_records
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'returns a collection of records' do
|
149
|
+
expect(datatable).to receive(:get_raw_records) { User.all }
|
150
|
+
expect(datatable.fetch_records).to be_a(ActiveRecord::Relation)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe '#filter_records' do
|
155
|
+
it {
|
156
|
+
expect { datatable.filter_records([]) }.to raise_error(NotImplementedError).with_message('FOO')
|
157
|
+
}
|
158
|
+
end
|
159
|
+
|
160
|
+
describe '#sort_records' do
|
161
|
+
it {
|
162
|
+
expect { datatable.sort_records([]) }.to raise_error(NotImplementedError).with_message('FOO')
|
163
|
+
}
|
164
|
+
end
|
165
|
+
|
166
|
+
describe '#paginate_records' do
|
167
|
+
it {
|
168
|
+
expect { datatable.paginate_records([]) }.to raise_error(NotImplementedError).with_message('FOO')
|
169
|
+
}
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe 'JSON format' do
|
176
|
+
describe '#as_json' do
|
177
|
+
let(:datatable) { ComplexDatatable.new(sample_params) }
|
178
|
+
|
179
|
+
it 'returns a hash' do
|
180
|
+
create_list(:user, 5)
|
181
|
+
data = datatable.as_json
|
182
|
+
expect(data[:recordsTotal]).to eq 5
|
183
|
+
expect(data[:recordsFiltered]).to eq 5
|
184
|
+
expect(data[:data]).to be_a(Array)
|
185
|
+
expect(data[:data].size).to eq 5
|
186
|
+
end
|
187
|
+
|
188
|
+
context 'with additional_data' do
|
189
|
+
it 'returns a hash' do
|
190
|
+
create_list(:user, 5)
|
191
|
+
expect(datatable).to receive(:additional_data) { { foo: 'bar' } }
|
192
|
+
data = datatable.as_json
|
193
|
+
expect(data[:recordsTotal]).to eq 5
|
194
|
+
expect(data[:recordsFiltered]).to eq 5
|
195
|
+
expect(data[:data]).to be_a(Array)
|
196
|
+
expect(data[:data].size).to eq 5
|
197
|
+
expect(data[:foo]).to eq 'bar'
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe 'User helper methods' do
|
204
|
+
describe '#column_id' do
|
205
|
+
let(:datatable) { ComplexDatatable.new(sample_params) }
|
206
|
+
|
207
|
+
it 'returns column id from view_columns hash' do
|
208
|
+
expect(datatable.column_id(:username)).to eq(0)
|
209
|
+
expect(datatable.column_id('username')).to eq(0)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe '#column_data' do
|
214
|
+
let(:datatable) { ComplexDatatable.new(sample_params) }
|
215
|
+
before { datatable.params[:columns]['0'][:search][:value] = 'doe' }
|
216
|
+
|
217
|
+
it 'returns column data from params' do
|
218
|
+
expect(datatable.column_data(:username)).to eq('doe')
|
219
|
+
expect(datatable.column_data('username')).to eq('doe')
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
@@ -0,0 +1,222 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe AjaxDatatablesRails::Datatable::Column do
|
6
|
+
|
7
|
+
let(:datatable) { ComplexDatatable.new(sample_params) }
|
8
|
+
|
9
|
+
describe 'username column' do
|
10
|
+
|
11
|
+
let(:column) { datatable.datatable.columns.first }
|
12
|
+
|
13
|
+
before { datatable.params[:columns]['0'][:search][:value] = 'searchvalue' }
|
14
|
+
|
15
|
+
it 'is orderable' do
|
16
|
+
expect(column.orderable?).to eq(true)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'sorts nulls last' do
|
20
|
+
expect(column.nulls_last?).to eq(false)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'is searchable' do
|
24
|
+
expect(column.searchable?).to eq(true)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'is searched' do
|
28
|
+
expect(column.searched?).to eq(true)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'has connected to id column' do
|
32
|
+
expect(column.data).to eq('username')
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#data' do
|
36
|
+
it 'returns the data from params' do
|
37
|
+
expect(column.data).to eq 'username'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#source' do
|
42
|
+
it 'returns the data source from view_column' do
|
43
|
+
expect(column.source).to eq 'User.username'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#table' do
|
48
|
+
context 'with ActiveRecord ORM' do
|
49
|
+
it 'returns the corresponding AR table' do
|
50
|
+
expect(column.table).to eq User.arel_table
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'with other ORM' do
|
55
|
+
it 'returns the corresponding model' do
|
56
|
+
expect(User).to receive(:respond_to?).with(:arel_table).and_return(false)
|
57
|
+
expect(column.table).to eq User
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#model' do
|
63
|
+
it 'returns the corresponding AR model' do
|
64
|
+
expect(column.model).to eq User
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#field' do
|
69
|
+
it 'returns the corresponding field in DB' do
|
70
|
+
expect(column.field).to eq :username
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#custom_field?' do
|
75
|
+
it 'returns false if field is bound to an AR field' do
|
76
|
+
expect(column.custom_field?).to be false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#search' do
|
81
|
+
it 'child class' do
|
82
|
+
expect(column.search).to be_a(AjaxDatatablesRails::Datatable::SimpleSearch)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'has search value' do
|
86
|
+
expect(column.search.value).to eq('searchvalue')
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'does not regex' do
|
90
|
+
expect(column.search.regexp?).to eq false
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '#cond' do
|
95
|
+
it 'is :like by default' do
|
96
|
+
expect(column.cond).to eq(:like)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#source' do
|
101
|
+
it 'is :like by default' do
|
102
|
+
expect(column.source).to eq('User.username')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe '#search_query' do
|
107
|
+
it 'bulds search query' do
|
108
|
+
expect(column.search_query.to_sql).to include('%searchvalue%')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe '#sort_query' do
|
113
|
+
it 'builds sort query' do
|
114
|
+
expect(column.sort_query).to eq('users.username')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe '#use_regex?' do
|
119
|
+
it 'is true by default' do
|
120
|
+
expect(column.use_regex?).to be true
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe '#delimiter' do
|
125
|
+
it 'is - by default' do
|
126
|
+
expect(column.delimiter).to eq('-')
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '#formatter' do
|
132
|
+
let(:datatable) { DatatableWithFormater.new(sample_params) }
|
133
|
+
let(:column) { datatable.datatable.columns.find { |c| c.data == 'last_name' } }
|
134
|
+
|
135
|
+
it 'is a proc' do
|
136
|
+
expect(column.formatter).to be_a(Proc)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe '#filter' do
|
141
|
+
let(:datatable) { DatatableCondProc.new(sample_params) }
|
142
|
+
let(:column) { datatable.datatable.columns.find { |c| c.data == 'username' } }
|
143
|
+
|
144
|
+
it 'is a proc' do
|
145
|
+
config = column.instance_variable_get('@view_column')
|
146
|
+
filter = config[:cond]
|
147
|
+
expect(filter).to be_a(Proc)
|
148
|
+
expect(filter).to receive(:call).with(column, column.formatted_value)
|
149
|
+
column.filter
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe '#type_cast' do
|
154
|
+
let(:column) { datatable.datatable.columns.first }
|
155
|
+
|
156
|
+
it 'returns VARCHAR if :db_adapter is :pg' do
|
157
|
+
expect(datatable).to receive(:db_adapter) { :pg }
|
158
|
+
expect(column.send(:type_cast)).to eq('VARCHAR')
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'returns VARCHAR if :db_adapter is :postgre' do
|
162
|
+
expect(datatable).to receive(:db_adapter) { :postgre }
|
163
|
+
expect(column.send(:type_cast)).to eq('VARCHAR')
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'returns VARCHAR if :db_adapter is :postgresql' do
|
167
|
+
expect(datatable).to receive(:db_adapter) { :postgresql }
|
168
|
+
expect(column.send(:type_cast)).to eq('VARCHAR')
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'returns VARCHAR2(4000) if :db_adapter is :oracle' do
|
172
|
+
expect(datatable).to receive(:db_adapter) { :oracle }
|
173
|
+
expect(column.send(:type_cast)).to eq('VARCHAR2(4000)')
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'returns VARCHAR2(4000) if :db_adapter is :oracleenhanced' do
|
177
|
+
expect(datatable).to receive(:db_adapter) { :oracleenhanced }
|
178
|
+
expect(column.send(:type_cast)).to eq('VARCHAR2(4000)')
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'returns CHAR if :db_adapter is :mysql2' do
|
182
|
+
expect(datatable).to receive(:db_adapter) { :mysql2 }
|
183
|
+
expect(column.send(:type_cast)).to eq('CHAR')
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'returns CHAR if :db_adapter is :mysql' do
|
187
|
+
expect(datatable).to receive(:db_adapter) { :mysql }
|
188
|
+
expect(column.send(:type_cast)).to eq('CHAR')
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'returns TEXT if :db_adapter is :sqlite' do
|
192
|
+
expect(datatable).to receive(:db_adapter) { :sqlite }
|
193
|
+
expect(column.send(:type_cast)).to eq('TEXT')
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'returns TEXT if :db_adapter is :sqlite3' do
|
197
|
+
expect(datatable).to receive(:db_adapter) { :sqlite3 }
|
198
|
+
expect(column.send(:type_cast)).to eq('TEXT')
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'returns VARCHAR(4000) if :db_adapter is :sqlserver' do
|
202
|
+
expect(datatable).to receive(:db_adapter) { :sqlserver }
|
203
|
+
expect(column.send(:type_cast)).to eq('VARCHAR(4000)')
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe 'when empty column' do
|
208
|
+
before { datatable.params[:columns]['0'][:data] = '' }
|
209
|
+
|
210
|
+
it 'raises error' do
|
211
|
+
expect { datatable.to_json }.to raise_error(AjaxDatatablesRails::Error::InvalidSearchColumn).with_message('Unknown column. Check that `data` field is filled on JS side with the column name')
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe 'when unknown column' do
|
216
|
+
before { datatable.params[:columns]['0'][:data] = 'foo' }
|
217
|
+
|
218
|
+
it 'raises error' do
|
219
|
+
expect { datatable.to_json }.to raise_error(AjaxDatatablesRails::Error::InvalidSearchColumn).with_message("Check that column 'foo' exists in view_columns")
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe AjaxDatatablesRails::Datatable::Datatable do
|
6
|
+
|
7
|
+
let(:datatable) { ComplexDatatable.new(sample_params).datatable }
|
8
|
+
let(:datatable_json) { ComplexDatatable.new(sample_params_json).datatable }
|
9
|
+
let(:order_option) { { '0' => { 'column' => '0', 'dir' => 'asc' }, '1' => { 'column' => '1', 'dir' => 'desc' } } }
|
10
|
+
let(:order_option_json) { [{ 'column' => '0', 'dir' => 'asc' }, { 'column' => '1', 'dir' => 'desc' }] }
|
11
|
+
|
12
|
+
shared_examples 'order methods' do
|
13
|
+
it 'is orderable' do
|
14
|
+
expect(datatable.orderable?).to eq(true)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'is not orderable' do
|
18
|
+
datatable.options[:order] = nil
|
19
|
+
expect(datatable.orderable?).to eq(false)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'has 2 orderable columns' do
|
23
|
+
datatable.options[:order] = order_option
|
24
|
+
expect(datatable.orders.count).to eq(2)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'first column ordered by ASC' do
|
28
|
+
datatable.options[:order] = order_option
|
29
|
+
expect(datatable.orders.first.direction).to eq('ASC')
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'first column ordered by DESC' do
|
33
|
+
datatable.options[:order] = order_option
|
34
|
+
expect(datatable.orders.last.direction).to eq('DESC')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'child class' do
|
38
|
+
expect(datatable.orders.first).to be_a(AjaxDatatablesRails::Datatable::SimpleOrder)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
shared_examples 'columns methods' do
|
43
|
+
it 'has 7 columns' do
|
44
|
+
expect(datatable.columns.count).to eq(7)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'child class' do
|
48
|
+
expect(datatable.columns.first).to be_a(AjaxDatatablesRails::Datatable::Column)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'with query params' do
|
53
|
+
it_behaves_like 'order methods'
|
54
|
+
it_behaves_like 'columns methods'
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'with json params' do
|
58
|
+
let(:order_option) { order_option_json }
|
59
|
+
let(:datatable) { datatable_json }
|
60
|
+
it_behaves_like 'order methods'
|
61
|
+
it_behaves_like 'columns methods'
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'search methods' do
|
65
|
+
it 'is searchable' do
|
66
|
+
datatable.options[:search][:value] = 'atom'
|
67
|
+
expect(datatable.searchable?).to eq(true)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'is not searchable' do
|
71
|
+
datatable.options[:search][:value] = nil
|
72
|
+
expect(datatable.searchable?).to eq(false)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'child class' do
|
76
|
+
expect(datatable.search).to be_a(AjaxDatatablesRails::Datatable::SimpleSearch)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'option methods' do
|
81
|
+
describe '#paginate?' do
|
82
|
+
it {
|
83
|
+
expect(datatable.paginate?).to be(true)
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#per_page' do
|
88
|
+
context 'when params[:length] is missing' do
|
89
|
+
it 'defaults to 10' do
|
90
|
+
expect(datatable.per_page).to eq(10)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'when params[:length] is passed' do
|
95
|
+
let(:datatable) { ComplexDatatable.new({ length: '20' }).datatable }
|
96
|
+
|
97
|
+
it 'matches the value on view params[:length]' do
|
98
|
+
expect(datatable.per_page).to eq(20)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#offset' do
|
104
|
+
context 'when params[:start] is missing' do
|
105
|
+
it 'defaults to 0' do
|
106
|
+
expect(datatable.offset).to eq(0)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'when params[:start] is passed' do
|
111
|
+
let(:datatable) { ComplexDatatable.new({ start: '11' }).datatable }
|
112
|
+
|
113
|
+
it 'matches the value on view params[:start]' do
|
114
|
+
expect(datatable.offset).to eq(11)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '#page' do
|
120
|
+
let(:datatable) { ComplexDatatable.new({ start: '11' }).datatable }
|
121
|
+
|
122
|
+
it 'calculates page number from params[:start] and #per_page' do
|
123
|
+
expect(datatable.page).to eq(2)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe AjaxDatatablesRails::Datatable::SimpleOrder do
|
6
|
+
|
7
|
+
let(:parent) { ComplexDatatable.new(sample_params) }
|
8
|
+
let(:datatable) { parent.datatable }
|
9
|
+
let(:options) { ActiveSupport::HashWithIndifferentAccess.new({ 'column' => '1', 'dir' => 'desc' }) }
|
10
|
+
let(:simple_order) { AjaxDatatablesRails::Datatable::SimpleOrder.new(datatable, options) }
|
11
|
+
|
12
|
+
describe 'option methods' do
|
13
|
+
it 'sql query' do
|
14
|
+
expect(simple_order.query('firstname')).to eq('firstname DESC')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'option methods with nulls last' do
|
19
|
+
describe 'using class option' do
|
20
|
+
before { parent.nulls_last = true }
|
21
|
+
after { parent.nulls_last = false }
|
22
|
+
|
23
|
+
it 'sql query' do
|
24
|
+
skip('unsupported database adapter') if RunningSpec.oracle?
|
25
|
+
|
26
|
+
expect(simple_order.query('email')).to eq(
|
27
|
+
"email DESC #{nulls_last_sql(parent)}"
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'using column option' do
|
33
|
+
let(:parent) { DatatableOrderNullsLast.new(sample_params) }
|
34
|
+
let(:sorted_datatable) { parent.datatable }
|
35
|
+
let(:nulls_last_order) { AjaxDatatablesRails::Datatable::SimpleOrder.new(sorted_datatable, options) }
|
36
|
+
|
37
|
+
context 'with postgres database adapter' do
|
38
|
+
before { parent.db_adapter = :pg }
|
39
|
+
|
40
|
+
it 'sql query' do
|
41
|
+
expect(nulls_last_order.query('email')).to eq('email DESC NULLS LAST')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'with sqlite database adapter' do
|
46
|
+
before { parent.db_adapter = :sqlite }
|
47
|
+
|
48
|
+
it 'sql query' do
|
49
|
+
expect(nulls_last_order.query('email')).to eq('email DESC IS NULL')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'with mysql database adapter' do
|
54
|
+
before { parent.db_adapter = :mysql }
|
55
|
+
|
56
|
+
it 'sql query' do
|
57
|
+
expect(nulls_last_order.query('email')).to eq('email DESC IS NULL')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe AjaxDatatablesRails::Datatable::SimpleSearch do
|
6
|
+
|
7
|
+
let(:options) { ActiveSupport::HashWithIndifferentAccess.new({ 'value' => 'search value', 'regex' => 'true' }) }
|
8
|
+
let(:simple_search) { AjaxDatatablesRails::Datatable::SimpleSearch.new(options) }
|
9
|
+
|
10
|
+
describe 'option methods' do
|
11
|
+
it 'regexp?' do
|
12
|
+
expect(simple_search.regexp?).to be(true)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'value' do
|
16
|
+
expect(simple_search.value).to eq('search value')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|