<commit_before>require 'spec_helper'

module Uno
  describe Game do
    let(:game) { Uno::Game.new }

    it 'Starts in a :waiting_to_start state' do
      expect(game.state).to be :waiting_to_start
    end

    context "While waiting to start..." do
      it "Don't start the game unless there are at least 2 players" do
        expect{
          game.start
        }.to raise_error(NotEnoughPlayersError)
      end

      it "Allow multiple players to join the game" do
        game.add_player("Char")
        game.add_player("angelphish")

        expect(game.players).to be_an Array

        expect(game.players[0]).to eq "Char"
        expect(game.players[1]).to eq "angelphish"

        expect(game.players.length).to eq 2
      end

      it "Do nothing if a player tries to join twice" do
        game.add_player("Char")
        game.add_player("Char")

        expect(game.players.length).to eq 1
      end

      it "Moves are not accepted" do
        expect{
          game.play("foo12", Uno::Card.new)
        }.to raise_error(GameHasNotStartedError)
      end
    end

    context "When the game is started with at least two players..." do
      let(:game){ Uno::Game.new }

      before(:each) do
        game.add_player Player.new("Char")
        game.add_player Player.new("angelphish")
      end

      it "Generate a deck to play with" do
        expect(Deck).to receive(:generate).and_call_original
        Uno::Game.new
      end

      it "Shuffle the deck" do
        expect_any_instance_of(Array).to receive(:shuffle!).and_call_original

        game.start
      end

      it "Deals 7 cards to each player" do
        game.start

        game.players.each do |player|
          expect(player.hand).to be_an Array
          expect(player.hand.size).to eq 7
        end
      end

      it "Place one card from the deck on the discard pile" do
        game.start

        expect(game.discard_pile).to be_an Array
        expect(game.discard_pile.length).to eq 1
        expect(game.discard_pile.last).to be_a Card
      end

      it "Place the remaining cards from the deck into a draw pile" do
        game.start

        expect(game.draw_pile).to be_an Array
        expect(game.draw_pile.length).to eq 93
        expect(game.draw_pile.last).to be_a Uno::Card
      end

      it "Determine a play order" do
        game.start

        expect(game.players).to be_an Array
        expect(game.players.count).to eq 2
      end

      it "Expose the current player" do
        game.start

        expect(game.current_player).to be_a Player
        expect(game.players.include?(game.current_player)).to be true
      end

      it "Begin in a :waiting_for_player_to_move state" do
        game.start
        expect(game.state).to be :waiting_for_player_to_move
      end

      it "Can't add players once the game has started" do
        game.start
        player_count = game.players.count

        new_player = Player.new("Gatecrasher")
        expect{game.add_player(new_player)}.to raise_error(GameHasStartedError)
        expect(game.players.count).to eq player_count
      end

      it "Can't restart the game once it's already started" do
        game.start

        expect{game.start}.to raise_error(GameHasStartedError)
      end
    end

    context "Move validation" do
      let(:game){ Uno::Game.new}

      before(:each) do
        game.add_player(Player.new("Char"))
        game.add_player(Player.new("angelphish"))
        game.start
      end

      it "Moves are only accepted from players who are in the game" do
        gatecrasher = Player.new("foo12")

        expect{
          game.play(gatecrasher, Uno::Card.new)
        }.to raise_error(NotPlayersTurnError)
      end

      it "A player cannot move unless it is their turn" do
        expect(game.current_player).to eq game.players[0]
        queuejumper = game.players[1]

        expect{
          game.play(queuejumper, Uno::Card.new)
        }.to raise_error(NotPlayersTurnError)
      end

      it "A player cannot play a card that is not in their hand" do
        expect{
          game.play(game.players[0], Uno::Card.new(:zero, :yellow))
        }.to raise_error(PlayerDoesNotHaveThatCardError)
      end

      it "Valid move: Playing a card matching the color of the card on top of the discard pile" do
        fake_card = spy("Card")
        expect(fake_card).to receive(:type).and_return(:one)
        expect(fake_card).to receive(:color).and_return(:red)
        expect(game.discard_pile).to receive(:last).and_return(fake_card)
        expect(game.current_player).to receive(:has_card?).at_least(:once).and_return(true)

        expect{
          game.play(game.current_player, Uno::Card.new(:zero, :red))
        }.not_to raise_error
      end

      it "Valid move: Playing a card matching the number of the card on top of the discard pile" do
        fake_card = spy("Card")
        expect(fake_card).to receive(:type).and_return(:one)
        expect(game.discard_pile).to receive(:last).and_return(fake_card)
        expect(game.current_player).to receive(:has_card?).at_least(:once).and_return(true)

        expect{
          game.play(game.current_player, Uno::Card.new(:one, :blue))
        }.not_to raise_error
      end

      it "Invalid move: Playing a card that does not match the color or number of the card on top of the discard pile" do
        fake_card = spy("Card")<commit_msg>Fixed a test that would fail intermittently. We are testing that the player can't play a card they don't have, but sometimes by the luck of the draw they are given that card when the test starts. Now we test for such a thing and take the card from them before the test begins.<commit_after>require 'spec_helper'

