rear 0.2.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 +15 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +20 -0
- data/LICENSE +19 -0
- data/README.md +101 -0
- data/Rakefile +79 -0
- data/assets/api.js +307 -0
- data/assets/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css +8 -0
- data/assets/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js +26 -0
- data/assets/bootstrap/css/bootstrap-responsive.min.css +9 -0
- data/assets/bootstrap/css/bootstrap.min.css +9 -0
- data/assets/bootstrap/img/glyphicons-halflings-white.png +0 -0
- data/assets/bootstrap/img/glyphicons-halflings.png +0 -0
- data/assets/bootstrap/js/bootstrap.min.js +6 -0
- data/assets/jquery.js +5 -0
- data/assets/noty/jquery.noty.js +520 -0
- data/assets/noty/layouts/top.js +34 -0
- data/assets/noty/layouts/topRight.js +43 -0
- data/assets/noty/promise.js +432 -0
- data/assets/noty/themes/default.js +156 -0
- data/assets/select2-bootstrap.css +86 -0
- data/assets/select2/select2-spinner.gif +0 -0
- data/assets/select2/select2.css +652 -0
- data/assets/select2/select2.min.js +22 -0
- data/assets/select2/select2.png +0 -0
- data/assets/select2/select2x2.png +0 -0
- data/assets/ui.css +75 -0
- data/assets/xhr.js +4 -0
- data/bin/rear +65 -0
- data/docs/Assocs.md +100 -0
- data/docs/Columns.md +404 -0
- data/docs/Deploy.md +62 -0
- data/docs/FileManager.md +75 -0
- data/docs/Filters.md +341 -0
- data/docs/Setup.md +201 -0
- data/lib/rear.rb +13 -0
- data/lib/rear/actions.rb +98 -0
- data/lib/rear/constants.rb +61 -0
- data/lib/rear/controller_setup.rb +249 -0
- data/lib/rear/helpers.rb +17 -0
- data/lib/rear/helpers/class.rb +46 -0
- data/lib/rear/helpers/columns.rb +68 -0
- data/lib/rear/helpers/filters.rb +147 -0
- data/lib/rear/helpers/generic.rb +73 -0
- data/lib/rear/helpers/order.rb +47 -0
- data/lib/rear/helpers/pager.rb +35 -0
- data/lib/rear/helpers/render.rb +37 -0
- data/lib/rear/home_controller.rb +10 -0
- data/lib/rear/input.rb +341 -0
- data/lib/rear/orm.rb +73 -0
- data/lib/rear/rear.rb +74 -0
- data/lib/rear/setup.rb +9 -0
- data/lib/rear/setup/associations.rb +33 -0
- data/lib/rear/setup/columns.rb +109 -0
- data/lib/rear/setup/filters.rb +314 -0
- data/lib/rear/setup/generic.rb +59 -0
- data/lib/rear/setup/menu.rb +39 -0
- data/lib/rear/templates/editor/ace.slim +7 -0
- data/lib/rear/templates/editor/assocs.slim +10 -0
- data/lib/rear/templates/editor/boolean.slim +5 -0
- data/lib/rear/templates/editor/bulk_edit.slim +75 -0
- data/lib/rear/templates/editor/checkbox.slim +5 -0
- data/lib/rear/templates/editor/ckeditor.slim +7 -0
- data/lib/rear/templates/editor/date.slim +9 -0
- data/lib/rear/templates/editor/datetime.slim +9 -0
- data/lib/rear/templates/editor/layout.slim +103 -0
- data/lib/rear/templates/editor/password.slim +1 -0
- data/lib/rear/templates/editor/radio.slim +5 -0
- data/lib/rear/templates/editor/select.slim +3 -0
- data/lib/rear/templates/editor/string.slim +1 -0
- data/lib/rear/templates/editor/text.slim +1 -0
- data/lib/rear/templates/editor/time.slim +9 -0
- data/lib/rear/templates/error.slim +36 -0
- data/lib/rear/templates/filters/boolean.slim +10 -0
- data/lib/rear/templates/filters/checkbox.slim +15 -0
- data/lib/rear/templates/filters/date.slim +10 -0
- data/lib/rear/templates/filters/datetime.slim +10 -0
- data/lib/rear/templates/filters/layout.slim +26 -0
- data/lib/rear/templates/filters/radio.slim +14 -0
- data/lib/rear/templates/filters/select.slim +9 -0
- data/lib/rear/templates/filters/string.slim +3 -0
- data/lib/rear/templates/filters/text.slim +3 -0
- data/lib/rear/templates/filters/time.slim +10 -0
- data/lib/rear/templates/home.slim +0 -0
- data/lib/rear/templates/layout.slim +78 -0
- data/lib/rear/templates/pager.slim +22 -0
- data/lib/rear/templates/pane/ace.slim +2 -0
- data/lib/rear/templates/pane/assocs.slim +62 -0
- data/lib/rear/templates/pane/boolean.slim +2 -0
- data/lib/rear/templates/pane/checkbox.slim +5 -0
- data/lib/rear/templates/pane/ckeditor.slim +2 -0
- data/lib/rear/templates/pane/date.slim +2 -0
- data/lib/rear/templates/pane/datetime.slim +2 -0
- data/lib/rear/templates/pane/layout.slim +111 -0
- data/lib/rear/templates/pane/password.slim +2 -0
- data/lib/rear/templates/pane/quickview.slim +21 -0
- data/lib/rear/templates/pane/radio.slim +5 -0
- data/lib/rear/templates/pane/select.slim +5 -0
- data/lib/rear/templates/pane/string.slim +2 -0
- data/lib/rear/templates/pane/text.slim +2 -0
- data/lib/rear/templates/pane/time.slim +2 -0
- data/lib/rear/utils.rb +288 -0
- data/rear.gemspec +27 -0
- data/test/helpers.rb +33 -0
- data/test/models/ar.rb +52 -0
- data/test/models/dm.rb +53 -0
- data/test/models/sq.rb +58 -0
- data/test/setup.rb +4 -0
- data/test/templates/adhoc/book/editor/name.slim +1 -0
- data/test/templates/adhoc/book/editor/string.slim +1 -0
- data/test/templates/adhoc/book/pane/name.slim +1 -0
- data/test/templates/adhoc/book/pane/string.slim +1 -0
- data/test/templates/shared/shared-templates/editor/string.slim +1 -0
- data/test/templates/shared/shared-templates/pane/string.slim +1 -0
- data/test/test__assocs.rb +249 -0
- data/test/test__columns.rb +269 -0
- data/test/test__crud.rb +81 -0
- data/test/test__custom_templates.rb +147 -0
- data/test/test__filters.rb +228 -0
- metadata +220 -0
data/test/models/sq.rb
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
connection = Sequel.sqlite
|
|
2
|
+
Sequel::Model.db = connection
|
|
3
|
+
|
|
4
|
+
connection.create_table :books_genres do |t|
|
|
5
|
+
t.integer :book_id
|
|
6
|
+
t.integer :genre_id
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
connection.create_table :genres do |t|
|
|
10
|
+
primary_key :id
|
|
11
|
+
t.string :name
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
connection.create_table :authors do |t|
|
|
15
|
+
primary_key :id
|
|
16
|
+
t.string :name
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
connection.create_table :books do |t|
|
|
20
|
+
primary_key :id
|
|
21
|
+
t.integer :author_id
|
|
22
|
+
t.string :name
|
|
23
|
+
t.text :about
|
|
24
|
+
t.string :cover
|
|
25
|
+
t.string :colors
|
|
26
|
+
t.date :created_at
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
connection.create_table :states do |t|
|
|
30
|
+
primary_key :id
|
|
31
|
+
t.string :name
|
|
32
|
+
t.string :code
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
connection.create_table :cities do |t|
|
|
36
|
+
primary_key :id
|
|
37
|
+
t.string :name
|
|
38
|
+
t.string :state_code
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class Author < Sequel::Model
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class Genre < Sequel::Model
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class Book < Sequel::Model
|
|
48
|
+
many_to_one :author
|
|
49
|
+
many_to_many :genres
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class State < Sequel::Model
|
|
53
|
+
one_to_many :cities, key: :state_code, primary_key: :code
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class City < Sequel::Model
|
|
57
|
+
many_to_one :state, key: :state_code, primary_key: :code
|
|
58
|
+
end
|
data/test/setup.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
input.adhoc-given-template value=value
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
input.adhoc-default-template value=value
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
p.adhoc-given-template = value
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
p.adhoc-default-template = value
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
input.custom-shared-template value=value
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
p.custom-shared-template = value
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
module RearTest__Assocs
|
|
2
|
+
class Books < E
|
|
3
|
+
include Rear
|
|
4
|
+
model Book
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class Authors < E
|
|
8
|
+
include Rear
|
|
9
|
+
model Author
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class Genres < E
|
|
13
|
+
include Rear
|
|
14
|
+
model Genre
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
Spec.new Authors do
|
|
18
|
+
Books.mount
|
|
19
|
+
|
|
20
|
+
book, book_id = new_book()
|
|
21
|
+
args = [
|
|
22
|
+
:reverse_assoc,
|
|
23
|
+
RearTest__Assocs::Books,
|
|
24
|
+
:belongs_to,
|
|
25
|
+
:author,
|
|
26
|
+
book_id
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
Ensure 'no author attached' do
|
|
30
|
+
get app.route(*args, :attached)
|
|
31
|
+
is(last_response).ok?
|
|
32
|
+
are(extract_elements).empty?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
author = Author.create(name: rand(2**64).to_s)
|
|
36
|
+
|
|
37
|
+
Should 'attach given author' do
|
|
38
|
+
post app.route(*args, target_item_id: author.id.to_s)
|
|
39
|
+
is(last_response).ok?
|
|
40
|
+
|
|
41
|
+
Ensure 'model updated' do
|
|
42
|
+
book.reload
|
|
43
|
+
expect(book.author_id) == author.id
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
Ensure 'frontend reflects updates' do
|
|
47
|
+
get app.route(*args, :attached)
|
|
48
|
+
is(last_response).ok?
|
|
49
|
+
expect { extract_elements.children }.any? do |c|
|
|
50
|
+
c.text == author.name.to_s
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
Should 'detach given author' do
|
|
56
|
+
delete app.route(*args)
|
|
57
|
+
|
|
58
|
+
Ensure 'model updated' do
|
|
59
|
+
book.reload
|
|
60
|
+
refute(book.author_id) == author.id
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
Ensure 'frontend reflects updates' do
|
|
64
|
+
get app.route(*args, :attached)
|
|
65
|
+
is(last_response).ok?
|
|
66
|
+
are(extract_elements).empty?
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
Spec.new Genres do
|
|
73
|
+
|
|
74
|
+
book, book_id = new_book()
|
|
75
|
+
args = [
|
|
76
|
+
:reverse_assoc,
|
|
77
|
+
RearTest__Assocs::Books,
|
|
78
|
+
:has_many,
|
|
79
|
+
:genres,
|
|
80
|
+
book_id
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
Ensure 'no genres attached' do
|
|
84
|
+
get app.route(*args, :attached)
|
|
85
|
+
is(last_response).ok?
|
|
86
|
+
are(extract_elements).empty?
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
genre = Genre.create(name: rand(2**64).to_s)
|
|
90
|
+
|
|
91
|
+
Should 'attach given genre' do
|
|
92
|
+
post app.route(*args, target_item_id: genre.id.to_s)
|
|
93
|
+
|
|
94
|
+
Ensure 'model updated' do
|
|
95
|
+
book.reload
|
|
96
|
+
does(book.genres).include? genre
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
Ensure 'frontend reflects updates' do
|
|
100
|
+
get app.route(*args, :attached)
|
|
101
|
+
is(last_response).ok?
|
|
102
|
+
expect { extract_elements.children }.any? do |c|
|
|
103
|
+
c.text == genre.name.to_s
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
Should 'detach given genre' do
|
|
110
|
+
delete app.route(*args, target_item_id: genre.id.to_s)
|
|
111
|
+
|
|
112
|
+
Ensure 'model updated' do
|
|
113
|
+
book.reload
|
|
114
|
+
refute(book.genres).include? genre
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
Ensure 'frontend reflects updates' do
|
|
118
|
+
get app.route(*args, :attached)
|
|
119
|
+
is(last_response).ok?
|
|
120
|
+
are(extract_elements).empty?
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
class CustomKeys
|
|
126
|
+
class Child < E
|
|
127
|
+
include Rear
|
|
128
|
+
model City
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
class Parent < E
|
|
132
|
+
include Rear
|
|
133
|
+
model State
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
Spec.new CustomKeys::Parent do
|
|
138
|
+
CustomKeys::Child.mount
|
|
139
|
+
|
|
140
|
+
state = State.create(name: 'California', code: 'CA')
|
|
141
|
+
city = City.create
|
|
142
|
+
args = [
|
|
143
|
+
:reverse_assoc,
|
|
144
|
+
CustomKeys::Child,
|
|
145
|
+
:belongs_to,
|
|
146
|
+
:state,
|
|
147
|
+
city.id
|
|
148
|
+
]
|
|
149
|
+
|
|
150
|
+
Should 'set state to CA' do
|
|
151
|
+
post app.route(*args, target_item_id: state.id.to_s)
|
|
152
|
+
|
|
153
|
+
Ensure 'city updated' do
|
|
154
|
+
city.reload
|
|
155
|
+
expect(city.state_code) == state.code
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
Ensure 'frontend reflects updates' do
|
|
159
|
+
get app.route(*args, :attached)
|
|
160
|
+
is(last_response).ok?
|
|
161
|
+
expect { extract_elements.children }.any? do |c|
|
|
162
|
+
c.text == state.name
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
Spec.new CustomKeys::Child do
|
|
170
|
+
|
|
171
|
+
state = State.create(name: 'New York', code: 'NY')
|
|
172
|
+
cities = ['Fulton', 'Niagara Falls'].map {|c| City.create(name: c)}
|
|
173
|
+
args = [
|
|
174
|
+
:reverse_assoc,
|
|
175
|
+
CustomKeys::Parent,
|
|
176
|
+
:has_many,
|
|
177
|
+
:cities,
|
|
178
|
+
state.id
|
|
179
|
+
]
|
|
180
|
+
|
|
181
|
+
Should 'attach cities to New York' do
|
|
182
|
+
cities.each do |city|
|
|
183
|
+
post app.route(*args, target_item_id: city.id.to_s)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
Ensure 'cities updated' do
|
|
187
|
+
cities.each do |city|
|
|
188
|
+
city.reload
|
|
189
|
+
is(city.state_code) == state.code
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
Ensure 'frontend reflects updates' do
|
|
194
|
+
get app.route(*args, :attached)
|
|
195
|
+
is(last_response).ok?
|
|
196
|
+
cities_html = extract_elements.children
|
|
197
|
+
cities.each do |city|
|
|
198
|
+
expect(cities_html).any? do |c|
|
|
199
|
+
c.text == city.name
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
module ReadOnly
|
|
208
|
+
class Books < E
|
|
209
|
+
include Rear
|
|
210
|
+
model Book
|
|
211
|
+
readonly_assoc :author
|
|
212
|
+
end
|
|
213
|
+
class Authors < E
|
|
214
|
+
include Rear
|
|
215
|
+
model Author
|
|
216
|
+
end
|
|
217
|
+
Spec.new Authors do
|
|
218
|
+
Books.mount
|
|
219
|
+
|
|
220
|
+
book, book_id = new_book()
|
|
221
|
+
args = [
|
|
222
|
+
:reverse_assoc,
|
|
223
|
+
Books,
|
|
224
|
+
:belongs_to,
|
|
225
|
+
:author,
|
|
226
|
+
book_id
|
|
227
|
+
]
|
|
228
|
+
|
|
229
|
+
Ensure 'no author attached' do
|
|
230
|
+
get app.route(*args, :attached)
|
|
231
|
+
is(last_response).ok?
|
|
232
|
+
are(extract_elements).empty?
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
author = Author.create(name: rand(2**64).to_s)
|
|
236
|
+
|
|
237
|
+
Should 'prohibit attaching' do
|
|
238
|
+
post app.route(*args, target_item_id: author.id.to_s)
|
|
239
|
+
is(last_response).readonly_error?
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
Should 'prohibit detaching' do
|
|
243
|
+
delete app.route(*args)
|
|
244
|
+
is(last_response).readonly_error?
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
end
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
|
|
2
|
+
module RearTest__Columns
|
|
3
|
+
|
|
4
|
+
class BasicApp < E
|
|
5
|
+
include Rear
|
|
6
|
+
model Book
|
|
7
|
+
end
|
|
8
|
+
Spec.new BasicApp do
|
|
9
|
+
|
|
10
|
+
item, item_id = new_book()
|
|
11
|
+
|
|
12
|
+
Testing :pane do
|
|
13
|
+
get
|
|
14
|
+
is(last_response).ok?
|
|
15
|
+
expect(extract_elements('.pane-item').size) > 0
|
|
16
|
+
|
|
17
|
+
elements = extract_elements
|
|
18
|
+
expect( elements ).any? {|e| e.text == item[:name].to_s }
|
|
19
|
+
expect( elements ).any? {|e| e.text == item[:about].to_s}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
Testing :editor do
|
|
23
|
+
get :edit, item_id
|
|
24
|
+
is(last_response).ok?
|
|
25
|
+
elements = extract_elements
|
|
26
|
+
expect( elements ).any? do |e|
|
|
27
|
+
e.children.any? {|c| c.name == 'input' && c.attr(:value) == item[:name].to_s }
|
|
28
|
+
end
|
|
29
|
+
expect( elements ).any? do |e|
|
|
30
|
+
e.children.any? {|c| c.name == 'textarea' && c.text == item[:about].to_s }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class SelectType < E
|
|
37
|
+
include Rear
|
|
38
|
+
model Book
|
|
39
|
+
input :cover, :select do
|
|
40
|
+
options('Solid', 'Soft')
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
Spec.new SelectType do
|
|
44
|
+
|
|
45
|
+
item, item_id = new_book( :cover => 'Soft')
|
|
46
|
+
|
|
47
|
+
Testing :pane do
|
|
48
|
+
get
|
|
49
|
+
check( extract_elements ).any? {|e| e.text == 'Soft'}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
Testing :editor do
|
|
53
|
+
get :edit, item_id
|
|
54
|
+
is(last_response).ok?
|
|
55
|
+
check( extract_elements ).any? { |e|
|
|
56
|
+
e.children.any? do |c|
|
|
57
|
+
c.name == 'select' && c.attr(:name) == 'cover' &&
|
|
58
|
+
c.children.any? {|cc|
|
|
59
|
+
cc.attr(:value) == 'Soft' && cc.attr(:selected)
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class MultiSelectType < E
|
|
69
|
+
include Rear
|
|
70
|
+
model Book
|
|
71
|
+
|
|
72
|
+
on_save do
|
|
73
|
+
params['colors'] = params['colors'].join(',')
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
input :colors, :select, :multiple => true do
|
|
77
|
+
options 'r' => 'Reg', 'g' => 'Green', 'b' => 'Blue' do
|
|
78
|
+
item.colors.to_s.split(',')
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
Spec.new MultiSelectType do
|
|
83
|
+
|
|
84
|
+
item, item_id = new_book( :colors => 'r,g')
|
|
85
|
+
|
|
86
|
+
Testing :pane do
|
|
87
|
+
|
|
88
|
+
get
|
|
89
|
+
is(last_response).ok?
|
|
90
|
+
check( extract_elements ).any? {|e|
|
|
91
|
+
e.text =~ /Red/ || e.text =~ /Green/
|
|
92
|
+
}
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
Testing :editor do
|
|
96
|
+
get :edit, item_id
|
|
97
|
+
is(last_response).ok?
|
|
98
|
+
check( extract_elements ).any? { |e|
|
|
99
|
+
e.children.any? do |c|
|
|
100
|
+
c.name == 'select' && c.attr(:name) == 'colors[]' &&
|
|
101
|
+
c.children.any? {|cc|
|
|
102
|
+
cc.attr(:value) == 'r' && cc.attr(:selected)
|
|
103
|
+
} && c.children.any? {|cc|
|
|
104
|
+
cc.attr(:value) == 'g' && cc.attr(:selected)
|
|
105
|
+
}
|
|
106
|
+
end
|
|
107
|
+
}
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class CheckboxType < E
|
|
113
|
+
include Rear
|
|
114
|
+
model Book
|
|
115
|
+
|
|
116
|
+
on_save do
|
|
117
|
+
params['colors'] = params['colors'].join(',')
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
input :colors, :checkbox do
|
|
121
|
+
options 'r' => 'Reg', 'g' => 'Green', 'b' => 'Blue' do
|
|
122
|
+
item.colors.to_s.split(',')
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
Spec.new CheckboxType do
|
|
127
|
+
|
|
128
|
+
item, item_id = new_book( :colors => 'g,b')
|
|
129
|
+
Testing :pane do
|
|
130
|
+
get
|
|
131
|
+
check( extract_elements ).any? {|e|
|
|
132
|
+
e.text =~ /Green/ || e.text =~ /Blue/
|
|
133
|
+
}
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
Testing :editor do
|
|
137
|
+
|
|
138
|
+
get :edit, item_id
|
|
139
|
+
is(last_response).ok?
|
|
140
|
+
elements = extract_elements('.editor-checkbox_container')
|
|
141
|
+
item.colors.split(',').each do |color|
|
|
142
|
+
check( elements ).any? { |e|
|
|
143
|
+
e.children.any? { |c|
|
|
144
|
+
c.name == 'input' &&
|
|
145
|
+
c.attr(:type) == 'checkbox' &&
|
|
146
|
+
c.attr(:name) == 'colors[]' &&
|
|
147
|
+
c.attr(:value) == color && c.attr(:checked)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class RadioType < E
|
|
156
|
+
include Rear
|
|
157
|
+
model Book
|
|
158
|
+
input :cover, :radio do
|
|
159
|
+
options('Solid', 'Soft') { item.cover }
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
Spec.new RadioType do
|
|
163
|
+
|
|
164
|
+
item, item_id = new_book( :cover => 'Solid')
|
|
165
|
+
Testing :pane do
|
|
166
|
+
get
|
|
167
|
+
is(last_response).ok?
|
|
168
|
+
check( extract_elements ).any? {|e| e.text == 'Solid' }
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
Testing :editor do
|
|
172
|
+
get :edit, item_id
|
|
173
|
+
is(last_response).ok?
|
|
174
|
+
elements = extract_elements('.editor-radio_container')
|
|
175
|
+
{'Solid' => true, 'Soft' => false}.each_pair do |value, status|
|
|
176
|
+
check( elements ).any? { |e|
|
|
177
|
+
e.children.any? do |c|
|
|
178
|
+
c.name == 'input' &&
|
|
179
|
+
c.attr(:type) == 'radio' &&
|
|
180
|
+
c.attr(:name) == 'cover' &&
|
|
181
|
+
c.attr(:value) == value &&
|
|
182
|
+
(status ? c.attr(:checked) : true)
|
|
183
|
+
end
|
|
184
|
+
}
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class AttrsApp < E
|
|
191
|
+
include Rear
|
|
192
|
+
model Book
|
|
193
|
+
input :name, style: 'width: 100%;'
|
|
194
|
+
input :about, cols: 10
|
|
195
|
+
end
|
|
196
|
+
Spec.new AttrsApp do
|
|
197
|
+
|
|
198
|
+
item, item_id = new_book()
|
|
199
|
+
|
|
200
|
+
get :edit, item_id
|
|
201
|
+
is(last_response).ok?
|
|
202
|
+
elements = extract_elements
|
|
203
|
+
expect( elements ).any? { |e|
|
|
204
|
+
e.children.any? {|c|
|
|
205
|
+
c.name == 'input' && c.attr(:style) == 'width: 100%;'
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
expect( elements ).any? { |e|
|
|
209
|
+
e.children.any? {|c| c.name == 'textarea' && c.attr(:cols) == '10' }
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
class DisablerApp < E
|
|
215
|
+
include Rear
|
|
216
|
+
model Book
|
|
217
|
+
|
|
218
|
+
input :name do
|
|
219
|
+
pane false
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
input :about do
|
|
223
|
+
editor false
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
end
|
|
227
|
+
Spec.new DisablerApp do
|
|
228
|
+
|
|
229
|
+
item, item_id = new_book()
|
|
230
|
+
|
|
231
|
+
Testing :pane do
|
|
232
|
+
get
|
|
233
|
+
is(last_response).ok?
|
|
234
|
+
elements = extract_elements
|
|
235
|
+
Should 'show :about column' do
|
|
236
|
+
expect( elements ).any? {|e|
|
|
237
|
+
e.children.any? {|c| c.to_s =~ /#{item[:about]}/}
|
|
238
|
+
}
|
|
239
|
+
end
|
|
240
|
+
Should 'NOT show :name column' do
|
|
241
|
+
refute do
|
|
242
|
+
elements.any? do |e|
|
|
243
|
+
e.children.any? {|c| c.text == item[:name]}
|
|
244
|
+
end
|
|
245
|
+
end == true
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
Testing :editor do
|
|
250
|
+
get :edit, item_id
|
|
251
|
+
is(last_response).ok?
|
|
252
|
+
elements = extract_elements
|
|
253
|
+
Should 'show :name column' do
|
|
254
|
+
expect( elements ).any? { |e|
|
|
255
|
+
e.children.any? do |c|
|
|
256
|
+
c.name == 'input' && c.attr(:value) == item[:name].to_s
|
|
257
|
+
end
|
|
258
|
+
}
|
|
259
|
+
end
|
|
260
|
+
Should 'NOT show :about column' do
|
|
261
|
+
refute do
|
|
262
|
+
elements.any? do |e|
|
|
263
|
+
e.children.any? {|c| c.name == 'textarea'}
|
|
264
|
+
end
|
|
265
|
+
end == true
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
end
|