connect-four
Version:
Lightweight connect-four game logic
264 lines (222 loc) • 5.68 kB
JavaScript
/* globals describe, it, beforeEach*/
'use strict';
var expect = require('chai').expect;
var Game = require('../src/Game');
var game;
beforeEach(function () {
game = new Game();
});
describe('Game dimensions', function () {
it('should respect the width and height instructed', function () {
game = new Game({
cols: 10,
rows: 10
});
expect(game.cols).to.eq(10);
expect(game.rows).to.eq(10);
});
it('should set it\'s own constructor', function () {
expect(game.constructor).to.eq(Game);
});
it('should default to standard size', function () {
expect(game.rows).to.eq(6);
expect(game.cols).to.eq(7);
});
});
describe('A game', function () {
it('should accept an existing board', function () {
var board = {};
game = new Game({
board: board
});
expect(game.board).to.eq(board);
});
it('should serialize just the board to json', function () {
var copy = JSON.parse(JSON.stringify(game));
expect(copy).to.deep.eq({
rows: game.rows,
cols: game.cols,
board: game.board
});
});
it('should scope events to itself', function () {
var comparison = new Game();
comparison.on('play', function () {
throw new Error('Event leaked to another instance');
});
game.play('red', 3);
});
it('should return the player when given coords', function () {
var play = game.get(4, 5);
expect(play).to.eq(null);
});
it('should keep track of which player played a turn', function () {
game.play('green', 3);
var player = game.get(3, 0);
expect(player).to.eq('green');
});
it('should push a play above the last on a row', function () {
game.play('green', 3);
game.play('red', 3);
expect(game.get(3, 0)).not.to.eq('red');
expect(game.get(3, 1)).to.eq('red');
});
it('should throw an error if you exceed game board height', function () {
game = new Game({
rows: 1
});
game.play('green', 3);
expect(game.play.bind(game, 'green', 3)).to.throw();
});
it('should throw an error if you play outside the board', function () {
expect(game.play.bind(game, 'green', -3)).to.throw();
});
});
describe('A move', function () {
it('should be invalid if outside the boundaries', function () {
var valid = game.validMove(-1);
valid = valid || game.validMove(7);
expect(valid).to.eq(false);
});
it('should be valid if inside the boundaries', function () {
var valid = game.validMove(0);
valid = valid && game.validMove(6);
valid = valid && game.validMove(3);
expect(valid).to.eq(true);
});
it('should be invalid if no space is left on top', function () {
game = new Game({
rows: 1
});
game.play('green', 0);
expect(game.validMove(0)).to.eq(false);
});
it('should trigger an event', function () {
var player, board;
game.on('play', function (name, coord) {
player = name;
board = coord;
});
game.play('blue', 3);
expect(player).to.eq('blue');
expect(board.col).to.eq(3);
});
it('should cancel if the game is ended', function () {
game = new Game({
rows: 5,
cols: 2
});
game
.play('red', 0)
.play('red', 0)
.play('red', 0)
.play('red', 0)
.play('red', 1);
expect(game.get(1, 0)).not.to.eq('red');
});
});
describe('A win', function () {
it('should happen when four plays are lined up', function () {
game.play('red', 1);
game.play('red', 2);
game.play('red', 3);
game.play('red', 4);
expect(game.ended).to.eq(true);
expect(game.winner).to.eq('red');
});
it('should emit an event showing the winner', function () {
var winner;
game.on('end', function (player) {
winner = player;
});
game.play('green', 3);
game.play('green', 3);
game.play('green', 3);
game.play('green', 3);
expect(winner).to.eq('green');
});
it('should not happen if a play is prevented', function () {
game.play('red', 0);
game.play('green', 1);
game.play('red', 2);
game.play('red', 3);
expect(game.winner).not.to.eq('red');
expect(game.ended).to.eq(false);
});
it('should work top-left to bottom-right', function () {
game
.play('red', 0)
.play('green', 1)
.play('red', 1)
.play('green', 2)
.play('green', 2)
.play('red', 2)
.play('green', 3)
.play('green', 3)
.play('green', 3)
.play('red', 3);
expect(game.winner).to.eq('red');
});
it('should work top-right to bottom-left', function () {
game
.play('red', 6)
.play('green', 5)
.play('red', 5)
.play('green', 4)
.play('green', 4)
.play('red', 4)
.play('green', 3)
.play('green', 3)
.play('green', 3)
.play('red', 3);
expect(game.winner).to.eq('red');
});
it('should work vertically', function () {
game
.play('red', 0)
.play('red', 0)
.play('red', 0)
.play('red', 0);
expect(game.winner).to.eq('red');
});
it('should work horizontally', function () {
game
.play('red', 1)
.play('red', 2)
.play('red', 3)
.play('red', 4);
expect(game.winner).to.eq('red');
});
});
describe('A tie', function () {
it('should happen when no other positions are available', function () {
game = new Game({
cols: 2,
rows: 2
});
game.play('green', 0)
.play('green', 0)
.play('green', 1)
.play('green', 1);
expect(game.ended).to.eq(true);
expect(game.winner).to.eq(null);
});
it('should fire the game end event', function () {
var called = false;
game = new Game({
cols: 2,
rows: 2
}).on('end', function () {
called = true;
});
game.play('green', 0)
.play('green', 0)
.play('green', 1);
expect(game.ended).to.eq(false);
expect(called).to.eq(false);
game.play('green', 1);
expect(game.ended).to.eq(true);
expect(game.winner).to.eq(null);
expect(called).to.eq(true);
});
});