|
| 1 | +require_relative '../tictactoe.rb' |
| 2 | + |
| 3 | +describe Board do |
| 4 | + |
| 5 | + subject(:board) { described_class.new() } |
| 6 | + let(:player_one) { double('player', name: 'Michelle', symbol: 'X') } |
| 7 | + let(:player_two) { double('player', name: 'Carmen', symbol: 'O') } |
| 8 | + |
| 9 | + describe '#fill' do |
| 10 | + context 'when fill is called on a position' do |
| 11 | + it "fills the position with the right symbol" do |
| 12 | + horizontal, vertical = 1, 2 |
| 13 | + board.instance_variable_set(:@board, [[' ', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']]) |
| 14 | + board.fill(horizontal, vertical, 'O') |
| 15 | + symbol = board.get(horizontal, vertical) |
| 16 | + expect(symbol).to eq('O') |
| 17 | + end |
| 18 | + end |
| 19 | + end |
| 20 | + |
| 21 | + describe '#get' do |
| 22 | + context 'when get is called on a position' do |
| 23 | + it "returns the right symbol for the position" do |
| 24 | + horizontal, vertical = 0, 0 |
| 25 | + board.instance_variable_set(:@board, [['X', ' ', ' '], [' ', 'X', ' '], [' ', ' ', 'X']]) |
| 26 | + symbol = board.get(horizontal, vertical) |
| 27 | + expect(symbol).to eq('X') |
| 28 | + end |
| 29 | + end |
| 30 | + end |
| 31 | + |
| 32 | + describe '#win?' do |
| 33 | + context 'player wins with top row' do |
| 34 | + it 'returns true for that player' do |
| 35 | + board.instance_variable_set(:@board, [['X', 'X', 'X'], [' ', ' ', ' '], [' ', ' ', ' ']]) |
| 36 | + first_result = board.win?(player_one) |
| 37 | + second_result = board.win?(player_two) |
| 38 | + expect(first_result).to equal(true) |
| 39 | + expect(second_result).to equal(false) |
| 40 | + end |
| 41 | + end |
| 42 | + |
| 43 | + context 'player wins with middle row' do |
| 44 | + it 'returns true for that player' do |
| 45 | + board.instance_variable_set(:@board, [[' ', ' ', ' '], ['X', 'X', 'X'], [' ', ' ', ' ']]) |
| 46 | + first_result = board.win?(player_one) |
| 47 | + second_result = board.win?(player_two) |
| 48 | + expect(first_result).to equal(true) |
| 49 | + expect(second_result).to equal(false) |
| 50 | + end |
| 51 | + end |
| 52 | + |
| 53 | + context 'player wins with bottom row' do |
| 54 | + it 'returns true for that player' do |
| 55 | + board.instance_variable_set(:@board, [[' ', ' ', ' '], [' ', ' ', ' '], ['X', 'X', 'X']]) |
| 56 | + first_result = board.win?(player_one) |
| 57 | + second_result = board.win?(player_two) |
| 58 | + expect(first_result).to equal(true) |
| 59 | + expect(second_result).to equal(false) |
| 60 | + end |
| 61 | + end |
| 62 | + |
| 63 | + context 'player wins with top column' do |
| 64 | + it 'returns true for the player' do |
| 65 | + board.instance_variable_set(:@board, [['X', ' ', ' '], ['X', ' ', ' '], ['X', ' ', ' ']]) |
| 66 | + first_result = board.win?(player_one) |
| 67 | + second_result = board.win?(player_two) |
| 68 | + expect(first_result).to equal(true) |
| 69 | + expect(second_result).to equal(false) |
| 70 | + end |
| 71 | + end |
| 72 | + |
| 73 | + context 'player wins with middle column' do |
| 74 | + it 'returns true for the player' do |
| 75 | + board.instance_variable_set(:@board, [[' ', 'X', ' '], [' ', 'X', ' '], [' ', 'X', ' ']]) |
| 76 | + first_result = board.win?(player_one) |
| 77 | + second_result = board.win?(player_two) |
| 78 | + expect(first_result).to equal(true) |
| 79 | + expect(second_result).to equal(false) |
| 80 | + end |
| 81 | + end |
| 82 | + |
| 83 | + context 'player wins with bottom column' do |
| 84 | + it 'returns true for the player' do |
| 85 | + board.instance_variable_set(:@board, [[' ', ' ', 'X'], [' ', ' ', 'X'], [' ', ' ', 'X']]) |
| 86 | + first_result = board.win?(player_one) |
| 87 | + second_result = board.win?(player_two) |
| 88 | + expect(first_result).to equal(true) |
| 89 | + expect(second_result).to equal(false) |
| 90 | + end |
| 91 | + end |
| 92 | + |
| 93 | + context 'player wins with left diagonal' do |
| 94 | + it 'returns true for the player' do |
| 95 | + board.instance_variable_set(:@board, [['X', ' ', ' '], [' ', 'X', ' '], [' ', ' ', 'X']]) |
| 96 | + first_result = board.win?(player_one) |
| 97 | + second_result = board.win?(player_two) |
| 98 | + expect(first_result).to equal(true) |
| 99 | + expect(second_result).to equal(false) |
| 100 | + end |
| 101 | + end |
| 102 | + |
| 103 | + context 'player wins with right diagonal' do |
| 104 | + it 'returns true for the player' do |
| 105 | + board.instance_variable_set(:@board, [[' ', ' ', 'X'], [' ', 'X', ' '], ['X', ' ', ' ']]) |
| 106 | + first_result = board.win?(player_one) |
| 107 | + second_result = board.win?(player_two) |
| 108 | + expect(first_result).to equal(true) |
| 109 | + expect(second_result).to equal(false) |
| 110 | + end |
| 111 | + end |
| 112 | + end |
| 113 | + |
| 114 | + describe '#draw?' do |
| 115 | + context 'when the board is filled with no winner' do |
| 116 | + it 'return true' do |
| 117 | + board.instance_variable_set(:@board, [['X', 'O', 'X'], ['X', 'O', 'O'], ['O', 'X', 'O']]) |
| 118 | + result = board.draw? |
| 119 | + expect(result).to equal(true) |
| 120 | + end |
| 121 | + end |
| 122 | + end |
| 123 | + |
| 124 | + describe '#display' do |
| 125 | + # (Public Script Method) |
| 126 | + # Only contains puts statements -> No test necessary. |
| 127 | + end |
| 128 | +end |
| 129 | + |
| 130 | +describe Game do |
| 131 | + subject(:game) { described_class.new } |
| 132 | + subject(:position_game) { described_class.new } |
| 133 | + let(:player_one) { double('player', name: 'Michelle', symbol: 'X') } |
| 134 | + let(:player_two) { double('player', name: 'Carmen', symbol: 'O') } |
| 135 | + let(:board) { instance_double(Board) } |
| 136 | + |
| 137 | + describe '#play' do |
| 138 | + before do |
| 139 | + allow(game).to receive(:intro) |
| 140 | + allow(game).to receive(:receive_position).and_return([1, 2]) |
| 141 | + allow(board).to receive(:fill) |
| 142 | + end |
| 143 | + context 'when win? is true' do |
| 144 | + before do |
| 145 | + game.instance_variable_set(:@player1, player_one) |
| 146 | + game.instance_variable_set(:@player2, player_two) |
| 147 | + game.instance_variable_set(:@currentPlayer, player_one) |
| 148 | + game.instance_variable_set(:@board, board) |
| 149 | + |
| 150 | + allow(board).to receive(:win?).and_return(true) |
| 151 | + allow(board).to receive(:draw?) |
| 152 | + end |
| 153 | + it 'sends fill to board' do |
| 154 | + expect(board).to receive(:fill).with(0, 1, 'X') |
| 155 | + game.play |
| 156 | + end |
| 157 | + it 'draw? is never called' do |
| 158 | + expect(board).not_to receive(:draw?) |
| 159 | + game.play |
| 160 | + end |
| 161 | + end |
| 162 | + context 'when win? is false and then true' do |
| 163 | + before do |
| 164 | + game.instance_variable_set(:@player1, player_one) |
| 165 | + game.instance_variable_set(:@player2, player_two) |
| 166 | + game.instance_variable_set(:@currentPlayer, player_one) |
| 167 | + game.instance_variable_set(:@board, board) |
| 168 | + |
| 169 | + allow(board).to receive(:win?).and_return(false, true) |
| 170 | + allow(board).to receive(:draw?).and_return(false) |
| 171 | + end |
| 172 | + it 'calls draw once' do |
| 173 | + expect(board).to receive(:draw?).once |
| 174 | + game.play |
| 175 | + end |
| 176 | + it 'changes the state of currentPlayer' do |
| 177 | + expect {game.play}.to change {game.instance_variable_get(:@currentPlayer)} |
| 178 | + end |
| 179 | + end |
| 180 | + context 'when win? is false and draw? is true' do |
| 181 | + before do |
| 182 | + game.instance_variable_set(:@player1, player_one) |
| 183 | + game.instance_variable_set(:@player2, player_two) |
| 184 | + game.instance_variable_set(:@currentPlayer, player_one) |
| 185 | + game.instance_variable_set(:@board, board) |
| 186 | + |
| 187 | + allow(board).to receive(:win?).and_return(false) |
| 188 | + allow(board).to receive(:draw?).and_return(true) |
| 189 | + end |
| 190 | + it 'calls win? and draw? once' do |
| 191 | + expect(board).to receive(:draw?).once |
| 192 | + expect(board).to receive(:win?).once |
| 193 | + game.play |
| 194 | + end |
| 195 | + end |
| 196 | + end |
| 197 | + |
| 198 | + describe '#intro' do |
| 199 | + before do |
| 200 | + allow(game).to receive(:gets).and_return('Michelle') |
| 201 | + end |
| 202 | + context 'when intro is called' do |
| 203 | + it 'change the state of currentPlayer to player1' do |
| 204 | + expect {game.intro}.to change {game.instance_variable_get(:@currentPlayer)} |
| 205 | + end |
| 206 | + end |
| 207 | + end |
| 208 | + |
| 209 | + describe '#player_one_input' do |
| 210 | + context 'when player_one_input is called twice with an empty string and once with a valid string' do |
| 211 | + before do |
| 212 | + allow(game).to receive(:gets).and_return('', '', 'Michelle') |
| 213 | + end |
| 214 | + it 'return the first puts and 4 error puts (2 per empty string)' do |
| 215 | + expect(game).to receive(:puts).exactly(5).times |
| 216 | + game.player_one_input |
| 217 | + end |
| 218 | + it 'changes the state of player1' do |
| 219 | + expect {game.player_one_input}.to change {game.instance_variable_get(:@player1)} |
| 220 | + end |
| 221 | + end |
| 222 | + end |
| 223 | + |
| 224 | + describe '#player_two_input' do |
| 225 | + context 'when player_two_input is called once with an empty string and once with a valid string' do |
| 226 | + before do |
| 227 | + allow(game).to receive(:gets).and_return('', 'Carmen') |
| 228 | + end |
| 229 | + it 'return the first puts and 2 error puts (2 per empty string)' do |
| 230 | + expect(game).to receive(:puts).exactly(3).times |
| 231 | + game.player_two_input |
| 232 | + end |
| 233 | + it 'changes the state of player2' do |
| 234 | + expect {game.player_two_input}.to change {game.instance_variable_get(:@player2)} |
| 235 | + end |
| 236 | + end |
| 237 | + end |
| 238 | + |
| 239 | + describe '#horizontal_input' do |
| 240 | + context 'when horizontal input is called' do |
| 241 | + before do |
| 242 | + game.instance_variable_set(:@currentPlayer, player_one) |
| 243 | + horizontal = '2' |
| 244 | + allow(game).to receive(:gets).and_return(horizontal) |
| 245 | + end |
| 246 | + it 'returns the horizontal input' do |
| 247 | + horizontal_input = game.horizontal_input |
| 248 | + expect(horizontal_input).to eq(2) |
| 249 | + end |
| 250 | + end |
| 251 | + end |
| 252 | + |
| 253 | + describe '#vertical_input' do |
| 254 | + context 'when vertical input is called' do |
| 255 | + before do |
| 256 | + game.instance_variable_set(:@currentPlayer, player_one) |
| 257 | + vertical = '2' |
| 258 | + allow(game).to receive(:gets).and_return(vertical) |
| 259 | + end |
| 260 | + it 'returns the vertical input' do |
| 261 | + vertical_input = game.vertical_input |
| 262 | + expect(vertical_input).to eq(2) |
| 263 | + end |
| 264 | + end |
| 265 | + end |
| 266 | + |
| 267 | + describe '#position_taken?' do |
| 268 | + before do |
| 269 | + allow(board).to receive(:get).with(1, 2).and_return(' ') |
| 270 | + allow(board).to receive(:get).with(0, 1).and_return('X') |
| 271 | + end |
| 272 | + context 'when a position is not taken' do |
| 273 | + it 'returns false' do |
| 274 | + horizontal, vertical = 2, 3 |
| 275 | + game.instance_variable_set(:@board, board) |
| 276 | + taken = game.position_taken?(horizontal, vertical) |
| 277 | + expect(taken).to eq(false) |
| 278 | + end |
| 279 | + end |
| 280 | + context 'when a position is taken' do |
| 281 | + it 'returns true' do |
| 282 | + horizontal, vertical = 1, 2 |
| 283 | + game.instance_variable_set(:@board, board) |
| 284 | + taken = game.position_taken?(horizontal, vertical) |
| 285 | + expect(taken).to eq(true) |
| 286 | + end |
| 287 | + end |
| 288 | + end |
| 289 | + |
| 290 | + describe '#receive_position' do |
| 291 | + before do |
| 292 | + allow(board).to receive(:get).with(1, 2).and_return(' ') |
| 293 | + allow(game).to receive(:horizontal_input).and_return(0, 2, 2) |
| 294 | + allow(game).to receive(:vertical_input).and_return(0, 4, 3, 3) |
| 295 | + |
| 296 | + allow(position_game).to receive(:position_taken?).and_return(true, false) |
| 297 | + allow(position_game).to receive(:horizontal_input).and_return(2, 2) |
| 298 | + allow(position_game).to receive(:vertical_input).and_return(3, 3) |
| 299 | + end |
| 300 | + context 'horizontal input is invalid once then valid' do |
| 301 | + it 'call horizontal_input twice' do |
| 302 | + game.instance_variable_set(:@board, board) |
| 303 | + expect(game).to receive(:horizontal_input).twice |
| 304 | + game.receive_position |
| 305 | + end |
| 306 | + end |
| 307 | + context 'when vertical input is invalid twice then valid' do |
| 308 | + it 'call vertical_input three times' do |
| 309 | + game.instance_variable_set(:@board, board) |
| 310 | + expect(game).to receive(:vertical_input).exactly(3).times |
| 311 | + game.receive_position |
| 312 | + end |
| 313 | + end |
| 314 | + context 'when position_taken? returns false' do |
| 315 | + it 'repeats the loop a second time' do |
| 316 | + position_game.instance_variable_set(:@board, board) |
| 317 | + expect(position_game).to receive(:position_taken?).twice |
| 318 | + position_game.receive_position |
| 319 | + end |
| 320 | + end |
| 321 | + end |
| 322 | + |
| 323 | + describe '#verify_input' do |
| 324 | + # (Public Script Method) |
| 325 | + # Only contains puts statements + private -> No test necessary. |
| 326 | + end |
| 327 | +end |
0 commit comments