# frozen_string_literal: true require 'rails_helper' RSpec.describe Booru::VotingEngine do before(:each) do @post = create(:post) @engine = Booru::VotingEngine.new(create(:user), @post) end it 'should upvote a post' do @engine.vote!(:up) expect(@post.upvotes_count).to eq 1 expect(@post.downvotes_count).to eq 0 expect(@post.score).to eq 1 end it 'should downvote a post' do @engine.vote!(:down) expect(@post.upvotes_count).to eq 0 expect(@post.downvotes_count).to eq 1 expect(@post.score).to eq -1 end it 'should upvote and then downvote a post' do @engine.vote!(:up) @engine.vote!(:down) expect(@post.upvotes_count).to eq 0 expect(@post.downvotes_count).to eq 1 expect(@post.score).to eq -1 end it 'should ignore duplicate votes' do @engine.vote!(:up) @engine.vote!(:up) expect(@post.upvotes_count).to eq 1 expect(@post.downvotes_count).to eq 0 expect(@post.score).to eq 1 end it 'should correctly unvote' do @engine.vote!(:up) @engine.unvote! expect(@post.upvotes_count).to eq 0 expect(@post.downvotes_count).to eq 0 expect(@post.score).to eq 0 end it 'should correctly toggle from no vote to an upvote' do @engine.toggle_vote!(:up) expect(@post.upvotes_count).to eq 1 expect(@post.downvotes_count).to eq 0 expect(@post.score).to eq 1 end it 'should correctly toggle from no vote to a downvote' do @engine.toggle_vote!(:down) expect(@post.upvotes_count).to eq 0 expect(@post.downvotes_count).to eq 1 expect(@post.score).to eq -1 end it 'should correctly toggle an upvote on and then off' do @engine.toggle_vote!(:up) @engine.toggle_vote!(:up) expect(@post.upvotes_count).to eq 0 expect(@post.downvotes_count).to eq 0 expect(@post.score).to eq 0 end it 'should correctly toggle from an upvote to a downvote' do @engine.toggle_vote!(:up) @engine.toggle_vote!(:down) expect(@post.upvotes_count).to eq 0 expect(@post.downvotes_count).to eq 1 expect(@post.score).to eq -1 end it 'should correctly count votes' do 1.upto(25) do |_n| direction = [:up, :down].sample @engine.vote!(direction) end expect(@post.score).to be_between(-1, 1) expect(@post.upvotes_count).to be_between(0, 1) expect(@post.downvotes_count).to be_between(0, 1) expect(@post.upvotes_count).to_not eq @post.downvotes_count end it 'should not cause an off-by-one error' do 1.upto(10) do |_n| Booru::VotingEngine.new(create(:user), @post).vote! :up end @engine.vote! :down expect(@post.score).to eq 9 expect(@post.upvotes_count).to eq 10 expect(@post.downvotes_count).to eq 1 end it 'should fave a post' do @engine.fave!(true) expect(@post.faves_count).to eq 1 expect(@post.upvotes_count).to eq 1 end it 'should hide a post' do @engine.hide!(true) expect(@post.hides_count).to eq 1 end it 'should toggle a fave on a post' do @engine.toggle_fave! expect(@post.faves_count).to eq 1 expect(@post.upvotes_count).to eq 1 end it 'should toggle a fave twice' do @engine.toggle_fave! @engine.toggle_fave! expect(@post.faves_count).to eq 0 expect(@post.upvotes_count).to eq 1 end # it "does not have a race condition" do # threads = [] # # 10.times do # threads << Process.fork { # user = create(:user) # engine = Booru::VotingEngine.new(user, @post) # 15.times do # engine.vote!([:up, :down].sample) # end # } # end # # threads.each { |t| Process.waitpid(t) } # # expect(@post.upvotes_count).to eq @post.upvotes.count # expect(@post.downvotes_count).to eq @post.downvotes.count # expect(@post.score).to eq @post.upvotes_count - @post.downvotes_count # end end