ballot 1.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/Contributing.md +68 -0
- data/History.md +5 -0
- data/Licence.md +27 -0
- data/Manifest.txt +68 -0
- data/README.rdoc +264 -0
- data/Rakefile +71 -0
- data/bin/ballot_generator +9 -0
- data/lib/ballot.rb +25 -0
- data/lib/ballot/action_controller.rb +32 -0
- data/lib/ballot/active_record.rb +152 -0
- data/lib/ballot/active_record/votable.rb +145 -0
- data/lib/ballot/active_record/vote.rb +35 -0
- data/lib/ballot/active_record/voter.rb +99 -0
- data/lib/ballot/railtie.rb +19 -0
- data/lib/ballot/sequel.rb +170 -0
- data/lib/ballot/sequel/vote.rb +99 -0
- data/lib/ballot/votable.rb +445 -0
- data/lib/ballot/vote.rb +129 -0
- data/lib/ballot/voter.rb +320 -0
- data/lib/ballot/words.rb +32 -0
- data/lib/generators/ballot.rb +40 -0
- data/lib/generators/ballot/install/install_generator.rb +27 -0
- data/lib/generators/ballot/install/templates/active_record/migration.rb +19 -0
- data/lib/generators/ballot/install/templates/sequel/migration.rb +25 -0
- data/lib/generators/ballot/standalone.rb +89 -0
- data/lib/generators/ballot/standalone/support.rb +70 -0
- data/lib/generators/ballot/summary/summary_generator.rb +27 -0
- data/lib/generators/ballot/summary/templates/active_record/migration.rb +15 -0
- data/lib/generators/ballot/summary/templates/sequel/migration.rb +20 -0
- data/lib/sequel/plugins/ballot_votable.rb +180 -0
- data/lib/sequel/plugins/ballot_voter.rb +125 -0
- data/test/active_record/ballot_votable_test.rb +16 -0
- data/test/active_record/ballot_voter_test.rb +13 -0
- data/test/active_record/rails_generator_test.rb +28 -0
- data/test/active_record/votable_voter_test.rb +19 -0
- data/test/generators/rails-activerecord/Rakefile +2 -0
- data/test/generators/rails-activerecord/app/.keep +0 -0
- data/test/generators/rails-activerecord/bin/rails +5 -0
- data/test/generators/rails-activerecord/config/application.rb +17 -0
- data/test/generators/rails-activerecord/config/boot.rb +3 -0
- data/test/generators/rails-activerecord/config/database.yml +12 -0
- data/test/generators/rails-activerecord/config/environment.rb +3 -0
- data/test/generators/rails-activerecord/config/routes.rb +3 -0
- data/test/generators/rails-activerecord/config/secrets.yml +5 -0
- data/test/generators/rails-activerecord/db/seeds.rb +1 -0
- data/test/generators/rails-activerecord/log/.keep +0 -0
- data/test/generators/rails-sequel/Rakefile +2 -0
- data/test/generators/rails-sequel/app/.keep +0 -0
- data/test/generators/rails-sequel/bin/rails +5 -0
- data/test/generators/rails-sequel/config/application.rb +14 -0
- data/test/generators/rails-sequel/config/boot.rb +3 -0
- data/test/generators/rails-sequel/config/database.yml +12 -0
- data/test/generators/rails-sequel/config/environment.rb +3 -0
- data/test/generators/rails-sequel/config/routes.rb +3 -0
- data/test/generators/rails-sequel/config/secrets.yml +5 -0
- data/test/generators/rails-sequel/db/seeds.rb +1 -0
- data/test/generators/rails-sequel/log/.keep +0 -0
- data/test/minitest_config.rb +14 -0
- data/test/sequel/ballot_votable_test.rb +45 -0
- data/test/sequel/ballot_voter_test.rb +42 -0
- data/test/sequel/rails_generator_test.rb +25 -0
- data/test/sequel/votable_voter_test.rb +19 -0
- data/test/sequel/vote_test.rb +105 -0
- data/test/support/active_record_setup.rb +145 -0
- data/test/support/generators_setup.rb +129 -0
- data/test/support/sequel_setup.rb +164 -0
- data/test/support/shared_examples/votable_examples.rb +630 -0
- data/test/support/shared_examples/voter_examples.rb +600 -0
- metadata +333 -0
@@ -0,0 +1,600 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module VoterExamples
|
4
|
+
def describe_voter_models(models, focus: false)
|
5
|
+
describe '.ballot_voter?' do
|
6
|
+
models.each do |model|
|
7
|
+
self.focus if focus && respond_to?(:focus)
|
8
|
+
it "#{model}.ballot_voter? is true" do
|
9
|
+
assert_true model.ballot_voter?
|
10
|
+
end
|
11
|
+
|
12
|
+
self.focus if focus && respond_to?(:focus)
|
13
|
+
it "#{model}#ballot_voter? is true" do
|
14
|
+
assert_true model.new.ballot_voter?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def describe_non_voter_models(models, focus: false)
|
21
|
+
describe '.ballot_voter?' do
|
22
|
+
models.each do |model|
|
23
|
+
self.focus if focus && respond_to?(:focus)
|
24
|
+
it "#{model}.ballot_voter? is false" do
|
25
|
+
assert_false model.ballot_voter?
|
26
|
+
end
|
27
|
+
|
28
|
+
self.focus if focus && respond_to?(:focus)
|
29
|
+
it "#{model}.ballot_voter? is false" do
|
30
|
+
assert_false model.new.ballot_voter?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def describe_ballot_voter(klass = nil, focus: false, &block)
|
37
|
+
msg = 'a voter model'
|
38
|
+
klass && msg = "#{klass} is #{msg}"
|
39
|
+
|
40
|
+
describe msg do
|
41
|
+
instance_exec(&block) if block
|
42
|
+
|
43
|
+
describe '#cast_ballot_for' do
|
44
|
+
self.focus if focus
|
45
|
+
it 'is false when no votable is provided' do
|
46
|
+
assert_false voter.cast_ballot_for
|
47
|
+
end
|
48
|
+
|
49
|
+
self.focus if focus
|
50
|
+
it 'is false when the votable is not a model' do
|
51
|
+
assert_false voter.cast_ballot_for Class.new
|
52
|
+
end
|
53
|
+
|
54
|
+
self.focus if focus
|
55
|
+
it 'is false when the votable is not a votable' do
|
56
|
+
assert_false voter.cast_ballot_for not_votable
|
57
|
+
end
|
58
|
+
|
59
|
+
self.focus if focus
|
60
|
+
it 'is true when a vote succeeds' do
|
61
|
+
assert_true voter.cast_ballot_for votable
|
62
|
+
end
|
63
|
+
|
64
|
+
self.focus if focus
|
65
|
+
it 'adds a vote' do
|
66
|
+
assert_true voter.cast_ballot_for votable
|
67
|
+
assert_true voter_dataset(voter).any?
|
68
|
+
assert_equal 1, voter_dataset(voter).count
|
69
|
+
end
|
70
|
+
|
71
|
+
self.focus if focus
|
72
|
+
it 'creates only one vote per item' do
|
73
|
+
voter.cast_ballot_for votable: votable
|
74
|
+
|
75
|
+
assert_true(
|
76
|
+
voter.cast_ballot_for(
|
77
|
+
votable_id: votable.id,
|
78
|
+
votable_type: ballot_type_name(votable),
|
79
|
+
vote: 'no'
|
80
|
+
)
|
81
|
+
)
|
82
|
+
|
83
|
+
assert_equal 1, votable_dataset(votable).count
|
84
|
+
end
|
85
|
+
|
86
|
+
self.focus if focus
|
87
|
+
it 'creates only one vote per item, unless duplicates are allowed' do
|
88
|
+
voter.cast_ballot_for votable: votable
|
89
|
+
assert_true voter.cast_ballot_for votable: votable, duplicate: true
|
90
|
+
assert_equal 2, votable_dataset(votable).count
|
91
|
+
end
|
92
|
+
|
93
|
+
self.focus if focus
|
94
|
+
it 'creates a scoped vote' do
|
95
|
+
voter.cast_ballot_for votable: votable, scope: 'rank'
|
96
|
+
assert_true votable_dataset(votable).where(scope: 'rank').any?
|
97
|
+
end
|
98
|
+
|
99
|
+
self.focus if focus
|
100
|
+
it 'creates only one scoped vote per person' do
|
101
|
+
voter.cast_ballot_for votable: votable, scope: 'rank'
|
102
|
+
voter.cast_ballot_for votable: votable, scope: 'rank', vote: 'no'
|
103
|
+
assert_equal 1, votable_dataset(votable).where(scope: 'rank').count
|
104
|
+
end
|
105
|
+
|
106
|
+
self.focus if focus
|
107
|
+
it 'creates only one scoped vote per person, unless duplicates are allowed' do
|
108
|
+
voter.cast_ballot_for votable: votable, scope: 'rank'
|
109
|
+
assert_true(
|
110
|
+
voter.cast_ballot_for(
|
111
|
+
votable: votable, scope: 'rank', vote: 'no', duplicate: true
|
112
|
+
)
|
113
|
+
)
|
114
|
+
assert_equal 2, votable_dataset(votable).where(scope: 'rank').count
|
115
|
+
end
|
116
|
+
|
117
|
+
self.focus if focus
|
118
|
+
it 'creates multiple votes with different scopes' do
|
119
|
+
assert_true voter.cast_ballot_for votable: votable, scope: 'weekly_rank'
|
120
|
+
assert_true voter.cast_ballot_for votable: votable, scope: 'monthly_rank'
|
121
|
+
assert_equal 2, votable_dataset(votable).count
|
122
|
+
end
|
123
|
+
|
124
|
+
self.focus if focus
|
125
|
+
it 'records separate votes for separate voters' do
|
126
|
+
assert_true voter.cast_ballot_for votable: votable
|
127
|
+
assert_true voter2.cast_ballot_for votable: votable
|
128
|
+
assert_equal 2, votable_dataset(votable).count
|
129
|
+
end
|
130
|
+
|
131
|
+
self.focus if focus
|
132
|
+
it 'uses a default vote weight of 1' do
|
133
|
+
voter.cast_ballot_for votable
|
134
|
+
assert_equal 1, votable_dataset(votable).first.weight
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe '#cast_up_ballot_for' do
|
139
|
+
self.focus if focus
|
140
|
+
it 'is false when the votable is not a model' do
|
141
|
+
assert_false voter.cast_up_ballot_for Class.new
|
142
|
+
end
|
143
|
+
|
144
|
+
self.focus if focus
|
145
|
+
it 'is false when the votable is not a votable' do
|
146
|
+
assert_false voter.cast_up_ballot_for not_votable
|
147
|
+
end
|
148
|
+
|
149
|
+
self.focus if focus
|
150
|
+
it 'is true when a vote succeeds' do
|
151
|
+
assert_true voter.cast_up_ballot_for votable
|
152
|
+
end
|
153
|
+
|
154
|
+
self.focus if focus
|
155
|
+
it 'adds a vote' do
|
156
|
+
assert_true voter.cast_up_ballot_for votable
|
157
|
+
assert_true voter_dataset(voter).any?
|
158
|
+
assert_equal 1, votable_dataset(votable).count
|
159
|
+
end
|
160
|
+
|
161
|
+
self.focus if focus
|
162
|
+
it 'creates only one vote per item' do
|
163
|
+
voter.cast_up_ballot_for votable
|
164
|
+
assert_false voter.cast_up_ballot_for votable, vote: 'no'
|
165
|
+
assert_equal 1, votable_dataset(votable).count
|
166
|
+
end
|
167
|
+
|
168
|
+
self.focus if focus
|
169
|
+
it 'creates only one vote per item, unless duplicates are allowed' do
|
170
|
+
voter.cast_up_ballot_for votable
|
171
|
+
assert_true voter.cast_up_ballot_for votable, duplicate: true
|
172
|
+
assert_equal 2, votable_dataset(votable).count
|
173
|
+
end
|
174
|
+
|
175
|
+
self.focus if focus
|
176
|
+
it 'creates a scoped vote' do
|
177
|
+
voter.cast_up_ballot_for votable, scope: 'rank'
|
178
|
+
assert_true votable_dataset(votable).where(scope: 'rank').any?
|
179
|
+
end
|
180
|
+
|
181
|
+
self.focus if focus
|
182
|
+
it 'creates only one scoped vote per person' do
|
183
|
+
voter.cast_up_ballot_for votable, scope: 'rank'
|
184
|
+
voter.cast_up_ballot_for votable, scope: 'rank', vote: 'no'
|
185
|
+
assert_equal 1, votable_dataset(votable).where(scope: 'rank').count
|
186
|
+
end
|
187
|
+
|
188
|
+
self.focus if focus
|
189
|
+
it 'creates only one scoped vote per person, unless duplicates are allowed' do
|
190
|
+
voter.cast_up_ballot_for votable, scope: 'rank'
|
191
|
+
assert_true(
|
192
|
+
voter.cast_up_ballot_for(votable, scope: 'rank', vote: 'no', duplicate: true)
|
193
|
+
)
|
194
|
+
assert_equal 2, votable_dataset(votable).where(scope: 'rank').count
|
195
|
+
end
|
196
|
+
|
197
|
+
self.focus if focus
|
198
|
+
it 'creates multiple votes with different scopes' do
|
199
|
+
assert_true voter.cast_up_ballot_for votable, scope: 'weekly_rank'
|
200
|
+
assert_true voter.cast_up_ballot_for votable, scope: 'monthly_rank'
|
201
|
+
assert_equal 2, votable_dataset(votable).count
|
202
|
+
end
|
203
|
+
|
204
|
+
self.focus if focus
|
205
|
+
it 'records separate votes for separate voters' do
|
206
|
+
assert_true voter.cast_up_ballot_for votable
|
207
|
+
assert_true voter2.cast_up_ballot_for votable
|
208
|
+
assert_equal 2, votable_dataset(votable).count
|
209
|
+
end
|
210
|
+
|
211
|
+
self.focus if focus
|
212
|
+
it 'uses a default vote weight of 1' do
|
213
|
+
voter.cast_up_ballot_for votable
|
214
|
+
assert_equal 1, votable_dataset(votable).first.weight
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
describe '#cast_down_ballot_for' do
|
219
|
+
self.focus if focus
|
220
|
+
it 'is false when the votable is not a model' do
|
221
|
+
assert_false voter.cast_down_ballot_for Class.new
|
222
|
+
end
|
223
|
+
|
224
|
+
self.focus if focus
|
225
|
+
it 'is false when the votable is not a votable' do
|
226
|
+
assert_false voter.cast_down_ballot_for not_votable
|
227
|
+
end
|
228
|
+
|
229
|
+
self.focus if focus
|
230
|
+
it 'is true when a vote succeeds' do
|
231
|
+
assert_true voter.cast_down_ballot_for votable
|
232
|
+
end
|
233
|
+
|
234
|
+
self.focus if focus
|
235
|
+
it 'adds a vote' do
|
236
|
+
assert_true voter.cast_down_ballot_for votable
|
237
|
+
assert_true voter_dataset(voter).any?
|
238
|
+
assert_equal 1, votable_dataset(votable).count
|
239
|
+
end
|
240
|
+
|
241
|
+
self.focus if focus
|
242
|
+
it 'creates only one vote per item' do
|
243
|
+
voter.cast_down_ballot_for votable
|
244
|
+
assert_false voter.cast_down_ballot_for votable, vote: 'no'
|
245
|
+
assert_equal 1, votable_dataset(votable).count
|
246
|
+
end
|
247
|
+
|
248
|
+
self.focus if focus
|
249
|
+
it 'creates only one vote per item, unless duplicates are allowed' do
|
250
|
+
voter.cast_down_ballot_for votable
|
251
|
+
assert_true voter.cast_down_ballot_for votable, duplicate: true
|
252
|
+
assert_equal 2, votable_dataset(votable).count
|
253
|
+
end
|
254
|
+
|
255
|
+
self.focus if focus
|
256
|
+
it 'creates a scoped vote' do
|
257
|
+
voter.cast_down_ballot_for votable, scope: 'rank'
|
258
|
+
assert_true votable_dataset(votable).where(scope: 'rank').any?
|
259
|
+
end
|
260
|
+
|
261
|
+
self.focus if focus
|
262
|
+
it 'creates only one scoped vote per person' do
|
263
|
+
voter.cast_down_ballot_for votable, scope: 'rank'
|
264
|
+
voter.cast_down_ballot_for votable, scope: 'rank', vote: 'no'
|
265
|
+
assert_equal 1, votable_dataset(votable).where(scope: 'rank').count
|
266
|
+
end
|
267
|
+
|
268
|
+
self.focus if focus
|
269
|
+
it 'creates only one scoped vote per person, unless duplicates are allowed' do
|
270
|
+
voter.cast_down_ballot_for votable, scope: 'rank'
|
271
|
+
assert_true(
|
272
|
+
voter.cast_down_ballot_for(votable, scope: 'rank', vote: 'no', duplicate: true)
|
273
|
+
)
|
274
|
+
assert_equal 2, votable_dataset(votable).where(scope: 'rank').count
|
275
|
+
end
|
276
|
+
|
277
|
+
self.focus if focus
|
278
|
+
it 'creates multiple votes with different scopes' do
|
279
|
+
assert_true voter.cast_down_ballot_for votable, scope: 'weekly_rank'
|
280
|
+
assert_true voter.cast_down_ballot_for votable, scope: 'monthly_rank'
|
281
|
+
assert_equal 2, votable_dataset(votable).count
|
282
|
+
end
|
283
|
+
|
284
|
+
self.focus if focus
|
285
|
+
it 'records separate votes for separate voters' do
|
286
|
+
assert_true voter.cast_down_ballot_for votable
|
287
|
+
assert_true voter2.cast_down_ballot_for votable
|
288
|
+
assert_equal 2, votable_dataset(votable).count
|
289
|
+
end
|
290
|
+
|
291
|
+
self.focus if focus
|
292
|
+
it 'uses a default vote weight of 1' do
|
293
|
+
voter.cast_down_ballot_for votable
|
294
|
+
assert_equal 1, votable_dataset(votable).first.weight
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
describe '#remove_ballot_for' do
|
299
|
+
self.focus if focus
|
300
|
+
it 'removes an up vote' do
|
301
|
+
voter.cast_up_ballot_for votable
|
302
|
+
assert_true voter.remove_ballot_for votable
|
303
|
+
assert_true votable_dataset(votable).none?
|
304
|
+
end
|
305
|
+
|
306
|
+
self.focus if focus
|
307
|
+
it 'removes a down vote' do
|
308
|
+
voter.cast_down_ballot_for votable
|
309
|
+
assert_true voter.remove_ballot_for votable
|
310
|
+
assert_true votable_dataset(votable).none?
|
311
|
+
end
|
312
|
+
|
313
|
+
self.focus if focus
|
314
|
+
it 'sets ballot_registered? to false' do
|
315
|
+
voter.cast_ballot_for votable
|
316
|
+
assert_true voter.remove_ballot_for votable
|
317
|
+
assert_false votable.ballot_registered?
|
318
|
+
end
|
319
|
+
|
320
|
+
self.focus if focus
|
321
|
+
it 'removes only a single vote' do
|
322
|
+
voter.cast_up_ballot_for votable
|
323
|
+
voter2.cast_up_ballot_for votable
|
324
|
+
voter.remove_ballot_for votable
|
325
|
+
assert_true votable_dataset(votable).any?
|
326
|
+
assert_true votable_dataset(votable).where(
|
327
|
+
voter_id: voter.id,
|
328
|
+
voter_type: voter.class.name
|
329
|
+
).none?
|
330
|
+
assert_true votable_dataset(votable).where(
|
331
|
+
voter_id: voter2.id,
|
332
|
+
voter_type: voter2.class.name
|
333
|
+
).any?
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
describe '#cast_ballot_for?' do
|
338
|
+
self.focus if focus
|
339
|
+
it 'is true if the user voted up' do
|
340
|
+
voter.cast_up_ballot_for votable
|
341
|
+
assert_true voter.cast_ballot_for?(votable)
|
342
|
+
end
|
343
|
+
|
344
|
+
self.focus if focus
|
345
|
+
it 'is true if the user voted down' do
|
346
|
+
voter.cast_down_ballot_for votable
|
347
|
+
assert_true voter.cast_ballot_for?(votable)
|
348
|
+
end
|
349
|
+
|
350
|
+
self.focus if focus
|
351
|
+
it 'is false if the user has not voted' do
|
352
|
+
assert_false voter.cast_ballot_for?(votable)
|
353
|
+
end
|
354
|
+
|
355
|
+
self.focus if focus
|
356
|
+
it 'is true if the user voted in scope' do
|
357
|
+
voter.cast_up_ballot_for votable, scope: 'rank'
|
358
|
+
assert_false voter.cast_ballot_for?(votable)
|
359
|
+
assert_true voter.cast_ballot_for?(votable, scope: 'rank')
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
describe '#cast_up_ballot_for?, #cast_down_ballot_for?' do
|
364
|
+
self.focus if focus
|
365
|
+
it 'is up if the user voted up' do
|
366
|
+
voter.cast_up_ballot_for votable
|
367
|
+
assert_true voter.cast_up_ballot_for?(votable)
|
368
|
+
assert_false voter.cast_down_ballot_for?(votable)
|
369
|
+
end
|
370
|
+
|
371
|
+
self.focus if focus
|
372
|
+
it 'is true if the user voted down' do
|
373
|
+
voter.cast_down_ballot_for votable
|
374
|
+
assert_false voter.cast_up_ballot_for?(votable)
|
375
|
+
assert_true voter.cast_down_ballot_for?(votable)
|
376
|
+
end
|
377
|
+
|
378
|
+
self.focus if focus
|
379
|
+
it 'is false if the user has not voted' do
|
380
|
+
assert_false voter.cast_up_ballot_for?(votable)
|
381
|
+
assert_false voter.cast_down_ballot_for?(votable)
|
382
|
+
end
|
383
|
+
|
384
|
+
self.focus if focus
|
385
|
+
it 'is true if the user voted in scope' do
|
386
|
+
voter.cast_up_ballot_for votable, scope: 'rank'
|
387
|
+
assert_false voter.cast_up_ballot_for?(votable)
|
388
|
+
assert_false voter.cast_down_ballot_for?(votable)
|
389
|
+
assert_true voter.cast_up_ballot_for?(votable, scope: 'rank')
|
390
|
+
assert_false voter.cast_down_ballot_for?(votable, scope: 'rank')
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
describe '#ballot_as_cast_for' do
|
395
|
+
self.focus if focus
|
396
|
+
it 'is true when voted up' do
|
397
|
+
voter.cast_up_ballot_for votable
|
398
|
+
assert_true voter.ballot_as_cast_for(votable)
|
399
|
+
end
|
400
|
+
|
401
|
+
self.focus if focus
|
402
|
+
it 'is false when voted down' do
|
403
|
+
voter.cast_down_ballot_for votable
|
404
|
+
assert_false voter.ballot_as_cast_for(votable)
|
405
|
+
end
|
406
|
+
|
407
|
+
self.focus if focus
|
408
|
+
it 'is nil when not voted' do
|
409
|
+
assert_nil voter.ballot_as_cast_for(votable)
|
410
|
+
end
|
411
|
+
|
412
|
+
self.focus if focus
|
413
|
+
it 'is true when voted up with a scope' do
|
414
|
+
voter.cast_up_ballot_for votable, scope: 'rank'
|
415
|
+
assert_true voter.ballot_as_cast_for(votable, scope: 'rank')
|
416
|
+
assert_nil voter.ballot_as_cast_for(votable)
|
417
|
+
end
|
418
|
+
|
419
|
+
self.focus if focus
|
420
|
+
it 'is false when voted down' do
|
421
|
+
voter.cast_down_ballot_for votable, scope: 'rank'
|
422
|
+
assert_false voter.ballot_as_cast_for(votable, scope: 'rank')
|
423
|
+
assert_nil voter.ballot_as_cast_for(votable)
|
424
|
+
end
|
425
|
+
|
426
|
+
self.focus if focus
|
427
|
+
it 'is nil when not voted' do
|
428
|
+
assert_nil voter.ballot_as_cast_for(votable, scope: 'rank')
|
429
|
+
end
|
430
|
+
|
431
|
+
self.focus if focus
|
432
|
+
it 'applies only to the voter' do
|
433
|
+
voter.cast_down_ballot_for votable
|
434
|
+
voter2.cast_up_ballot_for votable
|
435
|
+
assert_false voter.ballot_as_cast_for(votable)
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
describe '#up_ballots_by' do
|
440
|
+
self.focus if focus
|
441
|
+
it 'returns the set of up votes' do
|
442
|
+
voter.cast_up_ballot_for votable
|
443
|
+
voter.cast_up_ballot_for sti_votable
|
444
|
+
voter.cast_down_ballot_for child_of_sti_votable
|
445
|
+
voter.cast_down_ballot_for votable_child_of_sti_not_votable
|
446
|
+
|
447
|
+
assert_equal [
|
448
|
+
votable_dataset(votable).first,
|
449
|
+
votable_dataset(sti_votable).first
|
450
|
+
], voter.up_ballots_by.all
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
describe '#down_ballots_by' do
|
455
|
+
self.focus if focus
|
456
|
+
it 'returns the set of down votes' do
|
457
|
+
voter.cast_up_ballot_for votable
|
458
|
+
voter.cast_up_ballot_for sti_votable
|
459
|
+
voter.cast_down_ballot_for child_of_sti_votable
|
460
|
+
voter.cast_down_ballot_for votable_child_of_sti_not_votable
|
461
|
+
|
462
|
+
assert_equal [
|
463
|
+
votable_dataset(child_of_sti_votable).first,
|
464
|
+
votable_dataset(votable_child_of_sti_not_votable).first
|
465
|
+
], voter.down_ballots_by.all
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
describe '#ballots_for_class' do
|
470
|
+
self.focus if focus
|
471
|
+
it 'returns the set of votes for this class' do
|
472
|
+
voter.cast_up_ballot_for votable
|
473
|
+
voter.cast_down_ballot_for votable2
|
474
|
+
|
475
|
+
assert_equal [ votable_dataset(votable).first, votable_dataset(votable2).first ],
|
476
|
+
voter.ballots_for_class(votable.class).all
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
describe '#up_ballots_for_class' do
|
481
|
+
self.focus if focus
|
482
|
+
it 'returns the set of up votes for this class' do
|
483
|
+
voter.cast_up_ballot_for votable
|
484
|
+
voter.cast_down_ballot_for votable2
|
485
|
+
|
486
|
+
assert_equal [ votable_dataset(votable).first ],
|
487
|
+
voter.up_ballots_for_class(votable.class).all
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
describe '#down_ballots_for_class' do
|
492
|
+
self.focus if focus
|
493
|
+
it 'returns the set of down votes for this class' do
|
494
|
+
voter.cast_up_ballot_for votable
|
495
|
+
voter.cast_down_ballot_for votable2
|
496
|
+
|
497
|
+
assert_equal [ votable_dataset(votable2).first ],
|
498
|
+
voter.down_ballots_for_class(votable.class).all
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
describe '#ballot_votables' do
|
503
|
+
self.focus if focus
|
504
|
+
it 'returns the set of items voted on' do
|
505
|
+
voter.cast_up_ballot_for votable
|
506
|
+
voter.cast_down_ballot_for votable2
|
507
|
+
|
508
|
+
assert_equal [ votable, votable2 ], voter.ballot_votables
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
describe '#ballot_up_votables' do
|
513
|
+
self.focus if focus
|
514
|
+
it 'returns the set of items up voted' do
|
515
|
+
voter.cast_up_ballot_for votable
|
516
|
+
voter.cast_down_ballot_for votable2
|
517
|
+
|
518
|
+
assert_equal [ votable ], voter.ballot_up_votables
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
describe '#ballot_down_votables' do
|
523
|
+
self.focus if focus
|
524
|
+
it 'returns the set of items down voted' do
|
525
|
+
voter.cast_up_ballot_for votable
|
526
|
+
voter.cast_down_ballot_for votable2
|
527
|
+
|
528
|
+
assert_equal [ votable2 ], voter.ballot_down_votables
|
529
|
+
end
|
530
|
+
end
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
534
|
+
def describe_ballot_voter_sti_votable_support(focus: false)
|
535
|
+
describe 'with STI' do
|
536
|
+
describe '#vote' do
|
537
|
+
self.focus if focus && respond_to?(:focus)
|
538
|
+
it 'works with STI models' do
|
539
|
+
voter.cast_ballot_for sti_votable
|
540
|
+
assert_true votable_dataset(sti_votable).any?
|
541
|
+
end
|
542
|
+
|
543
|
+
self.focus if focus && respond_to?(:focus)
|
544
|
+
it 'works with Child STI models' do
|
545
|
+
voter.cast_ballot_for child_of_sti_votable
|
546
|
+
assert_true votable_dataset(child_of_sti_votable).any?
|
547
|
+
end
|
548
|
+
|
549
|
+
self.focus if focus && respond_to?(:focus)
|
550
|
+
it 'works with votable children of non-votable STI models' do
|
551
|
+
voter.cast_ballot_for votable_child_of_sti_not_votable
|
552
|
+
assert_true votable_dataset(votable_child_of_sti_not_votable).any?
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
describe '#cast_up_ballot_for' do
|
557
|
+
self.focus if focus && respond_to?(:focus)
|
558
|
+
it 'works with STI models' do
|
559
|
+
voter.cast_up_ballot_for sti_votable
|
560
|
+
assert_true votable_dataset(sti_votable).any?
|
561
|
+
end
|
562
|
+
|
563
|
+
self.focus if focus && respond_to?(:focus)
|
564
|
+
it 'works with Child STI models' do
|
565
|
+
voter.cast_up_ballot_for child_of_sti_votable
|
566
|
+
assert_true votable_dataset(child_of_sti_votable).any?
|
567
|
+
end
|
568
|
+
|
569
|
+
self.focus if focus && respond_to?(:focus)
|
570
|
+
it 'works with votable children of non-votable STI models' do
|
571
|
+
voter.cast_up_ballot_for votable_child_of_sti_not_votable
|
572
|
+
assert_true votable_dataset(votable_child_of_sti_not_votable).any?
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
576
|
+
describe '#cast_down_ballot_for' do
|
577
|
+
self.focus if focus && respond_to?(:focus)
|
578
|
+
it 'works with STI models' do
|
579
|
+
voter.cast_down_ballot_for sti_votable
|
580
|
+
assert_true votable_dataset(sti_votable).any?
|
581
|
+
end
|
582
|
+
|
583
|
+
self.focus if focus && respond_to?(:focus)
|
584
|
+
it 'works with Child STI models' do
|
585
|
+
voter.cast_down_ballot_for child_of_sti_votable
|
586
|
+
assert_true votable_dataset(child_of_sti_votable).any?
|
587
|
+
end
|
588
|
+
|
589
|
+
self.focus if focus && respond_to?(:focus)
|
590
|
+
it 'works with votable children of non-votable STI models' do
|
591
|
+
voter.cast_down_ballot_for votable_child_of_sti_not_votable
|
592
|
+
assert_true votable_dataset(votable_child_of_sti_not_votable).any?
|
593
|
+
end
|
594
|
+
end
|
595
|
+
end
|
596
|
+
end
|
597
|
+
|
598
|
+
::Minitest::SequelSpec.extend self
|
599
|
+
::Minitest::ActiveRecordSpec.extend self
|
600
|
+
end
|