0

I am learning JavaScript and Jasmine-Node I have successfully passed the first 11 matchers. But I can't seem to get past this toThrow matcher and I have looked up everything I can think of to get past it. I am stuck. I would really appreciate some help and any comments on my code in general are welcome too.

Here is the spec test...

var Triangle = require('./triangle');

describe('Triangle', function() {

  it('equilateral triangles have equal sides', function() {
    var triangle = new Triangle(2,2,2);
    expect(triangle.kind()).toEqual('equilateral');
  });

  it('larger equilateral triangles also have equal sides', function() {
    var triangle = new Triangle(10,10,10);
    expect(triangle.kind()).toEqual('equilateral');
  });

  it('isosceles triangles have last two sides equal', function() {
    var triangle = new Triangle(3,4,4);
    expect(triangle.kind()).toEqual('isosceles');
  });

  it('isosceles trianges have first and last sides equal', function() {
    var triangle = new Triangle(4,3,4);
    expect(triangle.kind()).toEqual('isosceles');
  });

  it('isosceles triangles have two first sides equal', function() {
    var triangle = new Triangle(4,4,3);
    expect(triangle.kind()).toEqual('isosceles');
  });

  it('isosceles triangles have in fact exactly two sides equal', function() {
    var triangle = new Triangle(10,10,2);
    expect(triangle.kind()).toEqual('isosceles');
  });

  it('scalene triangles have no equal sides', function() {
    var triangle = new Triangle(3,4,5);
    expect(triangle.kind()).toEqual('scalene');
  });

  it('scalene triangles have no equal sides at a larger scale too', function() {
    var triangle = new Triangle(10,11,12);
    expect(triangle.kind()).toEqual('scalene');
  });

  it('scalene triangles have no equal sides in descending order either', function() {
    var triangle = new Triangle(5,4,2);
    expect(triangle.kind()).toEqual('scalene');
  });

  it('very small triangles are legal', function() {
    var triangle = new Triangle(0.4,0.6,0.3);
    expect(triangle.kind()).toEqual('scalene');
  });

  it('test triangles with no size are illegal', function() {
    var triangle = new Triangle(0,0,0);
    expect(triangle.kind.bind(triangle)).toThrow();
  });

  xit('triangles with negative sides are illegal', function() {
    var triangle = new Triangle(3,4,-5);
    expect(triangle.kind.bind(triangle)).toThrow();
  });

  xit('triangles violating triangle inequality are illegal', function() {
    var triangle = new Triangle(1,1,3);
    expect(triangle.kind.bind(triangle)).toThrow();
  });

  xit('edge cases of triangle inequality are in fact legal', function() {
    var triangle = new Triangle(2,4,2);
    expect(triangle.kind.bind(triangle)).not.toThrow();
  });

  xit('triangles violating triangle inequality are illegal 2', function() {
    var triangle = new Triangle(7,3,2);
    expect(triangle.kind.bind(triangle)).toThrow();
  });

  xit('triangles violating triangle inequality are illegal 3', function() {
    var triangle = new Triangle(10,1,3);
    expect(triangle.kind.bind(triangle)).toThrow();
  });

});

This is my JavaScript...

function Triangle(sideA, sideB, sideC) {

    this.kind = function() {
        //
        // Your solution to the exercise goes here
        //
      var triangleType = "";  
      if (this.isValidTriangle()){
        if (sideA == sideB && sideB == sideC ) {
          triangleType="equilateral";
        }
        else if (sideA == sideB || sideB == sideC || sideA == sideC) {
          triangleType="isosceles";
        }
        else {
         triangleType="scalene";
        } 
      }
      else {
//          throw new Error('Invalid Triangle');
//          throw TypeError("Invalid Triangle");
//          throw "up";
          throw new RangeError("Test");
          } 
      return triangleType;    
    };
    this.isValidTriangle = function() {
        var sides = [sideA, sideB, sideC];
        for(var i = 0; i < sides.length; i++) {
            if(sides[i] = 0) {i = 3; return false;};
        };
        return true;
    };
};

module.exports = Triangle;

This is the Jasmine output...

c:\Users\EP\exercism\javascript>jasmine-node triangle --verbose

