From 388e8bb2b1ae5745a6d8553b9e8ca406a58afccd Mon Sep 17 00:00:00 2001 From: "Jesse C. Fisher" Date: Tue, 18 Aug 2015 04:59:35 -0700 Subject: [PATCH] Basic feature spec for game play --- app/controllers/games_controller.rb | 56 ++++++----- app/models/play.rb | 2 +- app/views/games/show.html.haml | 7 +- spec/features/plays_spec.rb | 145 +++++++++++++++++----------- 4 files changed, 124 insertions(+), 86 deletions(-) diff --git a/app/controllers/games_controller.rb b/app/controllers/games_controller.rb index 31735710..f6d3e54b 100644 --- a/app/controllers/games_controller.rb +++ b/app/controllers/games_controller.rb @@ -24,39 +24,45 @@ class GamesController < ApplicationController # TODO: validate player's turn, current_user == @game.current_player.user # TODO: move this logic out of controller maybe to model(s) + if params[:game] + if params[:game][:hand_type] == 'pass' + @game.set_active_player 'next' + flash[:notice] = 'Successfully passed.' + @game.save + end + end + # If cards are played if params[:player_card_ids] @cards_to_play = @game.current_player.player_cards.order(:value).find(params[:player_card_ids]) - else - # No cards are played - @cards_to_play = [] - end - - # Instantiate the play - @play = @game.current_player.plays.new - @play.game_id = @game.id - @play.player_cards << @cards_to_play - @play.save - - #@cards_to_play.each do |card| - #@play.player_cards << card - #end - - if @play.save - # TODO: Ensure active player only changes when valid hand is played - @game.set_active_player 'next' - @game.save - else - # If play is invalid, remove the cards from the play - #@play.player_cards.map {|card| card.play_id = nil; card.save} - # Delete play - #@play.destroy - end + # Instantiate the play + @play = @game.current_player.plays.new + @play.game_id = @game.id + @play.player_cards << @cards_to_play + if @play.save + # TODO: Ensure active player only changes when valid hand is played + @game.set_active_player 'next' + @game.save + else + # If play is invalid, remove the cards from the play + #@play.player_cards.map {|card| card.play_id = nil; card.save} + # Delete play + #@play.destroy + end #@play.save @play.errors.messages.each do |key, msg| flash[key] = msg.join end + else + # No cards are played + @cards_to_play = [] + end + + #@cards_to_play.each do |card| + #@play.player_cards << card + #end + redirect_to(@game) # TODO: add current_hand logic diff --git a/app/models/play.rb b/app/models/play.rb index bf73c68f..87fd5469 100644 --- a/app/models/play.rb +++ b/app/models/play.rb @@ -39,7 +39,7 @@ class Play < ActiveRecord::Base if has_player_cards - @truths << !hand_type.empty? + @truths << !hand_type.nil? if first_play? @truths << contains_lowest_card? diff --git a/app/views/games/show.html.haml b/app/views/games/show.html.haml index a7c62952..ebb577e3 100644 --- a/app/views/games/show.html.haml +++ b/app/views/games/show.html.haml @@ -46,7 +46,7 @@ -# TODO better logic, not in view - unless @game.status == nil .table - - if @game.play_to_beat + - if @game.play_to_beat && @game.player_to_beat.user != current_user - if @game.play_to_beat.play %h1 Hand to beat @@ -70,4 +70,9 @@ // Provide id of current game -#= f.hidden_field :id = f.submit "Play Hand" + = form_for @game, :url => play_hand_game_path(@game) do |f| + // Provide id of current game + -#= f.hidden_field :id + = f.hidden_field :hand_type, value: 'pass' + = f.submit "Pass" diff --git a/spec/features/plays_spec.rb b/spec/features/plays_spec.rb index 824632bb..bdd67c15 100644 --- a/spec/features/plays_spec.rb +++ b/spec/features/plays_spec.rb @@ -3,6 +3,13 @@ include Warden::Test::Helpers Warden.test_mode! feature 'Play a hand', type: :feature do + before(:all) do + @game = setup_game + @player = @game.current_player + login_as(@player.user, scope: :user) + visit game_path @game + end + after(:each) do Warden.test_reset! end @@ -17,28 +24,24 @@ feature 'Play a hand', type: :feature do # expect successful play message # TODO: extract game setup to a factory - game = setup_game - login_as(game.current_player.user, scope: :user) - visit game_path game # Click the lowest card checkbox - @card_to_play = game.lowest_card + @card_to_play = @game.lowest_card check @card_to_play.to_s click_button 'Play Hand' - expect(page).to have_content('Played ' + game.lowest_card.to_s) + expect(page).to have_content('Played ' + @game.lowest_card.to_s) end scenario 'first play does not contain lowest card' do # current_player plays hand not containing lowest card # expect unsuccessful play message hand MUST contain lowest card - game = setup_game - login_as(game.current_player.user, scope: :user) - visit game_path game # Click the lowest card checkbox - @card_to_play = game.current_player.player_cards.order(:value).last + login_as(@game.current_player.user, scope: :user) + visit game_path @game + @card_to_play = @game.current_player.player_cards.order(:value).last check @card_to_play.to_s click_button 'Play Hand' - expect(page).to have_content "First hand must contain the lowest card: #{game.lowest_card.to_s}" - expect(game.play_to_beat).to eq(nil) + expect(page).to have_content "First hand must contain the lowest card: #{@game.lowest_card.to_s}" + expect(@game.play_to_beat).to eq(nil) end # Scenario: Played cards leave the players inventory @@ -46,18 +49,16 @@ feature 'Play a hand', type: :feature do # When I play a hand # Then the cards played should leave my inventory scenario 'played cards are removed from the players inventory' do - game = setup_game # Store initial state of players inventory - @player = game.current_player + login_as(@game.current_player.user, scope: :user) + visit game_path @game @player_inventory = @player.player_cards.order(:value).join(' ') @player_inventory = @player.inventory.order(:value).join(' ') - login_as(game.current_player.user, scope: :user) - visit game_path game - @card_to_play = game.current_player.player_cards.order(:value).first + @card_to_play = @game.current_player.player_cards.order(:value).first check @card_to_play.to_s click_button 'Play Hand' # Played hand is rendered - expect(page).to have_content('Played ' + game.lowest_card.to_s) + expect(page).to have_content('Played ' + @game.lowest_card.to_s) # Player inventory is rendered without played cards expect(page).to have_content(@player_inventory.gsub(@card_to_play.to_s,'')) # Player inventory method does not return played cards @@ -69,37 +70,33 @@ feature 'Play a hand', type: :feature do # When I play an invalid hand # Then the cards played should not leave my inventory scenario 'invalid hand played cards are not removed from the players inventory' do - game = setup_game # Store initial state of players inventory - @player = game.current_player @player_inventory = @player.player_cards.order(:value).join(' ') @player_inventory = @player.inventory.order(:value).join(' ') - login_as(game.current_player.user, scope: :user) - visit game_path game + login_as(@game.current_player.user, scope: :user) + visit game_path @game # Play invalid hand - @card_to_play = game.current_player.player_cards.order(:value).last + @card_to_play = @game.current_player.player_cards.order(:value).last check @card_to_play.to_s click_button 'Play Hand' # Played hand is rendered - expect(page).to have_content("First hand must contain the lowest card: #{game.lowest_card.to_s}") + expect(page).to have_content("First hand must contain the lowest card: #{@game.lowest_card.to_s}") # Player inventory is rendered with played cards expect(page).to have_content(@player_inventory) # Player inventory method does return played cards expect(@player.inventory.order(:value).join(' ')).to have_content(@card_to_play.to_s) end - # Scenario: Current player status updates after successful play # Given I am the current player # When I play a hand # Then the next player becomes the current player scenario 'active player rotates after a valid hand' do - @game = setup_game - login_as(@game.active_player.user, scope: :user) + login_as(@player.user, scope: :user) + visit game_path @game @next_player_id = @game.next_player_id @active_player_id = @game.active_player.id @active_player_index = @game.players.index(@game.active_player) - visit game_path @game @card_to_play = @game.active_player.player_cards.order(:value).first check @card_to_play.to_s click_button 'Play Hand' @@ -115,42 +112,23 @@ feature 'Play a hand', type: :feature do expect(@game.active_player_id).to eq(@next_player_id) end - # Scenario: Player can play a valid hand on their turn - # Given I am the active player - # And the last played card was a single card - # When I play a valid hand of one higher card - # Then I see a successful play message - scenario 'active player can play a valid hand' do - skip 'to be implemented' - # create game with players - game = setup_game - # current_player plays the lowest card - login_as(game.current_player.user, scope: :user) - visit game_path game - @card_to_play = game.lowest_card - check @card_to_play.to_s - click_button 'Play Hand' - expect(page).to have_content('Played ' + game.lowest_card.to_s) - # next player plays a valid hand - login_as(game.current_player.user, scope: :user) - visit game_path game - expect(page).to have_content('Played ' + game.lowest_card.to_s) - @card_to_play = game.current_player.player_cards.order(:value).first - check @card_to_play.to_s - click_button 'Play Hand' - expect(page).to have_content('Played ' + @card_to_play.to_s) - # expect successful play message - end - # Scenario: Player can not play an invalid hand on their turn # Given I am the active player # When I play an invalid hand # Then I see an invalid hand message - scenario 'active player can play a valid hand' do - # create game with players + scenario 'active player can not play an invalid hand' do + login_as(@player.user, scope: :user) + visit game_path @game + @cards_to_play = [@player.player_cards.order(:value).first.to_s, @player.player_cards.order(:value).last.to_s] + @cards_to_play.each do |card| + check card + end + click_button 'Play Hand' # current_player plays an invalid hand # expect invalid hand message - skip 'to be implemented' + expect(page).to have_content("Invalid pair.") + # expect inventory to remain unchanged + expect(page).to have_content("#{@player.inventory.map {|c| c.to_s}.join ' '}") end # Scenario: Player can not play a hand when it is not their turn @@ -160,7 +138,56 @@ feature 'Play a hand', type: :feature do scenario 'inactive player can not play a hand' do # create game with players # not_current_player plays a valid hand - # expect unsuccessful play message - skip 'to be implemented' + # expect not to be able to submit a play + @inactive_player = @game.players.where.not(id: @game.current_player_id).first + login_as(@inactive_player.user, scope: :user) + visit game_path @game + expect(page).to_not have_button 'Play Hand' + # TODO: Submit a POST request end + + # Scenario: Player can pass when it is their turn + # Given I am the active player + # When I pass + # Then I see an successful pass message + scenario 'active player can pass' do + login_as(@player.user, scope: :user) + visit game_path @game + @current_user = @game.current_player + click_button 'Pass' + expect(page).to have_content 'Successfully passed.' + # Expect active player should rotate + expect(page).to_not have_button 'Play Hand' + @new_current_player = @game.current_player + expect(@game.current_player).to_not eq(@current_player) + end + + # Scenario: Player can play any hand when they are the player to beat + # Given I am the active player + # And I am the player to beat + # Then I see an open table + scenario 'active player to beat has open table' do + login_as(@player.user, scope: :user) + visit game_path @game + @card_to_play = @game.lowest_card + check @card_to_play.to_s + click_button 'Play Hand' + @game.reload + + 3.times do + login_as(@game.active_player.user, scope: :user) + visit game_path @game + click_button 'Pass' + expect(page).to_not have_button 'Play Hand' + @game.reload + end + + login_as(@game.active_player.user, scope: :user) + visit game_path @game + # Expect active player should rotate + expect(page).to have_button 'Play Hand' + #expect(@game.player_to_beat).to eq(@game.active_player) + expect(page).to have_content 'Open table' + end + end