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