Triangle - 20 ms
    equilateral triangles have equal sides - 16 ms
    larger equilateral triangles also have equal sides - 1 ms
    isosceles triangles have last two sides equal - 0 ms
    isosceles trianges have first and last sides equal - 0 ms
    isosceles triangles have two first sides equal - 0 ms
    isosceles triangles have in fact exactly two sides equal - 0 ms
    scalene triangles have no equal sides - 0 ms
    scalene triangles have no equal sides at a larger scale too - 0 ms
    scalene triangles have no equal sides in descending order either - 0 ms
    very small triangles are legal - 0 ms
    test triangles with no size are illegal - 1 ms

Failures:

  1) Triangle test triangles with no size are illegal
   Message:
     Expected function to throw an exception.
   Stacktrace:
     Error: Expected function to throw an exception.
    at null.<anonymous> (C:\Users\EP\exercism\javascript\triangle\triangle.spec.js:57:42)

Finished in 0.053 seconds
11 tests, 11 assertions, 1 failure, 0 skipped

I know I must be missing something. I have read Jasmine doc, JavaScript doc, MDN, googled it and just can't seem to determine what I am doing wrong.

Update: with some help from the stackoverflow community I was able to overcome the issue. Below is the final code which passed all of the matchers (those that were pending (xit) were all activated (it).

function Triangle(sideA, sideB, sideC) {

    this.kind = function() {
        //
        // Your solution to the exercise goes here
        //
      if (this.isValidTriangle() == false){ throw new TypeError("Invalid Triangle");}
      else if (sideA == sideB && sideB == sideC ) {
        triangleType="equilateral";
      }
      else if (sideA == sideB || sideB == sideC || sideA == sideC) {
        triangleType="isosceles";
      }
      else {
        triangleType="scalene";
      }
      return triangleType; 
    };

    this.isValidTriangle = function() {
        // no triangle inequality
        if(sideA + sideB < sideC) {return false;}
        if(sideB + sideC < sideA) {return false;}
        if(sideA + sideC < sideB) {return false;}       
        // no zero or negative sides
        var sides = [sideA, sideB, sideC];
        for(var i = 0; i < 3; i++) {
            if(sides[i] <= 0) {i = 3; return false;}; 
        };
        return true;
    };
}
module.exports = Triangle;

Thanks again to all who helped me with their answers!

pks_jw
  • 13
  • 4
  • The JavaScript code is for en exercise described in the spec. That is to say, I am not supposed to change the spec, but rather, one-by-one write JavaScript to pass each test. I am on the test that passes all zeroes to the Triangle function. I have read the two answers but still find myself lost. Feel free to dumb it down for me, I really want to understand why it does not work. I tried looking at the underlying Jasmine code and my head is spinning. – pks_jw Feb 29 '16 at 15:19

2 Answers2

0

The reason resides on the fact that you are calling the method directly and this creates a javascript error, you need to pass a callback that will be invoked by jasmine... this allows jasmine to catch your error:

describe("Something throws", () => {
  it("foo is not defined", () => {
    expect(() => { foo + 5 }).toThrow();

    // instead of:
    // expect(foo + 5).toThrow();
  });
});
Hitmands
  • 13,491
  • 4
  • 34
  • 69
  • I am writing the JS code as part of an exercise where I need to pass the matchers in the spec one-by-one. I still am a little lost, so feel free to dumb down an answer for me, I won't be insulted, I really want to learn. Thx 4 ur time! – pks_jw Feb 29 '16 at 15:39
0

The bind method returns a function statement. You can't expect function statement to throw an exception before you execute it. If you want to change the context and execute the function at the same time you need to use apply or call.

nstoitsev
  • 740
  • 8
  • 7
  • I still am a little lost. I added a comment above to clarify that my JS code is to be written to pass the tests in the spec one-by-one for an exercise. So I assume there is a way, using the spec as is, to pass the current test (all sides zero). I have been reading like mad, but still seem to be lost. Feel free to dumb it down for me, I won't be insulted. Thx for your time! – pks_jw Feb 29 '16 at 15:30
  • You mean that the Jasmine tests should be as is and you can't change them? – nstoitsev Feb 29 '16 at 22:59
  • The test cases that start with `xit` are skipped and are not failing. The one that is producing the test failure is 'test triangles with no size are illegal'. Inside of it, you can see that there is a call to `triangle.kind.bind(triangle)`. You can read what bind does here - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind and see that it returns a function expression. You need to execute the expression so the logic inside of it can be executed. There is no way for it to throw an error without executing it. – nstoitsev Mar 01 '16 at 03:57