diff --git a/.rubocop.yml b/.rubocop.yml index e275936..eecbf55 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -15,7 +15,6 @@ AllCops: - 'spec/factories.rb' - 'node_modules/**/*' - 'app/models/user.rb' - - 'app/models/piece.rb' Metrics/BlockLength: IgnoredMethods: ['describe', 'context', 'it'] @@ -28,3 +27,9 @@ Style/FrozenStringLiteralComment: Documentation: Enabled: false + +Metrics/ClassLength: + Enabled: false + +Layout/LineLength: + Enabled: false diff --git a/app/models/piece.rb b/app/models/piece.rb index 5c7fb01..dd20bfd 100644 --- a/app/models/piece.rb +++ b/app/models/piece.rb @@ -2,246 +2,201 @@ class Piece < ApplicationRecord belongs_to :game def update_x_and_y - self.update_attribute(:x, self.destination_x) - self.update_attribute(:y, self.destination_y) + update(x: destination_x, y: destination_y) end def capture_piece - self.game.pieces.each do |piece| - if self != piece - if piece.x == self.x && piece.y == self.y - piece.update_attribute(:x, 100) - piece.update_attribute(:in_play, false) - end - end + game.pieces.each do |piece| + next if self == piece + + piece.update(x: 100, in_play: false) if piece.x == x && piece.y == y end end def horizontal_move? - self.destination_y == self.y && self.destination_x != self.x + destination_y == y && destination_x != x end def verticle_move? - self.destination_y != self.y && self.destination_x == self.x + destination_y != y && destination_x == x end def diagonal_move? - (self.x - self.destination_x).abs == (self.y - self.destination_y).abs + (x - destination_x).abs == (y - destination_y).abs end def king_move? - distance_of_x = (self.destination_x - self.x).abs - distance_of_y = (self.destination_y - self.y).abs + distance_of_x = (destination_x - x).abs + distance_of_y = (destination_y - y).abs return [0, 1].include?(distance_of_x) if distance_of_y == 1 - return distance_of_x == 1 if distance_of_y.zero? + + distance_of_x == 1 if distance_of_y.zero? end def knight_move? - distance_of_x = (self.destination_x - self.x).abs - distance_of_y = (self.destination_y - self.y).abs + distance_of_x = (destination_x - x).abs + distance_of_y = (destination_y - y).abs return distance_of_y == 1 if distance_of_x == 2 - return distance_of_y == 2 if distance_of_x == 1 - end - - def get_horizontal_or_verticle_path - coordinates = [] - if self.destination_x != self.x - x_value = self.x + 1 if self.destination_x > self.x - x_value = self.x - 1 if self.destination_x < self.x - while x_value != self.destination_x - coordinates.push([x_value, self.y]) - x_value += 1 if self.destination_x > self.x - x_value -= 1 if self.destination_x < self.x - end + + distance_of_y == 2 if distance_of_x == 1 + end + + def horizontal_or_verticle_path + if x != destination_x + horizontal_path else - y_value = self.y + 1 if self.destination_y > self.y - y_value = self.y - 1 if self.destination_y < self.y - while y_value != self.destination_y - coordinates.push([self.x, y_value]) - y_value += 1 if self.destination_y > self.y - y_value -= 1 if self.destination_y < self.y - end + verticle_path end - coordinates - end - - def get_diagonal_path - coordinates = [] - if self.destination_x > self.x - x_value = self.x + 1 - y_value = self.y + 1 if self.destination_y > self.y - y_value = self.y - 1 if self.destination_y < self.y - while x_value < self.destination_x - coordinates.push([x_value, y_value]) - x_value += 1 - y_value += 1 if self.destination_y > self.y - y_value -= 1 if self.destination_y < self.y - end + end + + def range(value, destination_value) + if destination_value > value + ((value + 1)..(destination_value - 1)).to_a else - x_value = self.x - 1 - y_value = self.y - 1 if self.destination_y < self.y - y_value = self.y + 1 if self.destination_y > self.y - while x_value > self.destination_x - coordinates.push([x_value, y_value]) - x_value -= 1 - y_value -= 1 if self.destination_y < self.y - y_value += 1 if self.destination_y > self.y - end + ((destination_value + 1)..(value - 1)).to_a + end + end + + def horizontal_path + range(x, destination_x).map do |x_value| + [x_value, y] + end + end + + def verticle_path + range(y, destination_y).map do |y_value| + [x, y_value] + end + end + + def diagonal_path + y_values = diagonal_y_values + range(x, destination_x).map.with_index do |x_value, index| + [x_value, y_values[index]] end - coordinates + end + + def diagonal_y_values + y_values = range(y, destination_y) + if destination_x > x + y_values = y_values.reverse if destination_y < y + elsif destination_y > y + y_values = y_values.reverse + end + y_values end def path_clear?(path) path.each do |coord_pair| - self.game.pieces.each do |piece| - if piece.x == coord_pair[0] && piece.y == coord_pair[1] - return false - end + game.pieces.each do |piece| + return false if piece.x == coord_pair.first && piece.y == coord_pair.last end end true end def friendly_capture? - self.game.pieces.each do |piece| - if piece.x == self.destination_x && piece.y == self.destination_y - return piece.color == self.color - end + game.pieces.each do |piece| + return piece.color == color if piece.x == destination_x && piece.y == destination_y end false end def tile_has_piece?(tile_x, tile_y) - self.game.pieces.each do |piece| - if piece.x == tile_x && piece.y == tile_y - return true - end + game.pieces.each do |piece| + return true if piece.x == tile_x && piece.y == tile_y end false end def forward_pawn_move?(operation) - if self.x == self.destination_x - if self.destination_y == self.y.send(operation, 1) - !self.tile_has_piece?(self.destination_x, self.destination_y) - end - end + x == destination_x && + destination_y == y.send(operation, 1) && + !tile_has_piece?(destination_x, destination_y) end def double_jump?(operation, starting_y) - if self.x == self.destination_x - if self.y == starting_y - if self.destination_y == starting_y.send(operation, 2) - !self.tile_has_piece?(self.destination_x, self.destination_y) && - !self.tile_has_piece?(self.destination_x, self.y.send(operation, 1)) - end - end - end + x == destination_x && + y == starting_y && + destination_y == starting_y.send(operation, 2) && + !tile_has_piece?(destination_x, destination_y) && + !tile_has_piece?(destination_x, y.send(operation, 1)) end def pawn_capturing?(operation) - if self.destination_y == self.y.send(operation, 1) - if [self.x + 1, self.x - 1].include?(self.destination_x) - self.tile_has_piece?(self.destination_x, self.destination_y) - end - end + destination_y == y.send(operation, 1) && + [x + 1, x - 1].include?(destination_x) && + tile_has_piece?(destination_x, destination_y) end def promoted?(origional_piece_type) - origional_piece_type != self.piece_type + origional_piece_type != piece_type end def on_row?(promotion_row) - self.y == promotion_row + y == promotion_row end def current_turn?(current_user) - if self.game.whites_turn - return current_user.username == self.game.as_white - else - current_user.username == self.game.as_black - end + return current_user.username == game.as_white if game.whites_turn + + current_user.username == game.as_black end def correct_color?(current_user) - if self.color === "white" - return current_user.username == self.game.as_white + return current_user.username == game.as_white if color == "white" + + current_user.username == game.as_black + end + + def move_horizontaly_or_vertically + return unless horizontal_move? || verticle_move? + + update_x_and_y && game.invert_turn if path_clear?(horizontal_or_verticle_path) + end + + def move_diagonally + return unless diagonal_move? + + update_x_and_y && game.invert_turn if path_clear?(diagonal_path) + end + + def move_queen + move_diagonally || move_horizontaly_or_vertically + end + + def move_king + update_x_and_y && game.invert_turn if king_move? + end + + def move_knight + update_x_and_y && game.invert_turn if knight_move? + end + + def handle_pawn_movement + if color == "white" + move_pawn(:+, 8, 2) else - current_user.username == self.game.as_black + move_pawn(:-, 1, 7) end end - def valid_move?(current_user) - if self.correct_color?(current_user) - if !self.friendly_capture? && self.current_turn?(current_user) - if self.piece_type == "rook" - if self.horizontal_move? || self.verticle_move? - if self.path_clear?(self.get_horizontal_or_verticle_path) - self.update_x_and_y - self.game.invert_turn - end - end - end - if self.piece_type == "bishop" - if self.diagonal_move? - if self.path_clear?(self.get_diagonal_path) - self.update_x_and_y - self.game.invert_turn - end - end - end - if self.piece_type == "queen" - if self.diagonal_move? - if self.path_clear?(self.get_diagonal_path) - self.update_x_and_y - self.game.invert_turn - end - end - if self.horizontal_move? || self.verticle_move? - if self.path_clear?(self.get_horizontal_or_verticle_path) - self.update_x_and_y - self.game.invert_turn - end - end - end - if self.piece_type == "king" - if self.king_move? - self.update_x_and_y - self.game.invert_turn - end - end - if self.piece_type == "knight" - if self.knight_move? - self.update_x_and_y - self.game.invert_turn - end - end - if self.piece_type == "pawn" - if self.color == "white" - if self.forward_pawn_move?(:+) || self.pawn_capturing?(:+) - self.update_x_and_y - if !self.on_row?(8) - self.game.invert_turn - end - end - if self.double_jump?(:+, 2) - self.update_x_and_y - self.game.invert_turn - end - else - if self.forward_pawn_move?(:-) || self.pawn_capturing?(:-) - self.update_x_and_y - if !self.on_row?(1) - self.game.invert_turn - end - end - if self.double_jump?(:-, 7) - self.update_x_and_y - self.game.invert_turn - end - end - end - end + def move_pawn(operation, promotion_row, starting_row) + if forward_pawn_move?(operation) || pawn_capturing?(operation) + update_x_and_y + game.invert_turn unless on_row?(promotion_row) end + update_x_and_y && game.invert_turn if double_jump?(operation, starting_row) + end + + def valid_move?(current_user) + return unless correct_color?(current_user) && !friendly_capture? && current_turn?(current_user) + + move_horizontaly_or_vertically if piece_type == "rook" + move_diagonally if piece_type == "bishop" + move_queen if piece_type == "queen" + move_king if piece_type == "king" + move_knight if piece_type == "knight" + handle_pawn_movement if piece_type == "pawn" end end diff --git a/spec/models/piece_spec.rb b/spec/models/piece_spec.rb index 802708c..4277f7f 100644 --- a/spec/models/piece_spec.rb +++ b/spec/models/piece_spec.rb @@ -2,7 +2,7 @@ RSpec.describe Piece, type: :model do describe "update_x_and_y function" do - it "should update the x and y attributes" do + it "should update the x and y attributes", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update_x_and_y expect(piece.x).to eq 4 @@ -11,132 +11,181 @@ end describe "capture_piece function" do - it "should remove any pieces that have matching coordinates from play" do + it "should remove any pieces that have matching coordinates from play", :aggregate_failures do game = FactoryBot.create(:game) - game.pieces.create(x: 1, y: 2) - piece = FactoryBot.create(:piece) - piece.update(x: 1) - piece.update(y: 2) - game.pieces.push(piece) - piece.capture_piece - expect(game.pieces.first.in_play).to eq false - expect(game.pieces.first.x).to eq 100 + first_piece = game.pieces.create(x: 1, y: 2) + second_piece = game.pieces.create(x: 1, y: 2) + second_piece.capture_piece + expect(first_piece.in_play).to eq false + expect(first_piece.x).to eq 100 end - it "should only capture pieces with matching coordinates" do + it "should only capture pieces with matching coordinates", :aggregate_failures do game = FactoryBot.create(:game) - game.pieces.create(x: 1, y: 2) - piece = FactoryBot.create(:piece) - game.pieces.push(piece) - piece.capture_piece - expect(game.pieces.first.in_play).to eq true - expect(game.pieces.first.x).to eq 1 + first_piece = game.pieces.create(x: 1, y: 2) + second_piece = game.pieces.create(x: 5, y: 5) + second_piece.capture_piece + expect(first_piece.in_play).to eq true + expect(first_piece.x).to eq 1 end - it "should not capture itself" do - game = FactoryBot.create(:game) + it "should not capture itself", :aggregate_failures do + FactoryBot.create(:game) piece = FactoryBot.create(:piece) - game.pieces.push(piece) piece.capture_piece - expect(game.pieces.first.in_play).to eq true - expect(game.pieces.first.x).to eq 5 + expect(piece.in_play).to eq true + expect(piece.x).to eq 5 end end - describe "get_horizontal_or_verticle_path function" do - it "should collect a list of coordinates when going west to east" do + describe "horizontal_or_verticle_path function" do + it "should collect a list of coordinates when going left to right", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(x: 1) piece.update(y: 4) piece.update(destination_x: 8) piece.update(destination_y: 4) - expect(piece.get_horizontal_or_verticle_path).to eq [[2, 4], [3, 4], [4, 4], [5, 4], [6, 4], [7, 4]] + coordinates = piece.horizontal_or_verticle_path + expect(coordinates.length).to eq 6 + expect(coordinates.include?([2, 4])).to eq true + expect(coordinates.include?([3, 4])).to eq true + expect(coordinates.include?([4, 4])).to eq true + expect(coordinates.include?([5, 4])).to eq true + expect(coordinates.include?([6, 4])).to eq true + expect(coordinates.include?([7, 4])).to eq true end - it "should collect a list of coordinates when going east to west" do + it "should collect a list of coordinates when going right to left", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(x: 8) piece.update(y: 4) piece.update(destination_x: 1) piece.update(destination_y: 4) - expect(piece.get_horizontal_or_verticle_path).to eq [[7, 4], [6, 4], [5, 4], [4, 4], [3, 4], [2, 4]] + coordinates = piece.horizontal_or_verticle_path + expect(coordinates.length).to eq 6 + expect(coordinates.include?([7, 4])).to eq true + expect(coordinates.include?([6, 4])).to eq true + expect(coordinates.include?([5, 4])).to eq true + expect(coordinates.include?([4, 4])).to eq true + expect(coordinates.include?([3, 4])).to eq true + expect(coordinates.include?([2, 4])).to eq true end - it "should collect a list of coordinates when going south to north" do + it "should collect a list of coordinates when going upwards", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(x: 1) piece.update(y: 1) piece.update(destination_x: 1) piece.update(destination_y: 8) - expect(piece.get_horizontal_or_verticle_path).to eq [[1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [1, 7]] + coordinates = piece.horizontal_or_verticle_path + expect(coordinates.length).to eq 6 + expect(coordinates.include?([1, 2])).to eq true + expect(coordinates.include?([1, 3])).to eq true + expect(coordinates.include?([1, 4])).to eq true + expect(coordinates.include?([1, 5])).to eq true + expect(coordinates.include?([1, 6])).to eq true + expect(coordinates.include?([1, 7])).to eq true end - it "should collect a list of coordinates when going north to south" do + it "should collect a list of coordinates when going downwards", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(x: 1) piece.update(y: 8) piece.update(destination_x: 1) piece.update(destination_y: 1) - expect(piece.get_horizontal_or_verticle_path).to eq [[1, 7], [1, 6], [1, 5], [1, 4], [1, 3], [1, 2]] + coordinates = piece.horizontal_or_verticle_path + expect(coordinates.length).to eq 6 + expect(coordinates.include?([1, 7])).to eq true + expect(coordinates.include?([1, 6])).to eq true + expect(coordinates.include?([1, 5])).to eq true + expect(coordinates.include?([1, 4])).to eq true + expect(coordinates.include?([1, 3])).to eq true + expect(coordinates.include?([1, 2])).to eq true end end - describe "get_diagonal_path function" do - it "should collect a list of coordinates when going north west" do + describe "diagonal_path function" do + it "should collect a list of coordinates when going north west", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(x: 8) piece.update(y: 1) piece.update(destination_x: 1) piece.update(destination_y: 8) - expect(piece.get_diagonal_path).to eq [[7, 2], [6, 3], [5, 4], [4, 5], [3, 6], [2, 7]] + coordinates = piece.diagonal_path + expect(coordinates.length).to eq 6 + expect(coordinates.include?([7, 2])).to eq true + expect(coordinates.include?([6, 3])).to eq true + expect(coordinates.include?([5, 4])).to eq true + expect(coordinates.include?([4, 5])).to eq true + expect(coordinates.include?([3, 6])).to eq true + expect(coordinates.include?([2, 7])).to eq true end - it "should collect a list of coordinates when going south east" do + it "should collect a list of coordinates when going south east", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(x: 1) piece.update(y: 8) piece.update(destination_x: 8) piece.update(destination_y: 1) - expect(piece.get_diagonal_path).to eq [[2, 7], [3, 6], [4, 5], [5, 4], [6, 3], [7, 2]] + coordinates = piece.diagonal_path + expect(coordinates.length).to eq 6 + expect(coordinates.include?([2, 7])).to eq true + expect(coordinates.include?([3, 6])).to eq true + expect(coordinates.include?([4, 5])).to eq true + expect(coordinates.include?([5, 4])).to eq true + expect(coordinates.include?([6, 3])).to eq true + expect(coordinates.include?([7, 2])).to eq true end - it "should collect a list of coordinates when going north east" do + it "should collect a list of coordinates when going north east", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(x: 1) piece.update(y: 1) piece.update(destination_x: 8) piece.update(destination_y: 8) - expect(piece.get_diagonal_path).to eq [[2, 2], [3, 3], [4, 4], [5, 5], [6, 6], [7, 7]] + coordinates = piece.diagonal_path + expect(coordinates.length).to eq 6 + expect(coordinates.include?([2, 2])).to eq true + expect(coordinates.include?([3, 3])).to eq true + expect(coordinates.include?([4, 4])).to eq true + expect(coordinates.include?([5, 5])).to eq true + expect(coordinates.include?([6, 6])).to eq true + expect(coordinates.include?([7, 7])).to eq true end - it "should collect a list of coordinates when going south west" do + it "should collect a list of coordinates when going south west", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(x: 8) piece.update(y: 8) piece.update(destination_x: 1) piece.update(destination_y: 1) - expect(piece.get_diagonal_path).to eq [[7, 7], [6, 6], [5, 5], [4, 4], [3, 3], [2, 2]] + coordinates = piece.diagonal_path + expect(coordinates.length).to eq 6 + expect(coordinates.include?([2, 2])).to eq true + expect(coordinates.include?([3, 3])).to eq true + expect(coordinates.include?([4, 4])).to eq true + expect(coordinates.include?([5, 5])).to eq true + expect(coordinates.include?([6, 6])).to eq true + expect(coordinates.include?([7, 7])).to eq true end end describe "path_clear? function" do it "should return false if any piece coordinates match any of the given path coordinates" do game = FactoryBot.create(:game) - piece = FactoryBot.create(:piece) - game.pieces.push(piece) - expect(game.pieces.first.path_clear?([[5, 4], [5, 5], [5, 6]])).to eq false + piece = FactoryBot.create(:piece, game_id: game.id) + expect(piece.path_clear?([[5, 4], [5, 5], [5, 6]])).to eq false end it "should return true if no piece coordinates match any of the given path coordinates" do game = FactoryBot.create(:game) - piece = FactoryBot.create(:piece) - game.pieces.push(piece) - expect(game.pieces.first.path_clear?([[1, 4], [1, 5], [1, 6]])).to eq true + piece = FactoryBot.create(:piece, game_id: game.id) + expect(piece.path_clear?([[1, 4], [1, 5], [1, 6]])).to eq true end end describe "horizontal_move? function" do - it "should return true if the starting and ending coordinates are horizontal" do + it "should return true if the starting and ending coordinates are horizontal", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(destination_x: 8) piece.update(destination_y: 5) @@ -146,7 +195,7 @@ expect(piece.horizontal_move?).to eq true end - it "should return false if the starting and ending coordinates are not directly horizontal" do + it "should return false if the starting and ending coordinates are not horizontal", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(destination_x: 8) piece.update(destination_y: 7) @@ -158,7 +207,7 @@ end describe "verticle_move? function" do - it "should return true if the starting and ending coordinates are verticle" do + it "should return true if the starting and ending coordinates are verticle", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(destination_x: 5) piece.update(destination_y: 8) @@ -168,7 +217,7 @@ expect(piece.verticle_move?).to eq true end - it "should return false if the starting and ending coordinates are not directly verticle" do + it "should return false if the starting and ending coordinates are not verticle", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(destination_x: 7) piece.update(destination_y: 8) @@ -180,7 +229,7 @@ end describe "diagonal_move? function" do - it "should return true if the starting and ending coordinates are diagonal" do + it "should return true if the starting and ending coordinates are diagonal", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(destination_x: 7) piece.update(destination_y: 7) @@ -196,7 +245,7 @@ expect(piece.diagonal_move?).to eq true end - it "should return false if the starting and ending coordinates are not diagonal" do + it "should return false if the starting and ending coordinates are not diagonal", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(destination_x: 2) piece.update(destination_y: 1) @@ -214,7 +263,7 @@ end describe "king_move? function" do - it "should return true if the ending coordinates directly border the king" do + it "should return true if the destination coordinates directly border the king", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(destination_x: 5) piece.update(destination_y: 4) @@ -242,7 +291,7 @@ expect(piece.king_move?).to eq true end - it "should not return true if the ending coordinates do not directly border the king" do + it "should not return true if the destination coordinates do not border the king", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(destination_x: 8) piece.update(destination_y: 8) @@ -263,7 +312,7 @@ end describe "knight_move? function" do - it "should return true if the move being requested is that of a knight" do + it "should return true if the move being requested is that of a knight", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(destination_x: 3) piece.update(destination_y: 6) @@ -291,7 +340,7 @@ expect(piece.knight_move?).to eq true end - it "should not return true if the move being requested is not that of a knight" do + it "should not return true if the move being requested is not that of a knight", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(destination_x: 8) piece.update(destination_y: 8) @@ -318,64 +367,58 @@ it "should return true if a piece's destination is occupied by a friendly piece" do game = FactoryBot.create(:game) game.pieces.create(x: 4, y: 4, color: "black") - piece = FactoryBot.create(:piece) - game.pieces.push(piece) + piece = FactoryBot.create(:piece, game_id: game.id) expect(piece.friendly_capture?).to eq true end it "should return false if a piece's destination is occupied by an opposing piece" do game = FactoryBot.create(:game) game.pieces.create(x: 4, y: 4, color: "white") - piece = FactoryBot.create(:piece) - game.pieces.push(piece) + piece = FactoryBot.create(:piece, game_id: game.id) expect(piece.friendly_capture?).to eq false end it "should return false if a piece's destination isn't occupied at all" do game = FactoryBot.create(:game) - piece = FactoryBot.create(:piece) - game.pieces.push(piece) + piece = FactoryBot.create(:piece, game_id: game.id) expect(piece.friendly_capture?).to eq false end end describe "forward_pawn_move? function" do - it "should return true if the piece advances by one tile" do + it "should return true if the piece wants to advance by one tile" do piece = FactoryBot.create(:piece) piece.update(destination_x: 5) piece.update(destination_y: 6) expect(piece.forward_pawn_move?(:+)).to eq true end - it "should return nil if the piece doesn't advance forward by just one tile" do + it "should not return true if the piece doesn't want to advance forward by just one tile", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(destination_x: 5) piece.update(destination_y: 3) - expect(piece.forward_pawn_move?(:-)).to eq nil + expect(piece.forward_pawn_move?(:-)).not_to eq true piece.update(destination_x: 1) piece.update(destination_y: 1) - expect(piece.forward_pawn_move?(:-)).to eq nil + expect(piece.forward_pawn_move?(:-)).not_to eq true piece.update(destination_x: 8) piece.update(destination_y: 8) - expect(piece.forward_pawn_move?(:-)).to eq nil + expect(piece.forward_pawn_move?(:-)).not_to eq true piece.update(destination_x: 5) piece.update(destination_y: 6) - expect(piece.forward_pawn_move?(:-)).to eq nil + expect(piece.forward_pawn_move?(:-)).not_to eq true end - it "should return false if there is a piece in the way" do + it "should not return true if there is a piece in the way" do game = FactoryBot.create(:game) game.pieces.create(x: 5, y: 6) - piece = FactoryBot.create(:piece) - piece.update(destination_x: 5) - piece.update(destination_y: 6) - game.pieces.push(piece) - expect(piece.forward_pawn_move?(:+)).to eq false + piece = FactoryBot.create(:piece, game_id: game.id, destination_x: 5, destination_y: 6) + expect(piece.forward_pawn_move?(:+)).not_to eq true end end describe "double_jump? function" do - it "should return true if the piece advances by two tiles from the starting point" do + it "should return true if the piece wants to advance by two tiles from the starting point" do piece = FactoryBot.create(:piece) piece.update(x: 1) piece.update(y: 7) @@ -387,46 +430,44 @@ it "should return false if there is a piece directly in the way" do game = FactoryBot.create(:game) game.pieces.create(x: 1, y: 6) - piece = FactoryBot.create(:piece) + piece = FactoryBot.create(:piece, game_id: game.id) piece.update(x: 1) piece.update(y: 7) piece.update(destination_x: 1) piece.update(destination_y: 5) - game.pieces.push(piece) expect(piece.double_jump?(:-, 7)).to eq false end it "should return false if there is a piece at the destination" do game = FactoryBot.create(:game) game.pieces.create(x: 1, y: 5) - piece = FactoryBot.create(:piece) + piece = FactoryBot.create(:piece, game_id: game.id) piece.update(x: 1) piece.update(y: 7) piece.update(destination_x: 1) piece.update(destination_y: 5) - game.pieces.push(piece) expect(piece.double_jump?(:-, 7)).to eq false end - it "should return nil if the piece isn't trying to move forward by two tiles" do + it "should not return true if the piece isn't trying to move forward by two tiles", :aggregate_failures do piece = FactoryBot.create(:piece) piece.update(x: 1) piece.update(y: 2) piece.update(destination_x: 1) piece.update(destination_y: 5) - expect(piece.double_jump?(:+, 2)).to eq nil + expect(piece.double_jump?(:+, 2)).not_to eq true piece.update(destination_x: 1) piece.update(destination_y: 1) - expect(piece.double_jump?(:+, 2)).to eq nil + expect(piece.double_jump?(:+, 2)).not_to eq true piece.update(destination_x: 8) piece.update(destination_y: 8) - expect(piece.double_jump?(:+, 2)).to eq nil + expect(piece.double_jump?(:+, 2)).not_to eq true piece.update(destination_x: 1) piece.update(destination_y: 8) - expect(piece.double_jump?(:+, 2)).to eq nil + expect(piece.double_jump?(:+, 2)).not_to eq true piece.update(destination_x: 4) piece.update(destination_y: 4) - expect(piece.double_jump?(:+, 2)).to eq nil + expect(piece.double_jump?(:+, 2)).not_to eq true end end @@ -434,72 +475,65 @@ it "should return true if the piece goes for a capture to it's right" do game = FactoryBot.create(:game) game.pieces.create(x: 6, y: 6) - piece = FactoryBot.create(:piece) + piece = FactoryBot.create(:piece, game_id: game.id) piece.update(destination_x: 6) piece.update(destination_y: 6) - game.pieces.push(piece) expect(piece.pawn_capturing?(:+)).to eq true end it "should return true if the piece goes for a capture to it's left" do game = FactoryBot.create(:game) game.pieces.create(x: 4, y: 4) - piece = FactoryBot.create(:piece) + piece = FactoryBot.create(:piece, game_id: game.id) piece.update(destination_x: 4) piece.update(destination_y: 4) - game.pieces.push(piece) expect(piece.pawn_capturing?(:-)).to eq true end it "should return false if the piece goes for a capture to it's left, but there's no piece to capture" do game = FactoryBot.create(:game) - piece = FactoryBot.create(:piece) + piece = FactoryBot.create(:piece, game_id: game.id) piece.update(destination_x: 4) piece.update(destination_y: 6) - game.pieces.push(piece) expect(piece.pawn_capturing?(:+)).to eq false end it "should return false if the piece goes for a capture to it's right, but there's no piece to capture" do game = FactoryBot.create(:game) - piece = FactoryBot.create(:piece) + piece = FactoryBot.create(:piece, game_id: game.id) piece.update(destination_x: 6) piece.update(destination_y: 4) - game.pieces.push(piece) expect(piece.pawn_capturing?(:-)).to eq false end - it "should return nil if the piece goes for a capture that's not directly to it's left or right" do + it "shouldn't return true if the piece tries to make a capture that's not directly to either side", :aggregate_failures do game = FactoryBot.create(:game) - piece = FactoryBot.create(:piece) - game.pieces.push(piece) + piece = FactoryBot.create(:piece, game_id: game.id) game.pieces.create(x: 8, y: 8) piece.update(destination_x: 8) piece.update(destination_y: 8) - expect(piece.pawn_capturing?(:-)).to eq nil + expect(piece.pawn_capturing?(:-)).not_to eq true game.pieces.create(x: 1, y: 1) piece.update(destination_x: 1) piece.update(destination_y: 1) - expect(piece.pawn_capturing?(:-)).to eq nil + expect(piece.pawn_capturing?(:-)).not_to eq true game.pieces.create(x: 1, y: 8) piece.update(destination_x: 1) piece.update(destination_y: 8) - expect(piece.pawn_capturing?(:-)).to eq nil + expect(piece.pawn_capturing?(:-)).not_to eq true end end describe "tile_has_piece? function" do it "should return true if a given tile is occupied" do - piece = FactoryBot.create(:piece) game = FactoryBot.create(:game) - game.pieces.push(piece) + piece = FactoryBot.create(:piece, game_id: game.id) expect(piece.tile_has_piece?(5, 5)).to eq true end it "should return false if a given tile is not occupied" do - piece = FactoryBot.create(:piece) game = FactoryBot.create(:game) - game.pieces.push(piece) + piece = FactoryBot.create(:piece, game_id: game.id) expect(piece.tile_has_piece?(3, 3)).to eq false end end @@ -511,8 +545,7 @@ end it "should return false if a given piece type is equal to a piece's type" do - piece = FactoryBot.create(:piece) - piece.update(piece_type: "pawn") + piece = FactoryBot.create(:piece, piece_type: "pawn") expect(piece.promoted?("pawn")).to eq false end end @@ -528,4 +561,64 @@ expect(piece.on_row?(6)).to eq false end end + + describe "current_turn? function" do + before do + @user = FactoryBot.create(:user) + end + + it "should return true if the current user is playing as white when it's white's turn" do + game = FactoryBot.create(:game, whites_turn: true, as_white: @user.username) + piece = FactoryBot.create(:piece, game_id: game.id) + expect(piece.current_turn?(@user)).to eq true + end + + it "should return false if the current user is not playing as white when it's white's turn" do + game = FactoryBot.create(:game, whites_turn: true, as_white: "someone else") + piece = FactoryBot.create(:piece, game_id: game.id) + expect(piece.current_turn?(@user)).to eq false + end + + it "should return true if the current user is playing as black when it's blacks's turn" do + game = FactoryBot.create(:game, whites_turn: false, as_black: @user.username) + piece = FactoryBot.create(:piece, game_id: game.id) + expect(piece.current_turn?(@user)).to eq true + end + + it "should return false if the current user is not playing as black when it's black's turn" do + game = FactoryBot.create(:game, whites_turn: false, as_black: "someone else") + piece = FactoryBot.create(:piece, game_id: game.id) + expect(piece.current_turn?(@user)).to eq false + end + end + + describe "correct_color? function" do + before do + @user = FactoryBot.create(:user) + end + + it "should return true if the current user is playing as white when dealing with a white piece" do + game = FactoryBot.create(:game, as_white: @user.username) + piece = FactoryBot.create(:piece, game_id: game.id, color: "white") + expect(piece.correct_color?(@user)).to eq true + end + + it "should return false if the current user is playing as black when dealing with a white piece" do + game = FactoryBot.create(:game, as_black: @user.username) + piece = FactoryBot.create(:piece, game_id: game.id, color: "white") + expect(piece.correct_color?(@user)).to eq false + end + + it "should return true if the current user is playing as black when dealing with a black piece" do + game = FactoryBot.create(:game, as_black: @user.username) + piece = FactoryBot.create(:piece, game_id: game.id, color: "black") + expect(piece.correct_color?(@user)).to eq true + end + + it "should return false if the current user is playing as white when dealing with a black piece" do + game = FactoryBot.create(:game, as_white: @user.username) + piece = FactoryBot.create(:piece, game_id: game.id, color: "black") + expect(piece.correct_color?(@user)).to eq false + end + end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 6169a01..ae7dd38 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -34,6 +34,7 @@ config.include Devise::Test::ControllerHelpers, type: :controller config.include Devise::Test::IntegrationHelpers, type: :request config.include Devise::Test::IntegrationHelpers, type: :system + config.include Devise::Test::IntegrationHelpers, type: :model # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures config.fixture_path = "#{::Rails.root}/spec/fixtures"