4

I'm improving my JavaScript by doing exercises on Exercism.io; I'm currently working on http://exercism.io/exercises/javascript/leap/readme.

So far, I've written a leap.js like so:

var Year = function (year) {};

Year.prototype.isLeap = function () {
    return (this.year % 4 === 0 && this.year % 100 !== 0) || this.year % 400 === 0
};

module.exports = Year;

The Jasmine test, leap.spec.js, is

var Year = require('./leap');

describe('Leap year', function () {
  it('is not very common', function () {
    var year = new Year(2015);
    expect(year.isLeap()).toBe(false);
  });

  it('is introduced every 4 years to adjust about a day', function () {
    var year = new Year(2016);
    expect(year.isLeap()).toBe(true);
  });

  it('is skipped every 100 years to remove an extra day', function () {
    var year = new Year(1900);
    expect(year.isLeap()).toBe(false);
  });

  it('is reintroduced every 400 years to adjust another day', function () {
    var year = new Year(2000);
    expect(year.isLeap()).toBe(true);
  });

However, some tests are still failing:

Kurts-MacBook-Pro:leap kurtpeek$ jasmine leap.spec.js
Started
.F.F

Failures:
1) Leap year is introduced every 4 years to adjust about a day
  Message:
    Expected false to be true.
  Stack:
    Error: Expected false to be true.
        at UserContext.<anonymous> (/Users/kurtpeek/exercism/javascript/leap/leap.spec.js:11:27)

2) Leap year is reintroduced every 400 years to adjust another day
  Message:
    Expected false to be true.
  Stack:
    Error: Expected false to be true.
        at UserContext.<anonymous> (/Users/kurtpeek/exercism/javascript/leap/leap.spec.js:21:27)

Ran 4 of 8 specs
4 specs, 2 failures
Finished in 0.009 seconds

Strangely, if I copy what is returned to the Node REPL with this.year replaced by 2016, I get true as expected:

Kurts-MacBook-Pro:leap kurtpeek$ node
> (2016 % 4 === 0 && 2016 % 100 !== 0) || 2016 % 400 === 0
true

What I suspect is happening is that this.year is not the number 2016, but the instance year of Year that was instantiated previously, so that the modulo expression doesn't make sense.

To confirm this, however, I would like to inspect the variables in the scope of the isLeap function. After some Googling I've tried installing jasmine-debug and jasmine-node-debug, but when I try to run either one of them (after inserting a debugger; statement before the return statement) I get the following error:

Kurts-MacBook-Pro:leap kurtpeek$ jasmine-node-debug
internal/modules/cjs/loader.js:550
    throw err;
    ^

Error: Cannot find module '_debugger'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:548:15)
    at Function.Module._load (internal/modules/cjs/loader.js:475:25)
    at Module.require (internal/modules/cjs/loader.js:598:17)
    at require (internal/modules/cjs/helpers.js:11:18)
    at Object.<anonymous> (/usr/local/lib/node_modules/jasmine-node-debug/node_modules/node-inspector/lib/debugger.js:2:16)
    at Module._compile (internal/modules/cjs/loader.js:654:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:665:10)
    at Module.load (internal/modules/cjs/loader.js:566:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:506:12)
    at Function.Module._load (internal/modules/cjs/loader.js:498:3)

From what I've read at https://github.com/angular/protractor/issues/4307, this error has to do with the Node.js team migrating users to the new inspect API - basically, these packages are outdated.

Is there any other way to enter the debugger through a Jasmine test?

Kurt Peek
  • 52,165
  • 91
  • 301
  • 526

2 Answers2

4

I managed to start the debugger by running node --inspect-brk with the jasmine.js file called by Jasmine's CLI:

Kurts-MacBook-Pro:bin kurtpeek$ node --inspect-brk /usr/local/lib/node_modules/jasmine/bin/jasmine.js ~/exercism/javascript/leap/leap.spec.js
Debugger listening on ws://127.0.0.1:9229/03d10b73-1d60-4db3-be79-850f7ee4d0d6
For help see https://nodejs.org/en/docs/inspector
Debugger attached.
Started

Then, upon navigating to chrome://inspect in the Chrome browser and hitting 'continue', I was able to determine that this.year is indeed undefined:

enter image description here

I then fixed the test by defining this.year:

var Year = function (year) {
    this.year = year;
};

Year.prototype.isLeap = function () {
    return (this.year % 4 === 0 && this.year % 100 !== 0) || this.year % 400 === 0
};

module.exports = Year;

Now the tests pass:

Kurts-MacBook-Pro:bin kurtpeek$ jasmine ~/exercism/javascript/leap/leap.spec.js
Started
....


Ran 4 of 8 specs
4 specs, 0 failures
Finished in 0.009 seconds
Kurt Peek
  • 52,165
  • 91
  • 301
  • 526
0

You are not setting this.year anywhere.

In the function isLeap(), this.year is undefined hence specs for falsy are passed.

You can console.log() inside your spec and see its value any time. It will be printed to the terminal as well as the browser instance. You may try dump() as well.

Try this:

var Year = function (year) {
    this.year = year;
};

You may also confirm what data type this.year is holding, using

expect(this.year).toEqual(jasmine.any(Number));
Satish Kumar
  • 601
  • 6
  • 14
  • 2
    My question wasn't so much about how to solve this problem rather than how to drop into the debugger so that I can have all the variables at my fingertips and more quickly solve these problems in the future. – Kurt Peek Apr 22 '18 at 07:43
  • Bit off topic don't ya thing? – PVermeer Feb 05 '20 at 22:07