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 | 131 | |
| 132 | 132 | ['left', 'right'].each do |side| |
| 133 | 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 | 136 | end |
| 137 | 137 | end |
| 138 | 138 | |
| ... | ... | @@ -158,9 +158,9 @@ describe Question do |
| 158 | 158 | future_prompt_id_1 = @question_optional_information[:future_prompt_id_1] |
| 159 | 159 | |
| 160 | 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 | 165 | @aoi_clone.record_vote(vote_options) |
| 166 | 166 | |
| ... | ... | @@ -178,9 +178,9 @@ describe Question do |
| 178 | 178 | @question_optional_information[:average_votes].should be_close(0.0, 0.1) |
| 179 | 179 | |
| 180 | 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 | 185 | @aoi_clone.record_vote(vote_options) |
| 186 | 186 | @question_optional_information = @question.get_optional_information(params) |
| ... | ... | @@ -204,219 +204,219 @@ describe Question do |
| 204 | 204 | @question.choices.count.should == 3 |
| 205 | 205 | end |
| 206 | 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 | 295 | end |
| 296 | 296 | after(:all) { truncate_all } |
| 297 | 297 | end |
| 298 | 298 | |
| 299 | 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 | 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 | 323 | skip_options = {:visitor_identifier => visitor.identifier, |
| 324 | 324 | :appearance_lookup => @a.lookup, |
| 325 | 325 | :prompt => @p, |
| 326 | 326 | :time_viewed => rand(1000), |
| 327 | 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 | 421 | after(:all) { truncate_all } |
| 422 | 422 | end | ... | ... |