diff --git a/app/models/game.rb b/app/models/game.rb index 46b78378..d1a724fc 100644 --- a/app/models/game.rb +++ b/app/models/game.rb @@ -7,7 +7,6 @@ class Game < ActiveRecord::Base has_many :player_cards, through: :players has_many :plays, through: :players has_one :controlling_player - has_one :winner, :class_name => "Player", :primary_key => "winner_player_id" belongs_to :play_to_beat accepts_nested_attributes_for :players #validates :title, presence: true @@ -45,6 +44,14 @@ class Game < ActiveRecord::Base save end + def winner + begin + self.players.find(self.winner_player_id) + rescue + nil + end + end + def validate_startable @player_count = players.count errors[:players] = 'Must be at least 2 players.' if @player_count < 2 @@ -159,10 +166,7 @@ class Game < ActiveRecord::Base def over? return false unless self.started? - @inventory_counts = [] - self.players.each do |player| - @inventory_counts << player.inventory.count - end + @inventory_counts = self.players.map {|p| p.player_cards.count > 0 ? player.inventory.count : nil} @inventory_counts.include? 0 end diff --git a/app/models/play.rb b/app/models/play.rb index 512f86ae..a47dcf38 100644 --- a/app/models/play.rb +++ b/app/models/play.rb @@ -205,7 +205,7 @@ class Play < ActiveRecord::Base def contains_lowest_card? # Cards being played must include the lowest card - if (self.player_cards.include? self.game.lowest_card) == false + if (self.player_cards.first.value != self.game.lowest_card.value) errors.add(:player_cards, "First hand must contain the lowest card: #{game.lowest_card.to_s}") return false else diff --git a/app/models/user.rb b/app/models/user.rb index 02db516d..57c63c89 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -33,7 +33,7 @@ class User < ActiveRecord::Base @seats << table.seats.where(user_soft_token: self.soft_token) end @seats.flatten.each do |seat| - seat.player.destroy + seat.try(:player).try(:destroy) seat.user_id = nil seat.player_id = nil seat.user_soft_token = nil diff --git a/spec/features/end_of_games_spec.rb b/spec/features/end_of_games_spec.rb index 44c47894..588419be 100644 --- a/spec/features/end_of_games_spec.rb +++ b/spec/features/end_of_games_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' RSpec.feature "EndOfGames", type: :feature, js: true do # Given I am in a started game - before do + before(:each) do @game = setup_game @game.reload @player = @game.controlling_player @@ -13,26 +13,36 @@ RSpec.feature "EndOfGames", type: :feature, js: true do # And I play my last cards # Then I win the game scenario 'I win the game' do - # Play lowest card # Other players always pass # Play next lowest card # Repeat until out of cards - @player.inventory.each do |card| + while (@player.inventory.count > 0) do + card = @player.inventory.first find_card(card).click - click_button "Play Hand" - sleep 1 - visit current_url - @game.reload - @game.controlling_player_id = @player.id - @game.save - @game.reload - sleep 1 - visit current_url + + # Try to click the Play Hand button + # If this fails, reload the page + begin + click_button "Play Hand" + visit current_url + @game.reload + rescue + @game.reload + visit current_url + end + + if @game.controlling_player_id != @player.id + # Simulate other players passing + @game.controlling_player_id = @player.id + @game.save + @game.reload + end end - # Play my last card(s) + # After I play my last card(s) # Expect that I am the winner + @game.reload expect(@game.winner).to eq @player end diff --git a/spec/models/play_spec.rb b/spec/models/play_spec.rb index 556e2388..7b779e65 100644 --- a/spec/models/play_spec.rb +++ b/spec/models/play_spec.rb @@ -1,20 +1,7 @@ RSpec.describe Play, type: :model do - before(:all) do + before(:each) do @game = setup_game - @play = @game.controlling_player.plays.new - @play.game_id = @game.id - @play.save - end - - after(:each) do - #reset game - @game.reload - @game.play_to_beat_id = nil - - # reset play - @play.reload - @play.errors[:player_cards].clear - @play.game = @game + @play = @game.controlling_player.plays.new(game_id: @game.id) end subject { @play } @@ -71,17 +58,22 @@ RSpec.describe Play, type: :model do describe 'wins?' do context 'it does not beat the hand_to_beat' do it 'single' do + # TODO: Refactor "lowest card first" to FactoryGirl.create :game, hand_to_beat: @cards + # First hand must contain lowest card + @cards_to_play = @play.player.player_cards.order(:value).first + @play.player_cards = [@cards_to_play] + @play.save + @game.reload + # Play a high single card + @play = @game.controlling_player.plays.new(game_id: @game.id) @cards_to_play = @play.player.player_cards.order(:value).last - @play.reload - @play.player_cards << @cards_to_play + @play.player_cards = [@cards_to_play] @play.save @game.reload # Try to play a losing card - @losing_play = Play.new - @losing_play.player = @game.players.where.not(id: @game.controlling_player_id).last - @losing_play.game = @game + @losing_play = @game.controlling_player.plays.new(game_id: @game.id) @losing_play.player_cards << @losing_play.player.player_cards.order(:value).first expect(@losing_play.beats? @play).to eq(false) expect(@losing_play.hand_valid?).to eq(false) @@ -92,6 +84,12 @@ RSpec.describe Play, type: :model do end it 'double' do + # First hand must contain low card + @cards_to_play = @play.player.player_cards.order(:value).first + @play.player_cards = [@cards_to_play] + @play.save + @game.reload + @deck = Deck.new @cards_to_beat = [ @spade5 = PlayerCard.new(@deck.cards[8].instance_values), @@ -116,9 +114,7 @@ RSpec.describe Play, type: :model do expect(play.player_cards.length).to eq(2) end - @play.reload @game.reload - binding.pry unless !@play.valid? expect(@play.valid?).to eq(false) expect(@play.beats? @play_to_beat).to eq(false) @@ -144,9 +140,7 @@ RSpec.describe Play, type: :model do @spade5 = PlayerCard.new(@deck.cards[8].instance_values) ] - @play.reload @game.reload - binding.pry unless !@play.valid? expect(@play.valid?).to eq(false) @@ -161,6 +155,7 @@ RSpec.describe Play, type: :model do @play.save @game.reload + @play = @game.controlling_player.plays.new(game_id: @game.id) # next player plays their lowest card and beats the previous play @cards_to_play = @play.player.player_cards.order(:value).first @play.player_cards << @cards_to_play @@ -183,7 +178,8 @@ RSpec.describe Play, type: :model do @club3 ] - @play.player_cards << @cards_to_beat + @play = @game.controlling_player.plays.new(game_id: @game.id) + @play.player_cards = @cards_to_beat expect(@play.save).to be true @game.reload @game.controlling_player_id = @game.next_player_id @@ -288,16 +284,26 @@ RSpec.describe Play, type: :model do context 'when four cards are played' do it 'valid bomb against a 2' do + # TODO: Refactor "lowest card first" to FactoryGirl.create :game, hand_to_beat: @cards + # First hand must contain lowest card + @spade3 = @game.lowest_card + first_play = Play.new(game_id: @game.id, player_id: @game.controlling_player_id, player_cards: [@spade3]) + first_play.save + @game.reload + + # Setup play to beat @heart2 = PlayerCard.new(rank: '2', suit: 'Heart', value: 52, player_id: @game.next_player_id) @play_to_beat = Play.new(game_id: @game.id, player_id: @game.controlling_player_id, player_cards: [@heart2]) @play_to_beat.save - @game.play_to_beat_id = @play_to_beat.id + @game.reload + @spade3 = PlayerCard.new(value: 1, rank: "3", suit: "Spade") @club3 = PlayerCard.new(value: 2, rank: "3", suit: "Club") @diamond3 = PlayerCard.new(value: 3, rank: "3", suit: "Diamond") @heart3 = PlayerCard.new(value: 4, rank: "3", suit: "Heart") @cards_to_play = [@spade3, @club3, @diamond3, @heart3] - @play.player_cards << @cards_to_play + @play = @game.controlling_player.plays.new(game_id: @game.id) + @play.player_cards = @cards_to_play expect(@play.hand_type).to eq('bomb') expect(@play.valid?).to eq(true) end @@ -311,6 +317,7 @@ RSpec.describe Play, type: :model do @play_to_beat = Play.new(game_id: @game.id, player_id: @game.controlling_player_id, player_cards: @cards_to_beat) @play_to_beat.save @game.play_to_beat_id = @play_to_beat.id + @game.reload # Setup the play @spade4 = PlayerCard.new(rank: "4", suit: "Spade", value: 5) @@ -318,6 +325,7 @@ RSpec.describe Play, type: :model do @diamond4 = PlayerCard.new(rank: "4", suit: "Diamond", value: 7) @heart4 = PlayerCard.new(rank: "4", suit: "Heart", value: 8) @cards_to_play = [@spade4, @club4, @diamond4, @heart4] + @play = @game.controlling_player.plays.new(game_id: @game.id) @play.player_cards = @cards_to_play expect(@play.hand_type).to eq('bomb') @@ -326,16 +334,27 @@ RSpec.describe Play, type: :model do end it 'invalid bomb against a greater bomb' do + # Play lowest card first + @spade3 = @game.lowest_card + first_play = Play.new(game_id: @game.id, player_id: @game.controlling_player_id, player_cards: [@spade3]) + first_play.save + @game.reload + + # Create an Open Table, so every hand is valid. + @game.controlling_player_id = first_play.player_id + @game.save + #@game.reload + + # # Setup the play to beat @spade4 = PlayerCard.new(rank: "4", suit: "Spade", value: 5) @club4 = PlayerCard.new(rank: "4", suit: "Club", value: 6) @diamond4 = PlayerCard.new(rank: "4", suit: "Diamond", value: 7) @heart4 = PlayerCard.new(rank: "4", suit: "Heart", value: 8) @cards_to_beat = [@spade4, @club4, @diamond4, @heart4] - @play_to_beat = Play.new(game_id: @game.id, player_id: @game.next_player_id, player_cards: @cards_to_beat) - @play_to_beat.save - @game.play_to_beat_id = @play_to_beat.id - @play.reload + @play_to_beat = Play.new(game_id: @game.id, player_id: @game.controlling_player_id, player_cards: @cards_to_beat) + expect(@play_to_beat.save).to eq true + @game.reload # Setup the play @spade3 = PlayerCard.new(rank: "3", suit: "Spade", value: 1) @@ -343,9 +362,13 @@ RSpec.describe Play, type: :model do @diamond3 = PlayerCard.new(rank: "3", suit: "Diamond", value: 3) @heart3 = PlayerCard.new(rank: "3", suit: "Heart", value: 4) @cards_to_play = [@spade3, @club3, @diamond3, @heart3] - @play.player_cards = @cards_to_play + @play = Play.new(game_id: @game.id, player_id: @game.controlling_player_id, player_cards: @cards_to_beat) expect(@play.hand_type).to eq('bomb') + #TODO: Refactor this test to only test the @play.beats? method + #TODO: Move other expectations to another test + #TODO: Test every validation of a play + #TODO: Refactor @play.valid? method expect(@play.beats? @play_to_beat).to eq(false) expect(@play.valid?).to eq(false) end diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb index 1421b47a..056d14d4 100644 --- a/spec/support/capybara.rb +++ b/spec/support/capybara.rb @@ -11,5 +11,6 @@ if ENV['RAILS_ENV'] == 'staging' Capybara.app_host = asset_hosts[ENV['RAILS_ENV'].to_sym] end Capybara.asset_host = asset_hosts[ENV['RAILS_ENV'].to_sym] -#Capybara.asset_host = 'http://localhost:3000' -Capybara.javascript_driver = :poltergeist # :selenium + +Capybara.javascript_driver = :poltergeist +#Capybara.javascript_driver = :selenium