var err = require('../util').err;
require('../../');


describe('error', function() {
  it('test throw()', function() {
    err(function() {
      'a'.should.throw();
    }, 'expected \'a\' to be a function\n    expected \'a\' to have type function\n        expected \'string\' to be \'function\'');

    (function() {}).should.not.throw();
    (function() { throw new Error('fail'); }).should.throw();

    err(function() {
      (function() {}).should.throw();
    }, 'expected Function { name: \'\' } to throw exception');

    err(function() {
      (function() {
        throw new Error('fail');
      }).should.not.throw();
    }, /expected Function \{ name: '' \} not to throw exception \(got Error \{[\s\S]*message: 'fail'[\s\S]*\}\)/);
  });

  it('test throw() with regex message', function() {
    (function() { throw new Error('fail'); }).should.throw(/fail/);

    err(function() {
      (function() {}).should.throw(/fail/);
    }, 'expected Function { name: \'\' } to throw exception');

    err(function() {
      (function() { throw new Error('error'); }).should.throw(/fail/);
    }, "expected Function { name: \'\' } to throw exception with a message matching /fail/, but got 'error'");
  });

  it('test throw() with string message', function() {
    (function() { throw new Error('fail'); }).should.throw('fail');

    err(function() {
      (function() {}).should.throw('fail');
    }, 'expected Function { name: \'\' } to throw exception');

    err(function() {
      (function() { throw new Error('error'); }).should.throw('fail');
    }, "expected Function { name: \'\' } to throw exception with a message matching 'fail', but got 'error'");
  });

  it('test throw() with type', function() {
    (function() { throw new Error('fail'); }).should.throw(Error);

    err(function() {
      (function() {}).should.throw(Error);
    }, 'expected Function { name: \'\' } to throw exception');

    err(function() {
      (function() { throw 'error'; }).should.throw(Error);
    }, 'expected Function { name: \'\' } to throw exception of type Error, but got String');
  });

  it('test throwError()', function() {
    (function() {}).should.not.throwError();
    (function() { throw new Error('fail'); }).should.throwError();

    err(function() {
      (function() {}).should.throwError();
    }, 'expected Function { name: \'\' } to throw exception');

    err(function() {
      (function() {
        throw new Error('fail');
      }).should.not.throwError();
    }, /expected Function \{ name: '' \} not to throw exception \(got Error \{[\s\S]*message: 'fail'[\s\S]*\}\)/);
  });

  it('test throwError() with regex message', function() {
    (function() { throw new Error('fail'); }).should.throwError(/fail/);

    err(function() {
      (function() {}).should.throwError(/fail/);
    }, 'expected Function { name: \'\' } to throw exception');

    err(function() {
      (function() { throw new Error('error'); }).should.throwError(/fail/);
    }, "expected Function { name: \'\' } to throw exception with a message matching /fail/, but got 'error'");
  });

  it('test throwError() with string message', function() {
    (function() { throw new Error('fail'); }).should.throwError('fail');

    err(function() {
      (function() {}).should.throwError('fail');
    }, 'expected Function { name: \'\' } to throw exception');

    err(function() {
      (function() { throw new Error('error'); }).should.throwError('fail');
    }, "expected Function { name: \'\' } to throw exception with a message matching 'fail', but got 'error'");
  });

  it('test throwError() with type', function() {
    (function() { throw new Error('fail'); }).should.throw(Error);

    err(function() {
      (function() {}).should.throw(Error);
    }, 'expected Function { name: \'\' } to throw exception');

    err(function() {
      (function() { throw 'error'; }).should.throw(Error);
    }, "expected Function { name: '' } to throw exception of type Error, but got String");
  });

  it('test .throw(err, properties) with matching error', function() {
    var error = new Error();
    error.a = 10;
    (function() { throw error; }).should.throw(Error, { a: 10 });

    err(function() {
      (function() { throw error; }).should.throw(Error, { a: 11 });
    }, /expected Function \{ name: '' \} to throw exception: expected Error \{[\s\S]*a: 10,[\s\S]*message: ''[\s\S]*\} to match Object \{ a: 11 \}\n\s{4}not matched properties: a \(10\)/);
  });

  it('test .throw(properties) with matching error', function() {
    var error = new Error();
    error.a = 10;
    (function() { throw error; }).should.throw({ a: 10 });

    err(function() {
      (function() { throw error; }).should.throw({ a: 11 });
    }, /expected Function \{ name: '' \} to throw exception: expected Error \{[\s\S]*a: 10,[\s\S]*message: ''[\s\S]*\} to match Object \{ a: 11 \}\n\s{4}not matched properties: a \(10\)/);
  });
/* TODO find a way to write tests with es6 features
  it('should support to catch errors from generators', function() {
    if(generatorSupported) {
      var throwsError = function*() {
        throw new Error();
      }

      (function * () {
        yield throwsError();
      }).should.throw();

      var throwsError1 = function*() {
        throw new Error();
        yield console.log('hello');
      }

      (function * () {
        yield throwsError1();
      }).should.throw();

      var noError = function * () { yield console.log('no error') };

      err(function(){
        (function * () {yield noError();}).should.throw();
      }, 'expected Function { name: \'\' } to throw exception');

    }
  });*/
});
