2014-09-26 17:36:57 -07:00
// # 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)
import { assert } from 'rtts_assert/rtts_assert' ;
2014-10-06 17:35:00 -07:00
export function main ( ) {
2014-09-26 17:36:57 -07:00
// ## 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 ( ) {
2014-09-28 20:02:32 -07:00
expect ( assert . type ( true , primitive . boolean ) ) . toBe ( true ) ;
expect ( assert . type ( false , primitive . boolean ) ) . toBe ( false ) ;
2014-09-26 17:36:57 -07:00
} ) ;
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 voidType, got "bar"!' ) ;
} ) ;
it ( 'should fail when null returned' , function ( ) {
expect ( ( ) => foo ( null ) )
. toThrowError ( 'Expected to return an instance of voidType, got null!' ) ;
} ) ;
} ) ;
} ) ;
// <center><small>
// This documentation was generated from [assert.spec.js](https://github.com/vojtajina/assert/blob/master/test/assert.spec.js) using [Docco](http://jashkenas.github.io/docco/).
// </small></center>
2014-10-06 17:35:00 -07:00
}