Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript JavaScript Unit Testing Behavior Driven Development with Mocha & Chai Writing Our First Test Suite

Alejandro Molina
Alejandro Molina
3,997 Points

Still getting "expected undefined to be false" for checkForShip even after following all the instructions in the video

The two files for the test are listed below: ship_test.js and ship_methods.js. We would I still be getting the error above? What could I be missing?

ship_test.js file

var expect = require('chai').expect;

describe('checkForShip', function() {
  var checkForShip = require('../game_logic/ship_methods').checkForShip;
  it('should correctly report no ship at a given players coordinate', function () {
    player = {
      ships: [
        {
          locations:[[0,0]]
        }
      ]
    };
    expect(checkForShip(player, [9,9])).to.be.false;
   });
});

ship_methods.js file

function checkForShip(player, coordinates) {
  var shipPresent, ship;

  for (var i; i < player.ships.length; i++){ 
    ship = player.ships[i];
    shipPresent = ship.locations.filter(function (actualCoordinate) {
      return (actualCoordinate[0] === coordinates[0]) && (actualCoordinate[1] === coordinates[1]);
    })[0];

    if (!shipPresent) {
      return false;
    }
  }
}

module.exports.checkForShip = checkForShip; 

This is the exact error I get:

AssertionError: expected undefined to be false
at Context.<anonymous> (test/ship_test.js:18:46)

I am getting the same error, and I can't move forward :(

I am following Guil line by line and I can't pass the test.

6 Answers

I was able to fix mine. It was a syntax error.

The reason it's not passing a test on yours is also a syntax error: You forgot to initialize i in the for loop.

change from this

for (var i; i < player.ships.length; i++){

to that

for (var i=0; i < player.ships.length; i++){
Matt Juszczyk
Matt Juszczyk
12,824 Points

What seems to be the problem, at least for me in this step, was that an empty array wasn't actually evaluating as 'false'. So in our

if (!shipPresent)

Could read

if(shipPresent.length <= 0)

and we'll be working again.

Philip Cox
Philip Cox
14,818 Points

Could it be that 'player' is not defined with the var keyword, making it a global variable, thus out of scope of the test block?

Nick Prodromou
Nick Prodromou
12,824 Points

I have followed the video to the tee and I still can't get the test to pass

test returns:

1) checkForShip should correctly report no ship at a given players coordinate:
     AssertionError: expected undefined to be false
      at Context.<anonymous> (test/ship_test.js:16:46)

my files are:

ship_test.js

var expect = require('chai').expect;

describe('checkForShip', function() {
  var checkForShip = require('../game_logic/ship_methods.js').checkForShip;

  it('should correctly report no ship at a given players coordinate',function() {

    var player = {
      ships: [
        {
          locations: [[0, 0]]
        }
      ]
    };

    expect(checkForShip(player, [9,9])).to.be.false;
  });

});

ship_methods.js

function checkForShip(player, coordinates) {
  var shipPresent, ship;

  for (var i = 0; i < player.ships.length; i++) {
    ship = player.ships[i];

    shipPresent = ship.locations.filter(function(actualCoordinate) {
      return (actualCoordinate[0] === coordinates[0]) && (actualCoordinate[1] === coordinates[1]);
    })[0];
    if (!shipPresent) {
      return false;
    }
  }
}

module.exports.checkForShip = checkForShip;

This is my solution. I'm using a second Array.forEach loop instead of Array.filter because (spoiler alert) you're going to refactor this function to return an object instead of a boolean in a few videos:

ship_test.js:
Passes all tests, including tests for multiple ships and locations.

const expect = require('chai').expect;

describe('checkForShip', () => {
  const checkForShip = require('../game_logic/ship_methods').checkForShip;
  const player1 = { ships: [{ locations: [[0, 0]] }] };
  it('should correctly report no ship at a given player\'s coordinate', () => {
    expect(checkForShip(player1, [1, 1])).to.be.false;
  });
});

ship_methods.js:
Returns a boolean for now...

const checkForShip = (player, coords) => {
  let result;
  player.ships.forEach((item) => {
    item.locations.forEach((coord) => {
      if ((coord[0] === coords[0]) && (coord[1] === coords[1])) {
        result = item;
      }
    });
  });
  return typeof result === 'object';
};

When you get to the part of the course where you need to return an object, simply change the return statement to return result || false; and you'll either return an object if there was a hit, or false if there was a miss.

Gabbie Metheny
Gabbie Metheny
33,778 Points

If anyone is getting expected undefined to be false while using forEach instead of a for loop, I believe it's because forEach returns undefined. A for...of loop works, though! Hope that helps someone!

ship_test.js

const {expect} = require('chai');

describe('checkForShip', () => {
  const {checkForShip} = require('../game_logic/ship_methods');
  it('should correctly report no ship at a given player\'s coordinate', () => {
    const player = {
      ships: [
        {
          locations: [[0, 0]]
        }
      ]
    };
    expect(checkForShip(player, [9, 9])).to.be.false;
  });
});

ship_methods.js

function checkForShip(player, guess) {
  let shipPresent;
  for (ship of player.ships) {
    shipPresent = ship.locations.filter((coords) => {
      return (coords[0] === guess[0]) && (coords[1] === guess[1]);
    })[0];
    if (!shipPresent) {
      return false;
    }
  }
}

module.exports.checkForShip = checkForShip;