Commit 706e8359b6e77622024e84a687861d30702bbd6f
1 parent
71acdfab
Exists in
master
and in
1 other branch
retab question_spec
Showing
1 changed file
with
204 additions
and
204 deletions
Show diff stats
spec/models/question_spec.rb
@@ -131,8 +131,8 @@ describe Question do | @@ -131,8 +131,8 @@ describe Question do | ||
131 | 131 | ||
132 | ['left', 'right'].each do |side| | 132 | ['left', 'right'].each do |side| |
133 | ['text', 'id'].each do |param| | 133 | ['text', 'id'].each do |param| |
134 | - the_type = (param == 'text') ? String : Fixnum | ||
135 | - @question_optional_information["future_#{side}_choice_#{param}_1".to_sym].should be_an_instance_of(the_type) | 134 | + the_type = (param == 'text') ? String : Fixnum |
135 | + @question_optional_information["future_#{side}_choice_#{param}_1".to_sym].should be_an_instance_of(the_type) | ||
136 | end | 136 | end |
137 | end | 137 | end |
138 | 138 | ||
@@ -158,9 +158,9 @@ describe Question do | @@ -158,9 +158,9 @@ describe Question do | ||
158 | future_prompt_id_1 = @question_optional_information[:future_prompt_id_1] | 158 | future_prompt_id_1 = @question_optional_information[:future_prompt_id_1] |
159 | 159 | ||
160 | vote_options = {:visitor_identifier => "jim", | 160 | vote_options = {:visitor_identifier => "jim", |
161 | - :appearance_lookup => appearance_id, | ||
162 | - :prompt => Prompt.find(prompt_id), | ||
163 | - :direction => "left"} | 161 | + :appearance_lookup => appearance_id, |
162 | + :prompt => Prompt.find(prompt_id), | ||
163 | + :direction => "left"} | ||
164 | 164 | ||
165 | @aoi_clone.record_vote(vote_options) | 165 | @aoi_clone.record_vote(vote_options) |
166 | 166 | ||
@@ -178,9 +178,9 @@ describe Question do | @@ -178,9 +178,9 @@ describe Question do | ||
178 | @question_optional_information[:average_votes].should be_close(0.0, 0.1) | 178 | @question_optional_information[:average_votes].should be_close(0.0, 0.1) |
179 | 179 | ||
180 | vote_options = {:visitor_identifier => "jim", | 180 | vote_options = {:visitor_identifier => "jim", |
181 | - :appearance_lookup => @question_optional_information[:appearance_id], | ||
182 | - :prompt => Prompt.find(@question_optional_information[:picked_prompt_id]), | ||
183 | - :direction => "left"} | 181 | + :appearance_lookup => @question_optional_information[:appearance_id], |
182 | + :prompt => Prompt.find(@question_optional_information[:picked_prompt_id]), | ||
183 | + :direction => "left"} | ||
184 | 184 | ||
185 | @aoi_clone.record_vote(vote_options) | 185 | @aoi_clone.record_vote(vote_options) |
186 | @question_optional_information = @question.get_optional_information(params) | 186 | @question_optional_information = @question.get_optional_information(params) |
@@ -204,219 +204,219 @@ describe Question do | @@ -204,219 +204,219 @@ describe Question do | ||
204 | @question.choices.count.should == 3 | 204 | @question.choices.count.should == 3 |
205 | end | 205 | end |
206 | context "catchup algorithm" do | 206 | context "catchup algorithm" do |
207 | - before(:all) do | ||
208 | - @catchup_q = Factory.create(:aoi_question) | ||
209 | - | ||
210 | - @catchup_q.it_should_autoactivate_ideas = true | ||
211 | - @catchup_q.uses_catchup = true | ||
212 | - @catchup_q.save! | ||
213 | - | ||
214 | - # 2 ideas already exist, so this will make an even hundred | ||
215 | - 98.times.each do |num| | ||
216 | - @catchup_q.site.create_choice("visitor identifier", @catchup_q, {:data => num.to_s, :local_identifier => "exmaple"}) | ||
217 | - end | ||
218 | - @catchup_q.reload | ||
219 | - end | ||
220 | - | ||
221 | - | ||
222 | - it "should create a delayed job after requesting a prompt" do | ||
223 | - proc { @catchup_q.choose_prompt}.should change(Delayed::Job, :count).by(1) | ||
224 | - end | ||
225 | - | ||
226 | - | ||
227 | - it "should choose an active prompt using catchup algorithm on a large number of choices" do | ||
228 | - @catchup_q.reload | ||
229 | - # Sanity check | ||
230 | - @catchup_q.choices.size.should == 100 | ||
231 | - | ||
232 | - prompt = @catchup_q.catchup_choose_prompt | ||
233 | - prompt.active?.should == true | ||
234 | - end | ||
235 | - | ||
236 | - it "should have a normalized vector of weights to support the catchup algorithm" do | ||
237 | - weights = @catchup_q.catchup_prompts_weights | ||
238 | - sum = 0 | ||
239 | - weights.each{|k,v| sum+=v} | ||
240 | - | ||
241 | - (sum - 1.0).abs.should < 0.000001 | ||
242 | - end | ||
243 | - | ||
244 | - it "should allow the prompt queue to be cleared" do | ||
245 | - @catchup_q.add_prompt_to_queue | ||
246 | - @catchup_q.clear_prompt_queue | ||
247 | - | ||
248 | - @catchup_q.pop_prompt_queue.should == nil | ||
249 | - end | ||
250 | - it "should allow a prompt to be added to the prompt queue" do | ||
251 | - @catchup_q.clear_prompt_queue | ||
252 | - @catchup_q.pop_prompt_queue.should == nil | ||
253 | - | ||
254 | - @catchup_q.add_prompt_to_queue | ||
255 | - | ||
256 | - prompt = @catchup_q.pop_prompt_queue | ||
257 | - | ||
258 | - prompt.should_not == nil | ||
259 | - prompt.active?.should == true | ||
260 | - end | ||
261 | - it "should return prompts from the queue in FIFO order" do | ||
262 | - @catchup_q.clear_prompt_queue | ||
263 | - @catchup_q.pop_prompt_queue.should == nil | ||
264 | - | ||
265 | - prompt1 = @catchup_q.add_prompt_to_queue | ||
266 | - prompt2 = @catchup_q.add_prompt_to_queue | ||
267 | - prompt3 = @catchup_q.add_prompt_to_queue | ||
268 | - | ||
269 | - prompt_1 = @catchup_q.pop_prompt_queue | ||
270 | - prompt_2 = @catchup_q.pop_prompt_queue | ||
271 | - prompt_3 = @catchup_q.pop_prompt_queue | ||
272 | - | ||
273 | - | ||
274 | - prompt_1.should == prompt1 | ||
275 | - prompt_2.should == prompt2 | ||
276 | - prompt_3.should == prompt3 | ||
277 | - | ||
278 | - # there is a small probability that the catchup algorithm | ||
279 | - # choose two prompts that are indeed equal | ||
280 | - prompt_1.should_not == prompt_2 | ||
281 | - prompt_1.should_not == prompt_3 | ||
282 | - prompt_2.should_not == prompt_3 | ||
283 | - | ||
284 | - | ||
285 | - @catchup_q.pop_prompt_queue.should == nil | ||
286 | - end | ||
287 | - it "should not return prompts from queue that are deactivated" do | ||
288 | - @catchup_q.clear_prompt_queue | ||
289 | - @catchup_q.pop_prompt_queue.should == nil | ||
290 | - prompt1 = @catchup_q.add_prompt_to_queue | ||
291 | - | ||
292 | - prompt = Prompt.find(prompt1) | ||
293 | - prompt.left_choice.deactivate! | ||
294 | - @catchup_q.choose_prompt.should_not == prompt1 | 207 | + before(:all) do |
208 | + @catchup_q = Factory.create(:aoi_question) | ||
209 | + | ||
210 | + @catchup_q.it_should_autoactivate_ideas = true | ||
211 | + @catchup_q.uses_catchup = true | ||
212 | + @catchup_q.save! | ||
213 | + | ||
214 | + # 2 ideas already exist, so this will make an even hundred | ||
215 | + 98.times.each do |num| | ||
216 | + @catchup_q.site.create_choice("visitor identifier", @catchup_q, {:data => num.to_s, :local_identifier => "exmaple"}) | ||
217 | + end | ||
218 | + @catchup_q.reload | ||
219 | + end | ||
220 | + | ||
221 | + | ||
222 | + it "should create a delayed job after requesting a prompt" do | ||
223 | + proc { @catchup_q.choose_prompt}.should change(Delayed::Job, :count).by(1) | ||
224 | + end | ||
225 | + | ||
226 | + | ||
227 | + it "should choose an active prompt using catchup algorithm on a large number of choices" do | ||
228 | + @catchup_q.reload | ||
229 | + # Sanity check | ||
230 | + @catchup_q.choices.size.should == 100 | ||
231 | + | ||
232 | + prompt = @catchup_q.catchup_choose_prompt | ||
233 | + prompt.active?.should == true | ||
234 | + end | ||
235 | + | ||
236 | + it "should have a normalized vector of weights to support the catchup algorithm" do | ||
237 | + weights = @catchup_q.catchup_prompts_weights | ||
238 | + sum = 0 | ||
239 | + weights.each{|k,v| sum+=v} | ||
240 | + | ||
241 | + (sum - 1.0).abs.should < 0.000001 | ||
242 | + end | ||
243 | + | ||
244 | + it "should allow the prompt queue to be cleared" do | ||
245 | + @catchup_q.add_prompt_to_queue | ||
246 | + @catchup_q.clear_prompt_queue | ||
247 | + | ||
248 | + @catchup_q.pop_prompt_queue.should == nil | ||
249 | + end | ||
250 | + it "should allow a prompt to be added to the prompt queue" do | ||
251 | + @catchup_q.clear_prompt_queue | ||
252 | + @catchup_q.pop_prompt_queue.should == nil | ||
253 | + | ||
254 | + @catchup_q.add_prompt_to_queue | ||
255 | + | ||
256 | + prompt = @catchup_q.pop_prompt_queue | ||
257 | + | ||
258 | + prompt.should_not == nil | ||
259 | + prompt.active?.should == true | ||
260 | + end | ||
261 | + it "should return prompts from the queue in FIFO order" do | ||
262 | + @catchup_q.clear_prompt_queue | ||
263 | + @catchup_q.pop_prompt_queue.should == nil | ||
264 | + | ||
265 | + prompt1 = @catchup_q.add_prompt_to_queue | ||
266 | + prompt2 = @catchup_q.add_prompt_to_queue | ||
267 | + prompt3 = @catchup_q.add_prompt_to_queue | ||
268 | + | ||
269 | + prompt_1 = @catchup_q.pop_prompt_queue | ||
270 | + prompt_2 = @catchup_q.pop_prompt_queue | ||
271 | + prompt_3 = @catchup_q.pop_prompt_queue | ||
272 | + | ||
273 | + | ||
274 | + prompt_1.should == prompt1 | ||
275 | + prompt_2.should == prompt2 | ||
276 | + prompt_3.should == prompt3 | ||
277 | + | ||
278 | + # there is a small probability that the catchup algorithm | ||
279 | + # choose two prompts that are indeed equal | ||
280 | + prompt_1.should_not == prompt_2 | ||
281 | + prompt_1.should_not == prompt_3 | ||
282 | + prompt_2.should_not == prompt_3 | ||
283 | + | ||
284 | + | ||
285 | + @catchup_q.pop_prompt_queue.should == nil | ||
286 | + end | ||
287 | + it "should not return prompts from queue that are deactivated" do | ||
288 | + @catchup_q.clear_prompt_queue | ||
289 | + @catchup_q.pop_prompt_queue.should == nil | ||
290 | + prompt1 = @catchup_q.add_prompt_to_queue | ||
291 | + | ||
292 | + prompt = Prompt.find(prompt1) | ||
293 | + prompt.left_choice.deactivate! | ||
294 | + @catchup_q.choose_prompt.should_not == prompt1 | ||
295 | end | 295 | end |
296 | after(:all) { truncate_all } | 296 | after(:all) { truncate_all } |
297 | end | 297 | end |
298 | 298 | ||
299 | context "exporting data" do | 299 | context "exporting data" do |
300 | - before(:all) do | ||
301 | - @aoi_question = Factory.create(:aoi_question) | ||
302 | - user = @aoi_question.site | 300 | + before(:all) do |
301 | + @aoi_question = Factory.create(:aoi_question) | ||
302 | + user = @aoi_question.site | ||
303 | 303 | ||
304 | - @aoi_question.it_should_autoactivate_ideas = true | ||
305 | - @aoi_question.save! | 304 | + @aoi_question.it_should_autoactivate_ideas = true |
305 | + @aoi_question.save! | ||
306 | 306 | ||
307 | visitor = user.visitors.find_or_create_by_identifier('visitor identifier') | 307 | visitor = user.visitors.find_or_create_by_identifier('visitor identifier') |
308 | - 100.times.each do |num| | ||
309 | - user.create_choice(visitor.identifier, @aoi_question, {:data => num.to_s, :local_identifier => "example creator"}) | ||
310 | - end | 308 | + 100.times.each do |num| |
309 | + user.create_choice(visitor.identifier, @aoi_question, {:data => num.to_s, :local_identifier => "example creator"}) | ||
310 | + end | ||
311 | 311 | ||
312 | - 200.times.each do |num| | ||
313 | - @p = @aoi_question.picked_prompt | 312 | + 200.times.each do |num| |
313 | + @p = @aoi_question.picked_prompt | ||
314 | 314 | ||
315 | - @a = user.record_appearance(visitor, @p) | 315 | + @a = user.record_appearance(visitor, @p) |
316 | 316 | ||
317 | - vote_options = {:visitor_identifier => visitor.identifier, | ||
318 | - :appearance_lookup => @a.lookup, | ||
319 | - :prompt => @p, | ||
320 | - :time_viewed => rand(1000), | ||
321 | - :direction => (rand(2) == 0) ? "left" : "right"} | ||
322 | - | 317 | + vote_options = {:visitor_identifier => visitor.identifier, |
318 | + :appearance_lookup => @a.lookup, | ||
319 | + :prompt => @p, | ||
320 | + :time_viewed => rand(1000), | ||
321 | + :direction => (rand(2) == 0) ? "left" : "right"} | ||
322 | + | ||
323 | skip_options = {:visitor_identifier => visitor.identifier, | 323 | skip_options = {:visitor_identifier => visitor.identifier, |
324 | :appearance_lookup => @a.lookup, | 324 | :appearance_lookup => @a.lookup, |
325 | :prompt => @p, | 325 | :prompt => @p, |
326 | :time_viewed => rand(1000), | 326 | :time_viewed => rand(1000), |
327 | :skip_reason => "some reason"} | 327 | :skip_reason => "some reason"} |
328 | 328 | ||
329 | - choice = rand(3) | ||
330 | - case choice | ||
331 | - when 0 | ||
332 | - user.record_vote(vote_options) | ||
333 | - when 1 | ||
334 | - user.record_skip(skip_options) | ||
335 | - when 2 | ||
336 | - #this is an orphaned appearance, so do nothing | ||
337 | - end | ||
338 | - end | ||
339 | - end | ||
340 | - | ||
341 | - | ||
342 | - it "should export vote data to a csv file" do | ||
343 | - filename = @aoi_question.export('votes') | ||
344 | - | ||
345 | - filename.should_not be nil | ||
346 | - filename.should match /.*ideamarketplace_#{@aoi_question.id}_votes[.]csv$/ | ||
347 | - File.exists?(filename).should be_true | ||
348 | - # Not specifying exact file syntax, it's likely to change frequently | ||
349 | - # | ||
350 | - rows = FasterCSV.read(filename) | ||
351 | - rows.first.should include("Vote ID") | ||
352 | - rows.first.should_not include("Idea ID") | ||
353 | - File.delete(filename).should be_true | ||
354 | - | ||
355 | - end | ||
356 | - | ||
357 | - it "should notify redis after completing an export, if redis option set" do | ||
358 | - redis_key = "test_key123" | ||
359 | - $redis.del(redis_key) # clear if key exists already | ||
360 | - filename = @aoi_question.export('votes', :response_type => 'redis', :redis_key => redis_key) | ||
361 | - | ||
362 | - filename.should_not be nil | ||
363 | - filename.should match /.*ideamarketplace_#{@aoi_question.id}_votes[.]csv$/ | ||
364 | - File.exists?(filename).should be_true | ||
365 | - $redis.lpop(redis_key).should == filename | ||
366 | - $redis.del(redis_key) # clean up | ||
367 | - File.delete(filename).should be_true | ||
368 | - | ||
369 | - end | ||
370 | - it "should email question owner after completing an export, if email option set" do | ||
371 | - #TODO | ||
372 | - end | ||
373 | - | ||
374 | - it "should export non vote data to a csv file" do | ||
375 | - filename = @aoi_question.export('non_votes') | ||
376 | - | ||
377 | - filename.should_not be nil | ||
378 | - filename.should match /.*ideamarketplace_#{@aoi_question.id}_non_votes[.]csv$/ | ||
379 | - File.exists?(filename).should be_true | ||
380 | - | ||
381 | - # Not specifying exact file syntax, it's likely to change frequently | ||
382 | - # | ||
383 | - rows = FasterCSV.read(filename) | ||
384 | - rows.first.should include("Record ID") | ||
385 | - rows.first.should include("Record Type") | ||
386 | - rows.first.should_not include("Idea ID") | ||
387 | - File.delete(filename).should_not be_nil | ||
388 | - | ||
389 | - | ||
390 | - end | ||
391 | - | ||
392 | - it "should export idea data to a csv file" do | ||
393 | - filename = @aoi_question.export('ideas') | ||
394 | - | ||
395 | - filename.should_not be nil | ||
396 | - filename.should match /.*ideamarketplace_#{@aoi_question.id}_ideas[.]csv$/ | ||
397 | - File.exists?(filename).should be_true | ||
398 | - # Not specifying exact file syntax, it's likely to change frequently | ||
399 | - # | ||
400 | - rows = FasterCSV.read(filename) | ||
401 | - rows.first.should include("Idea ID") | ||
402 | - rows.first.should_not include("Skip ID") | ||
403 | - File.delete(filename).should_not be_nil | ||
404 | - | ||
405 | - end | ||
406 | - | ||
407 | - it "should raise an error when given an unsupported export type" do | ||
408 | - lambda { @aoi_question.export("blahblahblah") }.should raise_error | ||
409 | - end | ||
410 | - | ||
411 | - it "should export data and schedule a job to delete export after X days" do | ||
412 | - Delayed::Job.delete_all | ||
413 | - filename = @aoi_question.export_and_delete('votes', :delete_at => 2.days.from_now) | ||
414 | - | ||
415 | - Delayed::Job.count.should == 1 | ||
416 | - Delayed::Job.delete_all | ||
417 | - File.delete(filename).should_not be_nil | ||
418 | - | ||
419 | - end | 329 | + choice = rand(3) |
330 | + case choice | ||
331 | + when 0 | ||
332 | + user.record_vote(vote_options) | ||
333 | + when 1 | ||
334 | + user.record_skip(skip_options) | ||
335 | + when 2 | ||
336 | + #this is an orphaned appearance, so do nothing | ||
337 | + end | ||
338 | + end | ||
339 | + end | ||
340 | + | ||
341 | + | ||
342 | + it "should export vote data to a csv file" do | ||
343 | + filename = @aoi_question.export('votes') | ||
344 | + | ||
345 | + filename.should_not be nil | ||
346 | + filename.should match /.*ideamarketplace_#{@aoi_question.id}_votes[.]csv$/ | ||
347 | + File.exists?(filename).should be_true | ||
348 | + # Not specifying exact file syntax, it's likely to change frequently | ||
349 | + # | ||
350 | + rows = FasterCSV.read(filename) | ||
351 | + rows.first.should include("Vote ID") | ||
352 | + rows.first.should_not include("Idea ID") | ||
353 | + File.delete(filename).should be_true | ||
354 | + | ||
355 | + end | ||
356 | + | ||
357 | + it "should notify redis after completing an export, if redis option set" do | ||
358 | + redis_key = "test_key123" | ||
359 | + $redis.del(redis_key) # clear if key exists already | ||
360 | + filename = @aoi_question.export('votes', :response_type => 'redis', :redis_key => redis_key) | ||
361 | + | ||
362 | + filename.should_not be nil | ||
363 | + filename.should match /.*ideamarketplace_#{@aoi_question.id}_votes[.]csv$/ | ||
364 | + File.exists?(filename).should be_true | ||
365 | + $redis.lpop(redis_key).should == filename | ||
366 | + $redis.del(redis_key) # clean up | ||
367 | + File.delete(filename).should be_true | ||
368 | + | ||
369 | + end | ||
370 | + it "should email question owner after completing an export, if email option set" do | ||
371 | + #TODO | ||
372 | + end | ||
373 | + | ||
374 | + it "should export non vote data to a csv file" do | ||
375 | + filename = @aoi_question.export('non_votes') | ||
376 | + | ||
377 | + filename.should_not be nil | ||
378 | + filename.should match /.*ideamarketplace_#{@aoi_question.id}_non_votes[.]csv$/ | ||
379 | + File.exists?(filename).should be_true | ||
380 | + | ||
381 | + # Not specifying exact file syntax, it's likely to change frequently | ||
382 | + # | ||
383 | + rows = FasterCSV.read(filename) | ||
384 | + rows.first.should include("Record ID") | ||
385 | + rows.first.should include("Record Type") | ||
386 | + rows.first.should_not include("Idea ID") | ||
387 | + File.delete(filename).should_not be_nil | ||
388 | + | ||
389 | + | ||
390 | + end | ||
391 | + | ||
392 | + it "should export idea data to a csv file" do | ||
393 | + filename = @aoi_question.export('ideas') | ||
394 | + | ||
395 | + filename.should_not be nil | ||
396 | + filename.should match /.*ideamarketplace_#{@aoi_question.id}_ideas[.]csv$/ | ||
397 | + File.exists?(filename).should be_true | ||
398 | + # Not specifying exact file syntax, it's likely to change frequently | ||
399 | + # | ||
400 | + rows = FasterCSV.read(filename) | ||
401 | + rows.first.should include("Idea ID") | ||
402 | + rows.first.should_not include("Skip ID") | ||
403 | + File.delete(filename).should_not be_nil | ||
404 | + | ||
405 | + end | ||
406 | + | ||
407 | + it "should raise an error when given an unsupported export type" do | ||
408 | + lambda { @aoi_question.export("blahblahblah") }.should raise_error | ||
409 | + end | ||
410 | + | ||
411 | + it "should export data and schedule a job to delete export after X days" do | ||
412 | + Delayed::Job.delete_all | ||
413 | + filename = @aoi_question.export_and_delete('votes', :delete_at => 2.days.from_now) | ||
414 | + | ||
415 | + Delayed::Job.count.should == 1 | ||
416 | + Delayed::Job.delete_all | ||
417 | + File.delete(filename).should_not be_nil | ||
418 | + | ||
419 | + end | ||
420 | 420 | ||
421 | after(:all) { truncate_all } | 421 | after(:all) { truncate_all } |
422 | end | 422 | end |