gestart-admino 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yml +29 -0
- data/.gitignore +20 -0
- data/.tool-versions +1 -0
- data/CHANGELOG.md +91 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +716 -0
- data/Rakefile +6 -0
- data/gestart-admino.gemspec +36 -0
- data/lib/admino/action_view_extension.rb +35 -0
- data/lib/admino/query/base.rb +124 -0
- data/lib/admino/query/base_presenter.rb +27 -0
- data/lib/admino/query/builder.rb +24 -0
- data/lib/admino/query/configuration.rb +100 -0
- data/lib/admino/query/dsl.rb +38 -0
- data/lib/admino/query/filter_group.rb +73 -0
- data/lib/admino/query/filter_group_presenter.rb +85 -0
- data/lib/admino/query/scope_presenter.rb +17 -0
- data/lib/admino/query/search_field.rb +43 -0
- data/lib/admino/query/sorting.rb +74 -0
- data/lib/admino/query/sorting_presenter.rb +60 -0
- data/lib/admino/query.rb +15 -0
- data/lib/admino/table/head_row.rb +86 -0
- data/lib/admino/table/presenter.rb +122 -0
- data/lib/admino/table/resource_row.rb +145 -0
- data/lib/admino/table/row.rb +56 -0
- data/lib/admino/table.rb +7 -0
- data/lib/admino/version.rb +3 -0
- data/lib/admino.rb +14 -0
- data/lib/gestart-admino.rb +1 -0
- data/spec/admino/integration_spec.rb +63 -0
- data/spec/admino/query/base_presenter_spec.rb +59 -0
- data/spec/admino/query/base_spec.rb +192 -0
- data/spec/admino/query/dsl_spec.rb +52 -0
- data/spec/admino/query/filter_group_presenter_spec.rb +182 -0
- data/spec/admino/query/filter_group_spec.rb +133 -0
- data/spec/admino/query/search_field_spec.rb +66 -0
- data/spec/admino/query/sorting_presenter_spec.rb +206 -0
- data/spec/admino/query/sorting_spec.rb +137 -0
- data/spec/admino/table/head_row_spec.rb +158 -0
- data/spec/admino/table/presenter_spec.rb +180 -0
- data/spec/admino/table/resource_row_spec.rb +225 -0
- data/spec/admino/table/row_spec.rb +76 -0
- data/spec/spec_helper.rb +93 -0
- metadata +267 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Admino
|
|
4
|
+
module Query
|
|
5
|
+
describe Base do
|
|
6
|
+
subject(:query) { Base.new(params, context, config) }
|
|
7
|
+
let(:params) { {} }
|
|
8
|
+
let(:context) { {} }
|
|
9
|
+
let(:config) { nil }
|
|
10
|
+
|
|
11
|
+
it 'takes a request params' do
|
|
12
|
+
expect(query.params).to eq params
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
context 'with an explicit config' do
|
|
16
|
+
let(:config) { Configuration.new }
|
|
17
|
+
|
|
18
|
+
it 'uses it' do
|
|
19
|
+
expect(query.config).to eq config
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context 'with a declared search_field' do
|
|
24
|
+
let(:config) { Configuration.new }
|
|
25
|
+
let(:search_field_config) { config.add_search_field(:search_field) }
|
|
26
|
+
|
|
27
|
+
before do
|
|
28
|
+
search_field_config
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'returns a configured SearchField' do
|
|
32
|
+
search_field = query.search_field_by_name(:search_field)
|
|
33
|
+
expect(search_field.config).to eq search_field_config
|
|
34
|
+
expect(search_field.params).to eq params
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context 'with a declared filter_group' do
|
|
39
|
+
let(:config) { Configuration.new }
|
|
40
|
+
let(:filter_group_config) { config.add_filter_group(:filter_group, [:one, :two]) }
|
|
41
|
+
|
|
42
|
+
before do
|
|
43
|
+
filter_group_config
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'returns a configured FilterGroup' do
|
|
47
|
+
filter_group = query.filter_group_by_name(:filter_group)
|
|
48
|
+
expect(filter_group.config).to eq filter_group_config
|
|
49
|
+
expect(filter_group.params).to eq params
|
|
50
|
+
expect(filter_group.i18n_key).to eq :filter_group
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context 'with a declared sorting' do
|
|
55
|
+
let(:config) { Configuration.new }
|
|
56
|
+
let(:sorting_config) do
|
|
57
|
+
config.add_sorting_scopes([:by_title, :by_date])
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
before do
|
|
61
|
+
sorting_config
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'returns a configured Sorting' do
|
|
65
|
+
sorting = query.sorting
|
|
66
|
+
expect(sorting.config).to eq sorting_config
|
|
67
|
+
expect(sorting.params).to eq params
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe '#scope' do
|
|
72
|
+
let(:config) { Configuration.new }
|
|
73
|
+
let(:result) { query.scope(starting_scope) }
|
|
74
|
+
let(:starting_scope) { ScopeMock.new('explicit') }
|
|
75
|
+
|
|
76
|
+
describe 'starting scope' do
|
|
77
|
+
context 'with an explicit scope' do
|
|
78
|
+
it 'uses it' do
|
|
79
|
+
expect(result.name).to eq 'explicit'
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context 'with no explicit scope, but a default one configured' do
|
|
84
|
+
let(:result) { query.scope }
|
|
85
|
+
|
|
86
|
+
before do
|
|
87
|
+
config.starting_scope_callable = Proc.new { |query|
|
|
88
|
+
ScopeMock.new('configured').foo(query)
|
|
89
|
+
}
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
before do
|
|
93
|
+
result
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'calls it with self and uses it' do
|
|
97
|
+
expect(result.name).to eq 'configured'
|
|
98
|
+
expect(result.chain).to eq [:foo, [query]]
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context 'with no scope' do
|
|
103
|
+
let(:result) { query.scope }
|
|
104
|
+
|
|
105
|
+
it 'raises a ArgumentError' do
|
|
106
|
+
expect { result }.to raise_error(ArgumentError)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
context 'with a set of search_fields, filter_groups and sortings' do
|
|
112
|
+
let(:search_field_config) { config.add_search_field(:search_field) }
|
|
113
|
+
let(:filter_group_config) { config.add_filter_group(:filter_group, [:one, :two]) }
|
|
114
|
+
let(:sorting_config) { config.add_sorting_scopes([:title, :year]) }
|
|
115
|
+
|
|
116
|
+
let(:params) do
|
|
117
|
+
{
|
|
118
|
+
query: {
|
|
119
|
+
search_field: "foo",
|
|
120
|
+
filter_group: "one",
|
|
121
|
+
},
|
|
122
|
+
sorting: "title",
|
|
123
|
+
sort_order: "desc"
|
|
124
|
+
}
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
before do
|
|
128
|
+
search_field_config
|
|
129
|
+
filter_group_config
|
|
130
|
+
sorting_config
|
|
131
|
+
query
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
context 'if query object does not respond to scopes' do
|
|
135
|
+
it 'chains from starting scope' do
|
|
136
|
+
expect(result.chain).to eq [
|
|
137
|
+
:search_field, ["foo"],
|
|
138
|
+
:one, [],
|
|
139
|
+
:title, [:desc]
|
|
140
|
+
]
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
context 'else' do
|
|
145
|
+
let(:query_klass) do
|
|
146
|
+
Class.new(Base) do
|
|
147
|
+
def self.model_name
|
|
148
|
+
ActiveModel::Name.new(self, nil, "temp")
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def search_field_scope(scope, foo)
|
|
152
|
+
scope.my_search_field(foo)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def one_scope(scope)
|
|
156
|
+
scope.my_one
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def title_scope(scope, order)
|
|
160
|
+
scope.my_title(order)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
subject(:query) do
|
|
166
|
+
query_klass.new(params, context, config)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it 'chains from starting scope calling query object methods' do
|
|
170
|
+
expect(result.chain).to eq [
|
|
171
|
+
:my_search_field, ["foo"],
|
|
172
|
+
:my_one, [],
|
|
173
|
+
:my_title, [:desc]
|
|
174
|
+
]
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
context 'with a configured ending scope' do
|
|
180
|
+
before do
|
|
181
|
+
config.ending_scope_callable = Proc.new { |query| bar(query) }
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it 'calls it with self at the end of the chain' do
|
|
185
|
+
expect(result.chain).to eq [:bar, [query]]
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Admino
|
|
4
|
+
module Query
|
|
5
|
+
describe Dsl do
|
|
6
|
+
let(:config) { TestQuery.config }
|
|
7
|
+
let(:instance) { TestQuery.new }
|
|
8
|
+
|
|
9
|
+
it 'allows #search_field declaration' do
|
|
10
|
+
search_field = config.search_fields.last
|
|
11
|
+
expect(search_field.name).to eq :starting_from
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'allows #filter_by declaration' do
|
|
15
|
+
filter_group = config.filter_groups.first
|
|
16
|
+
expect(filter_group.name).to eq :bar
|
|
17
|
+
expect(filter_group.scopes).to eq [:one, :two]
|
|
18
|
+
expect(filter_group.include_empty_scope?).to be_truthy
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'allows #sortings declaration' do
|
|
22
|
+
sorting = config.sorting
|
|
23
|
+
expect(sorting.scopes).to eq [:by_title, :by_date]
|
|
24
|
+
expect(sorting.default_scope).to eq :by_title
|
|
25
|
+
expect(sorting.default_direction).to eq :desc
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'allows #starting_scope block declaration' do
|
|
29
|
+
expect(config.starting_scope_callable.call).to eq 'start'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'allows #ending_scope block declaration' do
|
|
33
|
+
expect(config.ending_scope_callable.call).to eq 'end'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context 'with a search_field' do
|
|
37
|
+
let(:search_field) { double('SearchField', value: 'value') }
|
|
38
|
+
|
|
39
|
+
before do
|
|
40
|
+
allow(instance).to receive(:search_field_by_name).
|
|
41
|
+
with(:foo).
|
|
42
|
+
and_return(search_field)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'it generates a getter' do
|
|
46
|
+
expect(instance.foo).to eq 'value'
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'active_support/hash_with_indifferent_access'
|
|
3
|
+
|
|
4
|
+
module Admino
|
|
5
|
+
module Query
|
|
6
|
+
describe FilterGroupPresenter do
|
|
7
|
+
subject(:presenter) { FilterGroupPresenter.new(filter_group, view) }
|
|
8
|
+
let(:view) { RailsViewContext.new }
|
|
9
|
+
let(:filter_group) do
|
|
10
|
+
double(
|
|
11
|
+
'FilterGroup',
|
|
12
|
+
query_i18n_key: :query_name,
|
|
13
|
+
i18n_key: :filter_group,
|
|
14
|
+
param_name: :filter_group
|
|
15
|
+
)
|
|
16
|
+
end
|
|
17
|
+
let(:request_object) do
|
|
18
|
+
double(
|
|
19
|
+
'ActionDispatch::Request',
|
|
20
|
+
query_parameters: ActiveSupport::HashWithIndifferentAccess.new(
|
|
21
|
+
params
|
|
22
|
+
),
|
|
23
|
+
path: '/'
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
let(:params) do
|
|
27
|
+
{ 'query' => { 'field' => 'value', 'filter_group' => 'bar' } }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
before do
|
|
31
|
+
allow(view).to receive(:request).and_return(request_object)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe '#scope_link' do
|
|
35
|
+
subject { presenter.scope_link(:foo) }
|
|
36
|
+
let(:scope_active) { false }
|
|
37
|
+
|
|
38
|
+
before do
|
|
39
|
+
allow(filter_group).to receive(:is_scope_active?).
|
|
40
|
+
with(:foo).and_return(scope_active)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context 'active CSS class' do
|
|
44
|
+
let(:scope_active) { true }
|
|
45
|
+
|
|
46
|
+
it 'adds an is-active class' do
|
|
47
|
+
is_expected.to have_tag(:a, with: { class: 'is-active' })
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context 'if an :active_class option is specified' do
|
|
51
|
+
subject { presenter.scope_link(:foo, active_class: 'active') }
|
|
52
|
+
|
|
53
|
+
it 'adds it' do
|
|
54
|
+
is_expected.to have_tag(:a, with: { class: 'active' })
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context 'else' do
|
|
60
|
+
it 'does not add it' do
|
|
61
|
+
is_expected.not_to have_tag(:a, with: { class: 'is-active' })
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
context 'label' do
|
|
66
|
+
before do
|
|
67
|
+
allow(presenter).to receive(:scope_name).with(:foo).and_return('scope_name')
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'uses #scope_name method' do
|
|
71
|
+
is_expected.to have_tag(:a, text: 'scope_name')
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
context 'if a second parameter is supplied' do
|
|
75
|
+
subject { presenter.scope_link(:foo, 'test', active_class: 'active') }
|
|
76
|
+
|
|
77
|
+
it 'uses it' do
|
|
78
|
+
is_expected.to have_tag(:a, text: 'test')
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context 'URL' do
|
|
84
|
+
before do
|
|
85
|
+
allow(presenter).to receive(:scope_path).with(:foo).and_return('URL')
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'uses #scope_path method' do
|
|
89
|
+
is_expected.to have_tag(:a, href: 'URL')
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
describe '#scope_params' do
|
|
95
|
+
let(:scope_active) { false }
|
|
96
|
+
subject { presenter.scope_params(:foo) }
|
|
97
|
+
|
|
98
|
+
before do
|
|
99
|
+
allow(filter_group).to receive(:is_scope_active?).with(:foo).and_return(scope_active)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context 'if scope is active' do
|
|
103
|
+
let(:scope_active) { true }
|
|
104
|
+
|
|
105
|
+
it 'deletes the filter_group param' do
|
|
106
|
+
expect(subject[:query]).not_to have_key 'filter_group'
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'keeps the request parameters intact' do
|
|
110
|
+
presenter.scope_params(:foo)
|
|
111
|
+
expect(request_object.query_parameters[:query][:filter_group]).to be_present
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
context 'the resulting query hash becomes empty' do
|
|
115
|
+
let(:params) do
|
|
116
|
+
{ 'query' => { 'filter_group' => 'bar' } }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it 'removes the param altoghether' do
|
|
120
|
+
expect(subject).not_to have_key 'query'
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
context 'else' do
|
|
126
|
+
let(:scope_active) { false }
|
|
127
|
+
|
|
128
|
+
it 'is set as filter group value' do
|
|
129
|
+
expect(subject[:query][:filter_group]).to eq 'foo'
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it 'preserves the other params' do
|
|
134
|
+
expect(subject[:query][:field]).to eq 'value'
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
describe '#name' do
|
|
139
|
+
context do
|
|
140
|
+
before do
|
|
141
|
+
I18n.backend.store_translations(
|
|
142
|
+
:en,
|
|
143
|
+
query: { filter_groups: { query_name: { filter_group: { name: 'NAME' } } } }
|
|
144
|
+
)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it 'returns a I18n translatable name for the filter_group' do
|
|
148
|
+
expect(presenter.name).to eq 'NAME'
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
context 'if no translation is available' do
|
|
153
|
+
it 'falls back to a titleized version of the filter_group name' do
|
|
154
|
+
expect(presenter.name).to eq 'Filter group'
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
describe '#scope_name' do
|
|
160
|
+
context do
|
|
161
|
+
before do
|
|
162
|
+
I18n.backend.store_translations(
|
|
163
|
+
:en,
|
|
164
|
+
query: { filter_groups: { query_name: { filter_group: { scopes: { bar: 'NAME' } } } } }
|
|
165
|
+
)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it 'returns a I18n translatable name for the scope' do
|
|
169
|
+
expect(presenter.scope_name(:bar)).to eq 'NAME'
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
context 'if no translation is available' do
|
|
174
|
+
it 'falls back to a titleized version of the scope name' do
|
|
175
|
+
expect(presenter.scope_name(:bar)).to eq 'Bar'
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Admino
|
|
4
|
+
module Query
|
|
5
|
+
describe FilterGroup do
|
|
6
|
+
subject(:filter_group) { FilterGroup.new(config, params) }
|
|
7
|
+
let(:config) do
|
|
8
|
+
Configuration::FilterGroup.new(:foo, [:bar, :other], options)
|
|
9
|
+
end
|
|
10
|
+
let(:options) { {} }
|
|
11
|
+
let(:params) { {} }
|
|
12
|
+
|
|
13
|
+
describe '#active_scope' do
|
|
14
|
+
context 'with no param' do
|
|
15
|
+
let(:params) { {} }
|
|
16
|
+
|
|
17
|
+
it 'returns nil' do
|
|
18
|
+
expect(filter_group.active_scope).to be_nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context 'if include_empty_scope is true' do
|
|
22
|
+
let(:options) { { include_empty_scope: true } }
|
|
23
|
+
|
|
24
|
+
it 'returns the :empty scope' do
|
|
25
|
+
expect(filter_group.active_scope).to eq :empty
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'if default scope is set' do
|
|
29
|
+
let(:config) do
|
|
30
|
+
Configuration::FilterGroup.new(
|
|
31
|
+
:foo,
|
|
32
|
+
[:bar],
|
|
33
|
+
include_empty_scope: true,
|
|
34
|
+
default: :bar
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'returns it' do
|
|
39
|
+
expect(filter_group.active_scope).to eq :bar
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context 'with "empty" param' do
|
|
46
|
+
let(:params) { { 'query' => { 'foo' => 'empty' } } }
|
|
47
|
+
|
|
48
|
+
context 'if include_empty_scope is true' do
|
|
49
|
+
let(:options) { { include_empty_scope: true, default: :bar } }
|
|
50
|
+
|
|
51
|
+
it 'returns the :empty scope' do
|
|
52
|
+
expect(filter_group.active_scope).to eq :empty
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context 'with an invalid value' do
|
|
58
|
+
let(:params) { { 'query' => { 'foo' => 'qux' } } }
|
|
59
|
+
|
|
60
|
+
it 'returns nil' do
|
|
61
|
+
expect(filter_group.active_scope).to be_nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
context 'if include_empty_scope is true' do
|
|
65
|
+
let(:options) { { include_empty_scope: true, default: :bar } }
|
|
66
|
+
|
|
67
|
+
it 'returns nil' do
|
|
68
|
+
expect(filter_group.active_scope).to be_nil
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context 'with a valid value' do
|
|
74
|
+
let(:params) { { 'query' => { 'foo' => 'bar' } } }
|
|
75
|
+
|
|
76
|
+
it 'returns the scope name' do
|
|
77
|
+
expect(filter_group.active_scope).to eq :bar
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
describe '#augment_scope' do
|
|
83
|
+
let(:result) { filter_group.augment_scope(scope) }
|
|
84
|
+
let(:scope) { ScopeMock.new('original') }
|
|
85
|
+
|
|
86
|
+
context 'if the search_field has a value' do
|
|
87
|
+
let(:params) { { 'query' => { 'foo' => 'bar' } } }
|
|
88
|
+
|
|
89
|
+
it 'returns the original scope chained with the filter_group scope' do
|
|
90
|
+
expect(result.chain).to eq [:bar, []]
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
context 'else' do
|
|
95
|
+
it 'returns the original scope' do
|
|
96
|
+
expect(result).to eq scope
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
context 'if include_empty_scope is true' do
|
|
100
|
+
let(:options) { { include_empty_scope: true } }
|
|
101
|
+
|
|
102
|
+
it 'returns the original scope' do
|
|
103
|
+
expect(result).to eq scope
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
describe '#is_scope_active?' do
|
|
110
|
+
let(:params) { { 'query' => { 'foo' => 'bar' } } }
|
|
111
|
+
|
|
112
|
+
it 'returns true if the provided scope is the one currently active' do
|
|
113
|
+
expect(filter_group.is_scope_active?('bar')).to be_truthy
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
describe '#scopes' do
|
|
118
|
+
subject { filter_group.scopes }
|
|
119
|
+
|
|
120
|
+
context 'if include_empty_scope is true' do
|
|
121
|
+
let(:options) { { include_empty_scope: true } }
|
|
122
|
+
|
|
123
|
+
it { is_expected.to eq [:empty, :bar, :other] }
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
context 'else' do
|
|
127
|
+
it { is_expected.to eq [:bar, :other] }
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Admino
|
|
4
|
+
module Query
|
|
5
|
+
describe SearchField do
|
|
6
|
+
subject(:search_field) { SearchField.new(config, params) }
|
|
7
|
+
let(:config) { Configuration::SearchField.new(:foo) }
|
|
8
|
+
let(:params) { {} }
|
|
9
|
+
|
|
10
|
+
describe '#value' do
|
|
11
|
+
context 'with a value' do
|
|
12
|
+
let(:params) { { 'query' => { 'foo' => 'bar' } } }
|
|
13
|
+
|
|
14
|
+
it 'returns the param value for the search_field' do
|
|
15
|
+
expect(search_field.value).to eq 'bar'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
context 'else' do
|
|
20
|
+
it 'returns nil' do
|
|
21
|
+
expect(search_field.value).to be_nil
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'with a default value' do
|
|
25
|
+
let(:config) {
|
|
26
|
+
Configuration::SearchField.new(:foo, default: 'foo')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
it 'returns it' do
|
|
30
|
+
expect(search_field.value).to eq 'foo'
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context 'with a date-shaped value' do
|
|
36
|
+
let(:params) { { 'query' => { 'foo' => '2014-10-05' } } }
|
|
37
|
+
|
|
38
|
+
it 'returns it untouched, as a String' do
|
|
39
|
+
expect(search_field.value).to eq '2014-10-05'
|
|
40
|
+
expect(search_field.value).to be_a String
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe '#augment_scope' do
|
|
46
|
+
let(:result) { search_field.augment_scope(scope) }
|
|
47
|
+
let(:scope) { ScopeMock.new('original') }
|
|
48
|
+
|
|
49
|
+
context 'if the search_field has a value' do
|
|
50
|
+
let(:params) { { 'query' => { 'foo' => 'bar' } } }
|
|
51
|
+
|
|
52
|
+
it 'returns the original scope chained with the search_field scope' do
|
|
53
|
+
expect(result.chain).to eq [:foo, ['bar']]
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context 'else' do
|
|
58
|
+
it 'returns the original scope' do
|
|
59
|
+
expect(result).to eq scope
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|