diff --git a/modules/rtts_assert/rtts_assert.es6 b/modules/rtts_assert/rtts_assert.es6 deleted file mode 100644 index 117e09a60f..0000000000 --- a/modules/rtts_assert/rtts_assert.es6 +++ /dev/null @@ -1 +0,0 @@ -export * from './src/rtts_assert'; \ No newline at end of file diff --git a/modules/rtts_assert/rtts_assert.ts b/modules/rtts_assert/rtts_assert.ts new file mode 100644 index 0000000000..dce716a413 --- /dev/null +++ b/modules/rtts_assert/rtts_assert.ts @@ -0,0 +1 @@ +export * from './src/rtts_assert'; diff --git a/modules/rtts_assert/src/rtts_assert.es6 b/modules/rtts_assert/src/rtts_assert.ts similarity index 71% rename from modules/rtts_assert/src/rtts_assert.es6 rename to modules/rtts_assert/src/rtts_assert.ts index 1ef8afef42..1d5d882451 100644 --- a/modules/rtts_assert/src/rtts_assert.es6 +++ b/modules/rtts_assert/src/rtts_assert.ts @@ -16,9 +16,9 @@ function argPositionName(i) { var primitives; var genericType; -if (typeof $traceurRuntime === 'object') { - primitives = $traceurRuntime.type; - genericType = $traceurRuntime.genericType; +if (typeof _global['$traceurRuntime'] === 'object') { + primitives = _global['$traceurRuntime'].type; + genericType = _global['$traceurRuntime'].genericType; } else { // Allow to work without traceur runtime as well! primitives = { @@ -26,21 +26,15 @@ if (typeof $traceurRuntime === 'object') { boolean: {name: 'boolean'}, number: {name: 'number'}, string: {name: 'string'}, - symbol: {name: 'symbol'}, - void: {name: 'void'} + symbol: {name: 'symbol'}, void: {name: 'void'} }; genericType = function(type, args) { - return { - type: type, - args: args - } + return { type: type, args: args } } } -Object.keys(primitives).forEach(function(name) { - primitives[name].__assertName = name; -}); +Object.keys(primitives).forEach(function(name) { primitives[name].__assertName = name; }); -export function proxy(){ +export function proxy() { } function assertArgumentTypes(...params) { @@ -59,10 +53,10 @@ function assertArgumentTypes(...params) { // if (!isType(actual, type, currentArgErrors)) { - // console.log(JSON.stringify(errors, null, ' ')); // TODO(vojta): print "an instance of" only if T starts with uppercase. - errors.push(argPositionName(i) + ' argument has to be an instance of ' + prettyPrint(type) + ', got ' + prettyPrint(actual)); + errors.push(argPositionName(i) + ' argument has to be an instance of ' + prettyPrint(type) + + ', got ' + prettyPrint(actual)); if (currentArgErrors.length) { errors.push(currentArgErrors); } @@ -74,7 +68,7 @@ function assertArgumentTypes(...params) { } } -function prettyPrint(value, depth) { +function prettyPrint(value, depth?) { if (typeof(depth) === 'undefined') { depth = 0; } @@ -159,7 +153,7 @@ function isType(value, T, errors) { var isValid; currentStack = errors; try { - isValid = T.assert(value) ; + isValid = T.assert(value); } catch (e) { fail(e.message); isValid = false; @@ -201,30 +195,33 @@ function _isProxy(obj) { function formatErrors(errors, indent = ' ') { return errors.map((e) => { - if (typeof e === 'string') return indent + '- ' + e; - return formatErrors(e, indent + ' '); - }).join('\n'); + if (typeof e === 'string') return indent + '- ' + e; + return formatErrors(e, indent + ' '); + }) + .join('\n'); } // assert a type of given value and throw if does not pass -function type(actual, T) { - var errors = []; - // currentStack = []; +var type: any = + function(actual, T) { + var errors = []; + // currentStack = []; - if (!isType(actual, T, errors)) { - // console.log(JSON.stringify(errors, null, ' ')); - // TODO(vojta): print "an instance of" only if T starts with uppercase. - var msg = 'Expected an instance of ' + prettyPrint(T) + ', got ' + prettyPrint(actual) + '!'; - if (errors.length) { - msg += '\n' + formatErrors(errors); + if (!isType(actual, T, errors)) { + // console.log(JSON.stringify(errors, null, ' ')); + // TODO(vojta): print "an instance of" only if T starts with uppercase. + var msg = + 'Expected an instance of ' + prettyPrint(T) + ', got ' + prettyPrint(actual) + '!'; + if (errors.length) { + msg += '\n' + formatErrors(errors); + } + + throw new Error(msg); + } + return actual; } - throw new Error(msg); - } - return actual; -} - function returnType(actual, T) { var errors = []; // currentStack = []; @@ -232,7 +229,8 @@ function returnType(actual, T) { if (!isType(actual, T, errors)) { // console.log(JSON.stringify(errors, null, ' ')); // TODO(vojta): print "an instance of" only if T starts with uppercase. - var msg = 'Expected to return an instance of ' + prettyPrint(T) + ', got ' + prettyPrint(actual) + '!'; + var msg = 'Expected to return an instance of ' + prettyPrint(T) + ', got ' + + prettyPrint(actual) + '!'; if (errors.length) { msg += '\n' + formatErrors(errors); } @@ -244,17 +242,12 @@ function returnType(actual, T) { } // TODO(vojta): define these with DSL? -var string = type.string = define('string', function(value) { - return typeof value === 'string'; -}); +var string = type.string = define('string', function(value) { return typeof value === 'string'; }); -var boolean = type.boolean = define('boolean', function(value) { - return typeof value === 'boolean'; -}); +var boolean = type.boolean = + define('boolean', function(value) { return typeof value === 'boolean'; }); -var number = type.number = define('number', function(value) { - return typeof value === 'number'; -}); +var number = type.number = define('number', function(value) { return typeof value === 'number'; }); function arrayOf(...types) { return assert.define('array of ' + types.map(prettyPrint).join('/'), function(value) { @@ -311,46 +304,46 @@ function define(classOrName, check) { return cls; } +var assert: any = + function(value) { + return { + is: function is(...types) { + // var errors = [] + var allErrors = []; + var errors; + for (var i = 0; i < types.length; i++) { + var type = types[i]; + errors = []; + if (isType(value, type, errors)) { + return true; + } -function assert(value) { - return { - is: function is(...types) { - // var errors = [] - var allErrors = []; - var errors; - for (var i = 0; i < types.length; i++) { - var type = types[i]; - errors = []; + // if no errors, merge multiple "is not instance of " into x/y/z ? + allErrors.push(prettyPrint(value) + ' is not instance of ' + prettyPrint(type)); + if (errors.length) { + allErrors.push(errors); + } + } - if (isType(value, type, errors)) { - return true; + // if (types.length > 1) { + // currentStack.push(['has to be ' + types.map(prettyPrint).join(' or '), + // ...allErrors]); + // } else { + currentStack.push(...allErrors); + // } + return false; } - - // if no errors, merge multiple "is not instance of " into x/y/z ? - allErrors.push(prettyPrint(value) + ' is not instance of ' + prettyPrint(type)) - if (errors.length) { - allErrors.push(errors); - } - } - - // if (types.length > 1) { - // currentStack.push(['has to be ' + types.map(prettyPrint).join(' or '), ...allErrors]); - // } else { - currentStack.push(...allErrors); - // } - return false; + }; } - }; -} -// PUBLIC API + // PUBLIC API -// asserting API + // asserting API -// throw if no type provided -assert.type = type; + // throw if no type provided + assert.type = type; for (var prop in primitives) { assert.type[prop] = primitives[prop]; } diff --git a/modules/rtts_assert/test/rtts_assert_spec.es6 b/modules/rtts_assert/test/rtts_assert_spec.es6 deleted file mode 100644 index 2efda60b9e..0000000000 --- a/modules/rtts_assert/test/rtts_assert_spec.es6 +++ /dev/null @@ -1,413 +0,0 @@ -// # Assert.js -// A run-time type assertion library for JavaScript. Designed to be used with [Traceur](https://github.com/google/traceur-compiler). - - -// - [Basic Type Check](#basic-type-check) -// - [Custom Check](#custom-check) -// - [Primitive Values](#primitive-values) -// - [Describing more complex types](#describing-more-complex-types) -// - [assert.arrayOf](#assert-arrayof) -// - [assert.structure](#assert-structure) -// - [Integrating with Traceur](#integrating-with-traceur) - -// Note: `assert` gets automatically included by traceur! - -export function main() { - return; - -describe('prettyPrint', () => { - class Type {}; - - it('should limit the number of printed properties', () => { - var o = {}; - for (var i = 0; i < 100; i++) { - o['p_' + i] = i; - } - try { - assert.type(o, Type); - throw 'fail!'; - } catch (e) { - expect(e.message.indexOf('p_0')).toBeGreaterThan(-1); - expect(e.message.indexOf('...')).toBeGreaterThan(-1); - expect(e.message.indexOf('p_20')).toBe(-1); - } - }); - - it('should limit the depth of printed properties', () => { - var o = {l1: {l2: {l3: {l4: {l5: {l6: 'deep'}}}}}}; - - expect(() => { - assert.type(o, Type); - }).toThrowError('Expected an instance of Type, got {l1: {l2: {l3: {l4: [...]}}}}!'); - }); -}); - -// ## Basic Type Check -// By default, `instanceof` is used to check the type. -// -// Note that you can use `assert.type()` in unit tests or anywhere in your code. -// Most of the time, you will use it with Traceur. -// Jump to the [Traceur section](#integrating-with-traceur) to see an example of that. -describe('basic type check', function() { - - class Type {} - - it('should pass', function() { - assert.type(new Type(), Type); - }); - - - it('should fail', function() { - expect(() => assert.type(123, Type)) - .toThrowError('Expected an instance of Type, got 123!'); - }); - - - it('should allow null', function() { - assert.type(null, Type); - }); -}); - - - -// ## Custom Check -// Often, `instanceof` is not flexible enough. -// In that case, your type can define its own `assert` method which will be used instead. -// -// See [Describing More Complex Types](#describing-more-complex-types) for examples how to -// define custom checks using `assert.define()`. -describe('custom check', function() { - - class Type {} - - // the basic check can just return true/false, without specifying any reason - it('should pass when returns true', function() { - Type.assert = function(value) { - return true; - }; - - assert.type({}, Type); - }); - - - it('should fail when returns false', function() { - Type.assert = function(value) { - return false; - }; - - expect(() => assert.type({}, Type)) - .toThrowError('Expected an instance of Type, got {}!'); - }); - - - // Using `assert.fail()` allows to report even multiple errors. - it('should fail when calls assert.fail()', function() { - Type.assert = function(value) { - assert.fail('not smart enough'); - assert.fail('not blue enough'); - }; - - expect(() => assert.type({}, Type)) - .toThrowError('Expected an instance of Type, got {}!\n' + - ' - not smart enough\n' + - ' - not blue enough'); - }); - - - it('should fail when throws an exception', function() { - Type.assert = function(value) { - throw new Error('not long enough'); - }; - - expect(function() { - assert.type(12345, Type); - }).toThrowError('Expected an instance of Type, got 12345!\n' + - ' - not long enough'); - }); -}); - - - -// ## Primitive Values -// You don't want to check primitive values (such as strings, numbers, or booleans) using `typeof` rather than -// `instanceof`. -// -// Again, you probably won't write this code and rather use Traceur to do it for you, simply based on type annotations. -describe('primitive value check', function() { - var primitive = $traceurRuntime.type; - - describe('string', function() { - - it('should pass', function() { - assert.type('xxx', primitive.string); - }); - - - it('should fail', function() { - expect(() => assert.type(12345, primitive.string)) - .toThrowError('Expected an instance of string, got 12345!'); - }); - - it('should allow null', function() { - assert.type(null, primitive.string); - }); - }); - - - describe('number', function() { - - it('should pass', function() { - assert.type(123, primitive.number); - }); - - - it('should fail', function() { - expect(() => assert.type(false, primitive.number)) - .toThrowError('Expected an instance of number, got false!'); - }); - - it('should allow null', function() { - assert.type(null, primitive.number); - }); - }); - - - describe('boolean', function() { - - it('should pass', function() { - expect(assert.type(true, primitive.boolean)).toBe(true); - expect(assert.type(false, primitive.boolean)).toBe(false); - }); - - - it('should fail', function() { - expect(() => assert.type(123, primitive.boolean)) - .toThrowError('Expected an instance of boolean, got 123!'); - }); - - it('should allow null', function() { - assert.type(null, primitive.boolean); - }); - }); -}); - - -// ## Describing more complex types -// -// Often, a simple type check using `instanceof` or `typeof` is not enough. -// That's why you can define custom checks using this DSL. -// The goal was to make them easy to compose and as descriptive as possible. -// Of course you can write your own DSL on the top of this. -describe('define', function() { - - // If the first argument to `assert.define()` is a type (function), it will define `assert` method on that function. - // - // In this example, being a type of Type means being a either a function or object. - it('should define assert for an existing type', function() { - class Type {} - - assert.define(Type, function(value) { - assert(value).is(Function, Object); - }); - - assert.type({}, Type); - assert.type(function() {}, Type); - expect(() => assert.type('str', Type)) - .toThrowError('Expected an instance of Type, got "str"!\n' + - ' - "str" is not instance of Function\n' + - ' - "str" is not instance of Object'); - }); - - - // If the first argument to `assert.define()` is a string, - // it will create an interface - basically an empty class with `assert` method. - it('should define an interface', function() { - var User = assert.define('MyUser', function(user) { - assert(user).is(Object); - }); - - assert.type({}, User); - expect(() => assert.type(12345, User)) - .toThrowError('Expected an instance of MyUser, got 12345!\n' + - ' - 12345 is not instance of Object'); - }); - - - // Here are a couple of more APIs to describe your custom types... - // - // ### assert.arrayOf - // Checks if the value is an array and if so, it checks whether all the items are one the given types. - // These types can be composed types, not just simple ones. - describe('arrayOf', function() { - - var Titles = assert.define('ListOfTitles', function(value) { - assert(value).is(assert.arrayOf(assert.string, assert.number)); - }); - - it('should pass', function () { - assert.type(['one', 55, 'two'], Titles); - }); - - - it('should fail when non-array given', function () { - expect(() => assert.type('foo', Titles)) - .toThrowError('Expected an instance of ListOfTitles, got "foo"!\n' + - ' - "foo" is not instance of array of string/number\n' + - ' - "foo" is not instance of Array'); - }); - - - it('should fail when an invalid item in the array', function () { - expect(() => assert.type(['aaa', true], Titles)) - .toThrowError('Expected an instance of ListOfTitles, got ["aaa", true]!\n' + - ' - ["aaa", true] is not instance of array of string/number\n' + - ' - true is not instance of string\n' + - ' - true is not instance of number'); - }); - }); - - - // ### assert.structure - // Similar to `assert.arrayOf` which checks a content of an array, - // `assert.structure` checks if the value is an object with specific properties. - describe('structure', function() { - - var User = assert.define('MyUser', function(value) { - assert(value).is(assert.structure({ - name: assert.string, - age: assert.number - })); - }); - - it('should pass', function () { - assert.type({name: 'Vojta', age: 28}, User); - }); - - - it('should fail when non-object given', function () { - expect(() => assert.type(123, User)) - .toThrowError('Expected an instance of MyUser, got 123!\n' + - ' - 123 is not instance of object with properties name, age\n' + - ' - 123 is not instance of Object'); - }); - - - it('should fail when an invalid property', function () { - expect(() => assert.type({name: 'Vojta', age: true}, User)) - .toThrowError('Expected an instance of MyUser, got {name: "Vojta", age: true}!\n' + - ' - {name: "Vojta", age: true} is not instance of object with properties name, age\n' + - ' - true is not instance of number'); - }); - }); -}); - - - -// ## Integrating with Traceur -// -// Manually calling `assert.type()` in your code is cumbersome. Most of the time, you'll want to -// have Traceur add the calls to `assert.type()` to your code based on type annotations. -// -// This has several advantages: -// - it's shorter and nicer, -// - you can easily ignore it when generating production code. -// -// You'll need to run Traceur with `--types=true --type-assertions=true --type-assertion-module="path/to/assert"`. -describe('Traceur', function() { - - describe('arguments', function() { - - function reverse(str: string) { - return str ? reverse(str.substring(1)) + str[0] : '' - } - - it('should pass', function() { - expect(reverse('angular')).toBe('ralugna'); - }); - - - it('should fail', function() { - expect(() => reverse(123)) - .toThrowError('Invalid arguments given!\n' + - ' - 1st argument has to be an instance of string, got 123'); - }); - }); - - - describe('return value', function() { - - function foo(bar): number { - return bar; - } - - it('should pass', function() { - expect(foo(123)).toBe(123); - }); - - - it('should fail', function() { - expect(() => foo('bar')) - .toThrowError('Expected to return an instance of number, got "bar"!'); - }); - }); - - - describe('variables', function() { - - it('should pass', function() { - var count:number = 1; - }); - - - it('should fail', function() { - expect(() => { - var count: number = true; - }).toThrowError('Expected an instance of number, got true!'); - }); - }); - - - describe('void', function() { - function foo(bar): void { - return bar; - } - - it('should pass when not defined', function() { - function nonReturn(): void {} - function returnNothing(): void { return; } - function returnUndefined(): void { return undefined; } - - foo(); - foo(undefined); - nonReturn(); - returnNothing(); - returnUndefined(); - }); - - - it('should fail when a value returned', function() { - expect(() => foo('bar')) - .toThrowError('Expected to return an instance of void, got "bar"!'); - }); - - - it('should fail when null returned', function() { - expect(() => foo(null)) - .toThrowError('Expected to return an instance of void, got null!'); - }); - }); - - - describe('generics', function() { - - it('should pass', function() { - var list:Array = []; - }); - - // TODO(tbosch): add assertions based on generics to rtts_assert - - }); - -}); - -} diff --git a/modules/rtts_assert/test/rtts_assert_spec.ts b/modules/rtts_assert/test/rtts_assert_spec.ts new file mode 100644 index 0000000000..93a76a3e4f --- /dev/null +++ b/modules/rtts_assert/test/rtts_assert_spec.ts @@ -0,0 +1,368 @@ +// # Assert.js +// A run-time type assertion library for JavaScript. Designed to be used with +// [Traceur](https://github.com/google/traceur-compiler). +import {} from '../../angular2/src/test_lib/e2e_util'; +import {assert} from '../rtts_assert'; + +// - [Basic Type Check](#basic-type-check) +// - [Custom Check](#custom-check) +// - [Primitive Values](#primitive-values) +// - [Describing more complex types](#describing-more-complex-types) +// - [assert.arrayOf](#assert-arrayof) +// - [assert.structure](#assert-structure) +// - [Integrating with Traceur](#integrating-with-traceur) + +// Note: `assert` gets automatically included by traceur! + +export function main() { + return; + + describe('prettyPrint', () => { + function Type() {} + + it('should limit the number of printed properties', () => { + var o = {}; + for (var i = 0; i < 100; i++) { + o['p_' + i] = i; + } + try { + assert.type(o, Type); + throw 'fail!'; + } catch (e) { + expect(e.message.indexOf('p_0')).toBeGreaterThan(-1); + expect(e.message.indexOf('...')).toBeGreaterThan(-1); + expect(e.message.indexOf('p_20')).toEqual(-1); + } + }); + + it('should limit the depth of printed properties', () => { + var o = {l1: {l2: {l3: {l4: {l5: {l6: 'deep'}}}}}}; + + expect(() => { assert.type(o, Type); }) + .toThrowError('Expected an instance of Type, got {l1: {l2: {l3: {l4: [...]}}}}!'); + }); + }); + + // ## Basic Type Check + // By default, `instanceof` is used to check the type. + // + // Note that you can use `assert.type()` in unit tests or anywhere in your code. + // Most of the time, you will use it with Traceur. + // Jump to the [Traceur section](#integrating-with-traceur) to see an example of that. + describe('basic type check', function() { + + function Type() {} + + it('should pass', function() { assert.type(new Type(), Type); }); + + + it('should fail', function() { + expect(() => assert.type(123, Type)).toThrowError('Expected an instance of Type, got 123!'); + }); + + + it('should allow null', function() { assert.type(null, Type); }); + }); + + + + // ## Custom Check + // Often, `instanceof` is not flexible enough. + // In that case, your type can define its own `assert` method which will be used instead. + // + // See [Describing More Complex Types](#describing-more-complex-types) for examples how to + // define custom checks using `assert.define()`. + describe('custom check', function() { + + function Type() {} + + // the basic check can just return true/false, without specifying any reason + it('should pass when returns true', function() { + (Type).assert = function(value) { return true; }; + + assert.type({}, Type); + }); + + + it('should fail when returns false', function() { + (Type).assert = function(value) { return false; }; + + expect(() => assert.type({}, Type)).toThrowError('Expected an instance of Type, got {}!'); + }); + + + // Using `assert.fail()` allows to report even multiple errors. + it('should fail when calls assert.fail()', function() { + (Type).assert = function(value) { + assert.fail('not smart enough'); + assert.fail('not blue enough'); + }; + + expect(() => assert.type({}, Type)) + .toThrowError('Expected an instance of Type, got {}!\n' + + ' - not smart enough\n' + + ' - not blue enough'); + }); + + + it('should fail when throws an exception', function() { + (Type).assert = function(value) { throw new Error('not long enough'); }; + + expect(function() { assert.type(12345, Type); }) + .toThrowError('Expected an instance of Type, got 12345!\n' + + ' - not long enough'); + }); + }); + + + + // ## Primitive Values + // You don't want to check primitive values (such as strings, numbers, or booleans) using `typeof` + // rather than + // `instanceof`. + // + // Again, you probably won't write this code and rather use Traceur to do it for you, simply based + // on type annotations. + describe('primitive value check', function() { + var primitive = global['$traceurRuntime'].type; + + describe('string', function() { + + it('should pass', function() { assert.type('xxx', primitive.string); }); + + + it('should fail', function() { + expect(() => assert.type(12345, primitive.string)) + .toThrowError('Expected an instance of string, got 12345!'); + }); + + it('should allow null', function() { assert.type(null, primitive.string); }); + }); + + + describe('number', function() { + + it('should pass', function() { assert.type(123, primitive.number); }); + + + it('should fail', function() { + expect(() => assert.type(false, primitive.number)) + .toThrowError('Expected an instance of number, got false!'); + }); + + it('should allow null', function() { assert.type(null, primitive.number); }); + }); + + + describe('boolean', function() { + + it('should pass', function() { + expect(assert.type(true, primitive.boolean)).toEqual(true); + expect(assert.type(false, primitive.boolean)).toEqual(false); + }); + + + it('should fail', function() { + expect(() => assert.type(123, primitive.boolean)) + .toThrowError('Expected an instance of boolean, got 123!'); + }); + + it('should allow null', function() { assert.type(null, primitive.boolean); }); + }); + }); + + + // ## Describing more complex types + // + // Often, a simple type check using `instanceof` or `typeof` is not enough. + // That's why you can define custom checks using this DSL. + // The goal was to make them easy to compose and as descriptive as possible. + // Of course you can write your own DSL on the top of this. + describe('define', function() { + + // If the first argument to `assert.define()` is a type (function), it will define `assert` + // method on that function. + // + // In this example, being a type of Type means being a either a function or object. + it('should define assert for an existing type', function() { + function Type() {} + + assert.define(Type, function(value) { assert(value).is(Function, Object); }); + + assert.type({}, Type); + assert.type(function() {}, Type); + expect(() => assert.type('str', Type)) + .toThrowError('Expected an instance of Type, got "str"!\n' + + ' - "str" is not instance of Function\n' + + ' - "str" is not instance of Object'); + }); + + + // If the first argument to `assert.define()` is a string, + // it will create an interface - basically an empty class with `assert` method. + it('should define an interface', function() { + var User = assert.define('MyUser', function(user) { assert(user).is(Object); }); + + assert.type({}, User); + expect(() => assert.type(12345, User)) + .toThrowError('Expected an instance of MyUser, got 12345!\n' + + ' - 12345 is not instance of Object'); + }); + + + // Here are a couple of more APIs to describe your custom types... + // + // ### assert.arrayOf + // Checks if the value is an array and if so, it checks whether all the items are one the given + // types. + // These types can be composed types, not just simple ones. + describe('arrayOf', function() { + + var Titles = assert.define('ListOfTitles', function(value) { + assert(value).is(assert.arrayOf(assert.string, assert.number)); + }); + + it('should pass', function() { assert.type(['one', 55, 'two'], Titles); }); + + + it('should fail when non-array given', function() { + expect(() => assert.type('foo', Titles)) + .toThrowError('Expected an instance of ListOfTitles, got "foo"!\n' + + ' - "foo" is not instance of array of string/number\n' + + ' - "foo" is not instance of Array'); + }); + + + it('should fail when an invalid item in the array', function() { + expect(() => assert.type(['aaa', true], Titles)) + .toThrowError('Expected an instance of ListOfTitles, got ["aaa", true]!\n' + + ' - ["aaa", true] is not instance of array of string/number\n' + + ' - true is not instance of string\n' + + ' - true is not instance of number'); + }); + }); + + + // ### assert.structure + // Similar to `assert.arrayOf` which checks a content of an array, + // `assert.structure` checks if the value is an object with specific properties. + describe('structure', function() { + + var User = assert.define('MyUser', function(value) { + assert(value).is(assert.structure({name: assert.string, age: assert.number})); + }); + + it('should pass', function() { assert.type({name: 'Vojta', age: 28}, User); }); + + + it('should fail when non-object given', function() { + expect(() => assert.type(123, User)) + .toThrowError('Expected an instance of MyUser, got 123!\n' + + ' - 123 is not instance of object with properties name, age\n' + + ' - 123 is not instance of Object'); + }); + + + it('should fail when an invalid property', function() { + expect(() => assert.type({name: 'Vojta', age: true}, User)) + .toThrowError( + 'Expected an instance of MyUser, got {name: "Vojta", age: true}!\n' + + ' - {name: "Vojta", age: true} is not instance of object with properties name, age\n' + + ' - true is not instance of number'); + }); + }); + }); + + + + // ## Integrating with Traceur + // + // Manually calling `assert.type()` in your code is cumbersome. Most of the time, you'll want to + // have Traceur add the calls to `assert.type()` to your code based on type annotations. + // + // This has several advantages: + // - it's shorter and nicer, + // - you can easily ignore it when generating production code. + // + // You'll need to run Traceur with `--types=true --type-assertions=true + // --type-assertion-module="path/to/assert"`. + describe('Traceur', function() { + + describe('arguments', function() { + + function reverse(str: string) { return str ? reverse(str.substring(1)) + str[0] : '' } + + it('should pass', function() { expect(reverse('angular')).toEqual('ralugna'); }); + + + it('should fail', function() { + expect(() => reverse(123)) + .toThrowError('Invalid arguments given!\n' + + ' - 1st argument has to be an instance of string, got 123'); + }); + }); + + + describe('return value', function() { + + function foo(bar): number { return bar; } + + it('should pass', function() { expect(foo(123)).toEqual(123); }); + + + it('should fail', function() { + expect(() => foo('bar')) + .toThrowError('Expected to return an instance of number, got "bar"!'); + }); + }); + + + describe('variables', function() { + + it('should pass', function() { var count: number = 1; }); + + + it('should fail', function() { + expect(() => { var count: number = true; }) + .toThrowError('Expected an instance of number, got true!'); + }); + }); + + + describe('void', function() { + function foo(bar?): void { return bar; } + + it('should pass when not defined', function() { + function nonReturn(): void {} + function returnNothing(): void { return; } + function returnUndefined(): void { return undefined; } + + foo(); + foo(undefined); + nonReturn(); + returnNothing(); + returnUndefined(); + }); + + + it('should fail when a value returned', function() { + expect(() => foo('bar')).toThrowError('Expected to return an instance of void, got "bar"!'); + }); + + + it('should fail when null returned', function() { + expect(() => foo(null)).toThrowError('Expected to return an instance of void, got null!'); + }); + }); + + + describe('generics', function() { + + it('should pass', function() { var list: Array = []; }); + + // TODO(tbosch): add assertions based on generics to rtts_assert + + }); + + }); +}