admino 0.0.1
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/.gitignore +19 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +6 -0
- data/admino.gemspec +34 -0
- data/lib/admino.rb +9 -0
- data/lib/admino/query.rb +12 -0
- data/lib/admino/query/base.rb +94 -0
- data/lib/admino/query/base_presenter.rb +34 -0
- data/lib/admino/query/configuration.rb +54 -0
- data/lib/admino/query/dsl.rb +30 -0
- data/lib/admino/query/field.rb +52 -0
- data/lib/admino/query/group.rb +55 -0
- data/lib/admino/query/group_presenter.rb +67 -0
- data/lib/admino/table.rb +7 -0
- data/lib/admino/table/head_row.rb +59 -0
- data/lib/admino/table/presenter.rb +81 -0
- data/lib/admino/table/resource_row.rb +135 -0
- data/lib/admino/table/row.rb +65 -0
- data/lib/admino/version.rb +3 -0
- data/spec/admino/query/base_presenter_spec.rb +60 -0
- data/spec/admino/query/base_spec.rb +133 -0
- data/spec/admino/query/dsl_spec.rb +45 -0
- data/spec/admino/query/field_spec.rb +69 -0
- data/spec/admino/query/group_presenter_spec.rb +140 -0
- data/spec/admino/query/group_spec.rb +65 -0
- data/spec/admino/table/head_row_spec.rb +116 -0
- data/spec/admino/table/presenter_spec.rb +168 -0
- data/spec/admino/table/resource_row_spec.rb +206 -0
- data/spec/admino/table/row_spec.rb +71 -0
- data/spec/spec_helper.rb +82 -0
- metadata +244 -0
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Admino
|
4
|
+
module Query
|
5
|
+
describe BasePresenter do
|
6
|
+
subject(:presenter) { BasePresenter.new(query, view) }
|
7
|
+
let(:view) { RailsViewContext.new }
|
8
|
+
let(:query) do
|
9
|
+
TestQuery.new(query: { foo: 'value' })
|
10
|
+
end
|
11
|
+
let(:request_object) do
|
12
|
+
double(
|
13
|
+
'ActionDispatch::Request',
|
14
|
+
fullpath: '/?foo=bar'
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
before do
|
19
|
+
view.stub(:request).and_return(request_object)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#form' do
|
23
|
+
let(:result) do
|
24
|
+
presenter.form do |form|
|
25
|
+
form.label(:foo) <<
|
26
|
+
form.text_field(:foo)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
before do
|
31
|
+
I18n.backend.store_translations(
|
32
|
+
:en,
|
33
|
+
query: { attributes: { test_query: { foo: 'NAME' } } }
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'renders a form pointing to the current URL' do
|
38
|
+
expect(result).to have_tag(:form, with: { action: '/?foo=bar' })
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'renders a form with method GET' do
|
42
|
+
expect(result).to have_tag(:form, with: { method: 'get' })
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'renders inputs with a query[] name prefix' do
|
46
|
+
expect(result).to have_tag(:input, with: { type: 'text', name: 'query[foo]' })
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'prefills inputs with query value' do
|
50
|
+
expect(result).to have_tag(:input, with: { type: 'text', value: 'value' })
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'it generates labels in the :query I18n space' do
|
54
|
+
expect(result).to have_tag(:label, text: 'NAME')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Admino
|
4
|
+
module Query
|
5
|
+
describe Base do
|
6
|
+
subject(:query) { Base.new(params, config) }
|
7
|
+
let(:params) { {} }
|
8
|
+
let(:config) { nil }
|
9
|
+
|
10
|
+
it 'takes a request params' do
|
11
|
+
expect(query.params).to eq params
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'with an explicit config' do
|
15
|
+
let(:config) { Configuration.new }
|
16
|
+
|
17
|
+
it 'uses it' do
|
18
|
+
expect(query.config).to eq config
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'with a declared field' do
|
23
|
+
let(:config) { Configuration.new }
|
24
|
+
let(:field_config) { config.add_field(:field) }
|
25
|
+
|
26
|
+
before do
|
27
|
+
field_config
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'returns a configured Field' do
|
31
|
+
field = query.field_by_name(:field)
|
32
|
+
expect(field.config).to eq field_config
|
33
|
+
expect(field.params).to eq params
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'with a declared group' do
|
38
|
+
let(:config) { Configuration.new }
|
39
|
+
let(:group_config) { config.add_group(:group, [:one, :two]) }
|
40
|
+
|
41
|
+
before do
|
42
|
+
group_config
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'returns a configured Group' do
|
46
|
+
group = query.group_by_name(:group)
|
47
|
+
expect(group.config).to eq group_config
|
48
|
+
expect(group.params).to eq params
|
49
|
+
expect(group.i18n_key).to eq :group
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#scope' do
|
54
|
+
let(:config) { Configuration.new }
|
55
|
+
let(:result) { query.scope(starting_scope) }
|
56
|
+
let(:starting_scope) { ScopeMock.new('explicit') }
|
57
|
+
|
58
|
+
describe 'starting scope' do
|
59
|
+
context 'with an explicit scope' do
|
60
|
+
it 'uses it' do
|
61
|
+
expect(result.name).to eq 'explicit'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'with no explicit scope, but a default one configured' do
|
66
|
+
let(:result) { query.scope }
|
67
|
+
|
68
|
+
before do
|
69
|
+
config.starting_scope_callable = Proc.new { |query|
|
70
|
+
ScopeMock.new('configured').foo(query)
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
before do
|
75
|
+
result
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'calls it with self and uses it' do
|
79
|
+
expect(result.name).to eq 'configured'
|
80
|
+
expect(result.chain).to eq [:foo, [query]]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'with no scope' do
|
85
|
+
let(:result) { query.scope }
|
86
|
+
|
87
|
+
it 'raises a ArgumentError' do
|
88
|
+
expect { result }.to raise_error(ArgumentError)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'with a set of fields and groups' do
|
94
|
+
let(:field_config) { config.add_field(:field) }
|
95
|
+
let(:group_config) { config.add_group(:group, [:one, :two]) }
|
96
|
+
let(:scope_chained_with_field) { double('scope 1') }
|
97
|
+
let(:final_chain) { double('scope 2') }
|
98
|
+
|
99
|
+
before do
|
100
|
+
field_config
|
101
|
+
group_config
|
102
|
+
query
|
103
|
+
|
104
|
+
query.field_by_name(:field).
|
105
|
+
stub(:augment_scope).
|
106
|
+
with(starting_scope).
|
107
|
+
and_return(scope_chained_with_field)
|
108
|
+
|
109
|
+
query.group_by_name(:group).
|
110
|
+
stub(:augment_scope).
|
111
|
+
with(scope_chained_with_field).
|
112
|
+
and_return(final_chain)
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'chains them toghether' do
|
116
|
+
expect(result).to eq final_chain
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'with a configured ending scope' do
|
121
|
+
before do
|
122
|
+
config.ending_scope_callable = Proc.new { |query| bar(query) }
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'calls it with self at the end of the chain' do
|
126
|
+
expect(result.chain).to eq [:bar, [query]]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
@@ -0,0 +1,45 @@
|
|
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 #field declaration' do
|
10
|
+
field = config.fields.last
|
11
|
+
expect(field.name).to eq :starting_from
|
12
|
+
expect(field.coerce_to).to eq :to_date
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'allows #group declaration' do
|
16
|
+
group = config.groups.first
|
17
|
+
expect(group.name).to eq :bar
|
18
|
+
expect(group.scopes).to eq [:one, :two]
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'allows #starting_scope block declaration' do
|
22
|
+
expect(config.starting_scope_callable.call).to eq 'start'
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'allows #ending_scope block declaration' do
|
26
|
+
expect(config.ending_scope_callable.call).to eq 'end'
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with a field' do
|
30
|
+
let(:field) { double('Field', value: 'value') }
|
31
|
+
|
32
|
+
before do
|
33
|
+
instance.stub(:field_by_name).
|
34
|
+
with(:foo).
|
35
|
+
and_return(field)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'it generates a getter' do
|
39
|
+
expect(instance.foo).to eq 'value'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Admino
|
4
|
+
module Query
|
5
|
+
describe Field do
|
6
|
+
subject(:field) { Field.new(config, params) }
|
7
|
+
let(:config) { Configuration::Field.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 field' do
|
15
|
+
expect(field.value).to eq 'bar'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'else' do
|
20
|
+
it 'returns nil' do
|
21
|
+
expect(field.value).to be_nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'with coertion' do
|
26
|
+
let(:config) {
|
27
|
+
Configuration::Field.new(:foo, coerce: :to_date)
|
28
|
+
}
|
29
|
+
|
30
|
+
context 'with a possible coertion' do
|
31
|
+
let(:params) { { 'query' => { 'foo' => '2014-10-05' } } }
|
32
|
+
|
33
|
+
it 'returns the coerced param value for the field' do
|
34
|
+
expect(field.value).to be_a Date
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'with a possible coertion' do
|
39
|
+
let(:params) { { 'query' => { 'foo' => '' } } }
|
40
|
+
|
41
|
+
it 'returns nil' do
|
42
|
+
expect(field.value).to be_nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#augment_scope' do
|
49
|
+
let(:result) { field.augment_scope(scope) }
|
50
|
+
let(:scope) { ScopeMock.new('original') }
|
51
|
+
|
52
|
+
context 'if the field has a value' do
|
53
|
+
let(:params) { { 'query' => { 'foo' => 'bar' } } }
|
54
|
+
|
55
|
+
it 'returns the original scope chained with the field scope' do
|
56
|
+
expect(result.chain).to eq [:foo, ['bar']]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'else' do
|
61
|
+
it 'returns the original scope' do
|
62
|
+
expect(result).to eq scope
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Admino
|
4
|
+
module Query
|
5
|
+
describe GroupPresenter do
|
6
|
+
subject(:presenter) { GroupPresenter.new(group, view) }
|
7
|
+
let(:view) { RailsViewContext.new }
|
8
|
+
let(:group) do
|
9
|
+
double(
|
10
|
+
'Group',
|
11
|
+
query_i18n_key: :query_name,
|
12
|
+
i18n_key: :group,
|
13
|
+
param_name: :group
|
14
|
+
)
|
15
|
+
end
|
16
|
+
let(:request_object) do
|
17
|
+
double(
|
18
|
+
'ActionDispatch::Request',
|
19
|
+
query_parameters: { 'group' => 'bar' },
|
20
|
+
path: '/'
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
before do
|
25
|
+
view.stub(:request).and_return(request_object)
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#scope_link' do
|
29
|
+
before do
|
30
|
+
group.stub(:is_scope_active?).with(:foo).and_return(true)
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'active CSS class' do
|
34
|
+
it 'adds an is-active class' do
|
35
|
+
expect(presenter.scope_link(:foo)).to have_tag(:a, with: { class: 'is-active' })
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'if an :active_class option is specified' do
|
39
|
+
it 'adds it' do
|
40
|
+
expect(presenter.scope_link(:foo, active_class: 'active')).to have_tag(:a, with: { class: 'active' })
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'else' do
|
45
|
+
before do
|
46
|
+
group.stub(:is_scope_active?).with(:foo).and_return(false)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'does not add it' do
|
50
|
+
expect(presenter.scope_link(:foo)).not_to have_tag(:a, with: { class: 'is-active' })
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'label' do
|
56
|
+
before do
|
57
|
+
presenter.stub(:scope_name).with(:foo).and_return('scope_name')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'uses #scope_name method' do
|
61
|
+
expect(presenter.scope_link(:foo)).to have_tag(:a, text: 'scope_name')
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'if a second parameter is supplied' do
|
65
|
+
it 'uses it' do
|
66
|
+
expect(presenter.scope_link(:foo, 'test')).to have_tag(:a, text: 'test')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'URL' do
|
72
|
+
before do
|
73
|
+
presenter.stub(:scope_path).with(:foo).and_return('URL')
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'uses #scope_path method' do
|
77
|
+
expect(presenter.scope_link(:foo)).to have_tag(:a, href: 'URL')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '#scope_params' do
|
83
|
+
context 'if scope is nil' do
|
84
|
+
it 'deletes the group param' do
|
85
|
+
expect(presenter.scope_params(nil)).not_to have_key 'group'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'else' do
|
90
|
+
it 'deletes the group param' do
|
91
|
+
expect(presenter.scope_params(:bar)[:group]).to eq 'bar'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#name' do
|
97
|
+
context do
|
98
|
+
before do
|
99
|
+
I18n.backend.store_translations(
|
100
|
+
:en,
|
101
|
+
query: { groups: { query_name: { group: { name: 'NAME' } } } }
|
102
|
+
)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'returns a I18n translatable name for the group' do
|
106
|
+
expect(presenter.name).to eq 'NAME'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'if no translation is available' do
|
111
|
+
it 'falls back to a titleized version of the group name' do
|
112
|
+
expect(presenter.name).to eq 'Group'
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#scope_name' do
|
118
|
+
context do
|
119
|
+
before do
|
120
|
+
I18n.backend.store_translations(
|
121
|
+
:en,
|
122
|
+
query: { groups: { query_name: { group: { scopes: { bar: 'NAME' } } } } }
|
123
|
+
)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'returns a I18n translatable name for the scope' do
|
127
|
+
expect(presenter.scope_name(:bar)).to eq 'NAME'
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'if no translation is available' do
|
132
|
+
it 'falls back to a titleized version of the scope name' do
|
133
|
+
expect(presenter.scope_name(:bar)).to eq 'Bar'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|