module Uno
  describe Game do
    let(:game) { Uno::Game.new }

    it 'Starts in a :waiting_to_start state' do
      expect(game.state).to be :waiting_to_start
    end

    context "While waiting to start..." do
      it "Don't start the game unless there are at least 2 players" do
        expect{
          game.start
        }.to raise_error(NotEnoughPlayersError)
      end

      it "Allow multiple players to join the game" do
        game.add_player("Char")
        game.add_player("angelphish")

        expect(game.players).to be_an Array

        expect(game.players[0]).to eq "Char"
        expect(game.players[1]).to eq "angelphish"

        expect(game.players.length).to eq 2
      end

      it "Do nothing if a player tries to join twice" do
        game.add_player("Char")
        game.add_player("Char")

        expect(game.players.length).to eq 1
      end

      it "Moves are not accepted" do
        expect{
          game.play("foo12", Uno::Card.new)
        }.to raise_error(GameHasNotStartedError)
      end
    end

    context "When the game is started with at least two players..." do
      let(:game){ Uno::Game.new }

      before(:each) do
        game.add_player Player.new("Char")
        game.add_player Player.new("angelphish")
      end

      it "Generate a deck to play with" do
        expect(Deck).to receive(:generate).and_call_original
        Uno::Game.new
      end

      it "Shuffle the deck" do
        expect_any_instance_of(Array).to receive(:shuffle!).and_call_original

        game.start
      end

      it "Deals 7 cards to each player" do
        game.start

        game.players.each do |player|
          expect(player.hand).to be_an Array
          expect(player.hand.size).to eq 7
        end
      end

      it "Place one card from the deck on the discard pile" do
        game.start

        expect(game.discard_pile).to be_an Array
        expect(game.discard_pile.length).to eq 1
        expect(game.discard_pile.last).to be_a Card
      end

      it "Place the remaining cards from the deck into a draw pile" do
        game.start

        expect(game.draw_pile).to be_an Array
        expect(game.draw_pile.length).to eq 93
        expect(game.draw_pile.last).to be_a Uno::Card
      end

      it "Determine a play order" do
        game.start

        expect(game.players).to be_an Array
        expect(game.players.count).to eq 2
      end

      it "Expose the current player" do
        game.start

        expect(game.current_player).to be_a Player
        expect(game.players.include?(game.current_player)).to be true
      end

      it "Begin in a :waiting_for_player_to_move state" do
        game.start
        expect(game.state).to be :waiting_for_player_to_move
      end

      it "Can't add players once the game has started" do
        game.start
        player_count = game.players.count

        new_player = Player.new("Gatecrasher")
        expect{game.add_player(new_player)}.to raise_error(GameHasStartedError)
        expect(game.players.count).to eq player_count
      end

      it "Can't restart the game once it's already started" do
        game.start

        expect{game.start}.to raise_error(GameHasStartedError)
      end
    end

    context "Move validation" do
      let(:game){ Uno::Game.new}

      before(:each) do
        game.add_player(Player.new("Char"))
        game.add_player(Player.new("angelphish"))
        game.start
      end

      it "Moves are only accepted from players who are in the game" do
        gatecrasher = Player.new("foo12")

        expect{
          game.play(gatecrasher, Uno::Card.new)
        }.to raise_error(NotPlayersTurnError)
      end

      it "A player cannot move unless it is their turn" do
        expect(game.current_player).to eq game.players[0]
        queuejumper = game.players[1]

        expect{
          game.play(queuejumper, Uno::Card.new)
        }.to raise_error(NotPlayersTurnError)
      end

      it "A player cannot play a card that is not in their hand" do
        allow(Rules).to receive(:card_can_be_played?).and_return(true)

        card_the_player_does_not_have = Uno::Card.new(:zero, :yellow)
        game.players[0].take_card_from_hand(card_the_player_does_not_have) if game.players[0].has_card?(card_the_player_does_not_have)

        expect{
          game.play(game.players[0], card_the_player_does_not_have)
        }.to raise_error(PlayerDoesNotHaveThatCardError)
      end

      it "Valid move: Playing a card matching the color of the card on top of the discard pile" do
        fake_card = spy("Card")
        expect(fake_card).to receive(:type).and_return(:one)
        expect(fake_card).to receive(:color).and_return(:red)
        expect(game.discard_pile).to receive(:last).and_return(fake_card)
        expect(game.current_player).to receive(:has_card?).at_least(:once).and_return(true)

        expect{
          game.play(game.current_player, Uno::Card.new(:zero, :red))
        }.not_to raise_error
      end

      it "Valid move: Playing a card matching the number of the card on top of the discard pile" do
        fake_card = spy("Card")
        expect(fake_card).to receive(:type).and_return(:one)
        expect(game.discard_pile).to receive(:last).and_return(fake_card)
        expect(game.current_player).to receive(:has_card?).at_least(:once).and_return(true)

        expect{
          game.play(game.current_player, Uno::Card.new(:one, :blue))
        }.not_to raise_error
      end

      it "Invalid move: Playing a card that does not match the color or number of the card on top of the discard pile" do
        fake_card = spy("Card")
{'fraction_non_alphanumeric': 0.09326880774307084, 'fraction_numerical': 0.0033435987681478224, 'mean_word_length': 2.41014101410141, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6479735', 'n_tokens_mistral': 3579, 'n_tokens_neox': 3398, 'n_words': 973}