refactor: move rtts-assert into modules directory
				
					
				
			The rtts assertion lib is only needed for js, but it should be treated like any other module (e.g. facade, …)
This commit is contained in:
		
							parent
							
								
									c3b442ea53
								
							
						
					
					
						commit
						c8cf03f200
					
				| @ -20,7 +20,7 @@ var js2es5Options = { | |||||||
|   types: true, // parse types
 |   types: true, // parse types
 | ||||||
|   script: false, // parse as a module
 |   script: false, // parse as a module
 | ||||||
|   modules: 'register', |   modules: 'register', | ||||||
|   typeAssertionModule: 'assert', |   typeAssertionModule: 'rtts_assert/rtts_assert', | ||||||
|   typeAssertions: true |   typeAssertions: true | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -52,12 +52,9 @@ gulp.task('jsRuntime/build', function() { | |||||||
| 
 | 
 | ||||||
| function createJsRuntimeTask(isWatch) { | function createJsRuntimeTask(isWatch) { | ||||||
|   var srcFn = isWatch ? watch : gulp.src.bind(gulp); |   var srcFn = isWatch ? watch : gulp.src.bind(gulp); | ||||||
|   var rttsAssert = srcFn('tools/rtts-assert/src/assert.js') |  | ||||||
|     .pipe(gulpTraceur(js2es5Options, resolveModuleName)) |  | ||||||
|     .pipe(gulp.dest('build/js')); |  | ||||||
|   var traceurRuntime = srcFn(gulpTraceur.RUNTIME_PATH) |   var traceurRuntime = srcFn(gulpTraceur.RUNTIME_PATH) | ||||||
|     .pipe(gulp.dest('build/js')); |     .pipe(gulp.dest('build/js')); | ||||||
|   return mergeStreams(rttsAssert, traceurRuntime); |   return traceurRuntime; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // -----------------------
 | // -----------------------
 | ||||||
|  | |||||||
| @ -26,9 +26,8 @@ module.exports = function(config) { | |||||||
|         script: false, |         script: false, | ||||||
|         modules: 'register', |         modules: 'register', | ||||||
|         types: true, |         types: true, | ||||||
|         // TODO: turn this on!
 |         typeAssertions: true, | ||||||
|         // typeAssertions: true,
 |         typeAssertionModule: 'rtts_assert/rtts_assert', | ||||||
|         // typeAssertionModule: 'assert',
 |  | ||||||
|         annotations: true |         annotations: true | ||||||
|       }, |       }, | ||||||
|       resolveModuleName: function(fileName) { |       resolveModuleName: function(fileName) { | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ export class View { | |||||||
| 
 | 
 | ||||||
|   onRecordChange(record:Record, target) { |   onRecordChange(record:Record, target) { | ||||||
|     // dispatch to element injector or text nodes based on context
 |     // dispatch to element injector or text nodes based on context
 | ||||||
|     if (target is ElementInjectorTarge) { |     if (target instanceof ElementInjectorTarge) { | ||||||
|       // we know that it is ElementInjectorTarge
 |       // we know that it is ElementInjectorTarge
 | ||||||
|       var eTarget:ElementInjectorTarget = target; |       var eTarget:ElementInjectorTarget = target; | ||||||
|       onChangeDispatcher.notify(this, eTarget); |       onChangeDispatcher.notify(this, eTarget); | ||||||
|  | |||||||
							
								
								
									
										44
									
								
								modules/rtts_assert/API.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								modules/rtts_assert/API.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | |||||||
|  | // Asserting APIs: | ||||||
|  | // - generated by Traceur (based on type annotations) | ||||||
|  | // - can be also used in tests for instance | ||||||
|  | assert.type(something, Type); | ||||||
|  | assert.returnType(returnValue, Type); | ||||||
|  | assert.argumentTypes(firstArg, Type, secondArg, Type); | ||||||
|  | 
 | ||||||
|  | // this can be used anywhere in the code | ||||||
|  | // (useful inside test, when we don't wanna define an interface) | ||||||
|  | assert(value).is(...) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Custom type assert: | ||||||
|  | // - i have a custom type | ||||||
|  | // - adding an assert methos | ||||||
|  | assert.define(MyUser, function(value) { | ||||||
|  |   assert(value).is(Type, Type2); // or | ||||||
|  |   assert(value, 'name').is(assert.string); | ||||||
|  |   assert(value, 'contact').is(assert.structure({ | ||||||
|  |     email: assert.string, | ||||||
|  |     cell: assert.string | ||||||
|  |   })); | ||||||
|  |   assert(value, 'contacts').is(assert.arrayOf(assert.structure({email: assert.string}))); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Define interface (an empty type with assert method) | ||||||
|  | // - returns an empty class with assert method | ||||||
|  | var Email = assert.define('IEmail', function(value) { | ||||||
|  |   assert(value).is(String); | ||||||
|  | 
 | ||||||
|  |   if (value.indexOf('@') !== -1) { | ||||||
|  |     assert.fail('has to contain "@"'); | ||||||
|  |   } | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Predefined types | ||||||
|  | assert.string | ||||||
|  | assert.number | ||||||
|  | assert.boolean | ||||||
|  | assert.arrayOf(...types) | ||||||
|  | assert.structure(object) | ||||||
							
								
								
									
										1
									
								
								modules/rtts_assert/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								modules/rtts_assert/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | http://angular.github.io/assert/ | ||||||
							
								
								
									
										31
									
								
								modules/rtts_assert/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								modules/rtts_assert/package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | |||||||
|  | { | ||||||
|  |   "name": "rtts-assert", | ||||||
|  |   "version": "0.0.1", | ||||||
|  |   "description": "A type assertion library for Traceur.", | ||||||
|  |   "main": "./dist/cjs/assert.js", | ||||||
|  |   "homepage": "https://github.com/angular/assert", | ||||||
|  |   "repository": { | ||||||
|  |     "type": "git", | ||||||
|  |     "url": "git://github.com/angular/assert.git" | ||||||
|  |   }, | ||||||
|  |   "bugs": { | ||||||
|  |     "url": "https://github.com/angular/assert/issues" | ||||||
|  |   }, | ||||||
|  |   "dependencies": {}, | ||||||
|  |   "devDependencies": { | ||||||
|  |     "gulp": "^3.5.6", | ||||||
|  |     "gulp-connect": "~1.0.5", | ||||||
|  |     "gulp-traceur": "~0.4.0", | ||||||
|  |     "karma": "^0.12.1", | ||||||
|  |     "karma-chrome-launcher": "^0.1.2", | ||||||
|  |     "karma-jasmine": "^0.2.2", | ||||||
|  |     "karma-requirejs": "^0.2.1", | ||||||
|  |     "karma-traceur-preprocessor": "^0.2.2", | ||||||
|  |     "pipe": "git://github.com/angular/pipe#remove-transitive-deps" | ||||||
|  |   }, | ||||||
|  |   "scripts": { | ||||||
|  |     "test": "karma start --single-run" | ||||||
|  |   }, | ||||||
|  |   "author": "Vojta Jína <vojta.jina@gmail.com>", | ||||||
|  |   "license": "Apache-2.0" | ||||||
|  | } | ||||||
							
								
								
									
										327
									
								
								modules/rtts_assert/src/rtts_assert.es6
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										327
									
								
								modules/rtts_assert/src/rtts_assert.es6
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,327 @@ | |||||||
|  | // TODO(vojta): | ||||||
|  | // - extract into multiple files | ||||||
|  | // - different error types | ||||||
|  | // - simplify/humanize error messages | ||||||
|  | // - throw when invalid input (such as odd number of args into assert.argumentTypes) | ||||||
|  | 
 | ||||||
|  | var POSITION_NAME = ['', '1st', '2nd', '3rd']; | ||||||
|  | function argPositionName(i) { | ||||||
|  |   var position = (i / 2) + 1; | ||||||
|  | 
 | ||||||
|  |   return POSITION_NAME[position] || (position + 'th'); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var primitives = $traceurRuntime.type; | ||||||
|  | 
 | ||||||
|  | function assertArgumentTypes(...params) { | ||||||
|  |   var actual, type; | ||||||
|  |   var currentArgErrors; | ||||||
|  |   var errors = []; | ||||||
|  |   var msg; | ||||||
|  | 
 | ||||||
|  |   for (var i = 0, l = params.length; i < l; i = i + 2) { | ||||||
|  |     actual = params[i]; | ||||||
|  |     type = params[i + 1]; | ||||||
|  | 
 | ||||||
|  |     currentArgErrors = []; | ||||||
|  | 
 | ||||||
|  |     // currentStack = []; | ||||||
|  |     // | ||||||
|  | 
 | ||||||
|  |     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)); | ||||||
|  |       if (currentArgErrors.length) { | ||||||
|  |         errors.push(currentArgErrors); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (errors.length) { | ||||||
|  |     throw new Error('Invalid arguments given!\n' + formatErrors(errors)); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function prettyPrint(value) { | ||||||
|  |   if (typeof value === 'undefined') { | ||||||
|  |     return 'undefined'; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (typeof value === 'string') { | ||||||
|  |     return '"' + value + '"'; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (typeof value === 'boolean') { | ||||||
|  |     return value.toString(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (value === null) { | ||||||
|  |     return 'null'; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (typeof value === 'object') { | ||||||
|  |     if (value.map) { | ||||||
|  |       return '[' + value.map(prettyPrint).join(', ') + ']'; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     var properties = Object.keys(value); | ||||||
|  |     return '{' + properties.map((p) => p + ': ' + prettyPrint(value[p])).join(', ') + '}'; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return value.__assertName || value.name || value.toString(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function isType(value, T, errors) { | ||||||
|  | 
 | ||||||
|  |   if (T === primitives.void) { | ||||||
|  |     return typeof value === 'undefined'; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (T === primitives.any || value === null) { | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (T === primitives.string) { | ||||||
|  |     return typeof value === 'string'; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (T === primitives.number) { | ||||||
|  |     return typeof value === 'number'; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (T === primitives.boolean) { | ||||||
|  |     return typeof value === 'boolean'; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // var parentStack = currentStack; | ||||||
|  |   // currentStack = []; | ||||||
|  | 
 | ||||||
|  |   // shouldnt this create new stack? | ||||||
|  |   if (typeof T.assert === 'function') { | ||||||
|  |     var parentStack = currentStack; | ||||||
|  |     var isValid; | ||||||
|  |     currentStack = errors; | ||||||
|  |     try { | ||||||
|  |       isValid = T.assert(value) ; | ||||||
|  |     } catch (e) { | ||||||
|  |       fail(e.message); | ||||||
|  |       isValid = false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     currentStack = parentStack; | ||||||
|  | 
 | ||||||
|  |     if (typeof isValid === 'undefined') { | ||||||
|  |       isValid = errors.length === 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return isValid; | ||||||
|  | 
 | ||||||
|  |     // if (!currentStack.length) { | ||||||
|  |     //   currentStack = parentStack; | ||||||
|  |     //   return []; | ||||||
|  |     // } | ||||||
|  |     // var res = currentStack; | ||||||
|  |     // currentStack = parentStack; | ||||||
|  |     // return ['not instance of ' + prettyPrint(T), res]; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return value instanceof T; | ||||||
|  | 
 | ||||||
|  |   // if (!(value instanceof T)) { | ||||||
|  |   //   fail('not instance of ' + prettyPrint(T)); | ||||||
|  |   // } | ||||||
|  | 
 | ||||||
|  |   // var res = currentStack; | ||||||
|  |   // currentStack = parentStack; | ||||||
|  | 
 | ||||||
|  |   // return res; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function formatErrors(errors, indent = '  ') { | ||||||
|  |   return errors.map((e) => { | ||||||
|  |     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 = []; | ||||||
|  | 
 | ||||||
|  |   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); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function returnType(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 to return an instance of ' + prettyPrint(T) + ', got ' + prettyPrint(actual) + '!'; | ||||||
|  |     if (errors.length) { | ||||||
|  |       msg += '\n' + formatErrors(errors); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     throw new Error(msg); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return actual; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // TODO(vojta): define these with DSL? | ||||||
|  | var string = define('string', function(value) { | ||||||
|  |   return typeof value === 'string'; | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // function string() {} | ||||||
|  | // string.assert = function(value) { | ||||||
|  | //   return typeof value === 'string'; | ||||||
|  | // }; | ||||||
|  | 
 | ||||||
|  | var boolean = define('boolean', function(value) { | ||||||
|  |   return typeof value === 'boolean'; | ||||||
|  | }); | ||||||
|  | // function boolean() {} | ||||||
|  | // boolean.assert = function(value) { | ||||||
|  | //   return typeof value === 'boolean'; | ||||||
|  | // }; | ||||||
|  | 
 | ||||||
|  | var number = define('number', function(value) { | ||||||
|  |   return typeof value === 'number'; | ||||||
|  | }); | ||||||
|  | // function number() {} | ||||||
|  | // number.assert = function(value) { | ||||||
|  | //   return typeof value === 'number'; | ||||||
|  | // }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | function arrayOf(...types) { | ||||||
|  |   return assert.define('array of ' + types.map(prettyPrint).join('/'), function(value) { | ||||||
|  |     if (assert(value).is(Array)) { | ||||||
|  |       for (var item of value) { | ||||||
|  |         assert(item).is(...types); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function structure(definition) { | ||||||
|  |   var properties = Object.keys(definition); | ||||||
|  |   return assert.define('object with properties ' + properties.join(', '), function(value) { | ||||||
|  |     if (assert(value).is(Object)) { | ||||||
|  |       for (var property of properties) { | ||||||
|  |         assert(value[property]).is(definition[property]); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // I'm sorry, bad global state... to make the API nice ;-) | ||||||
|  | var currentStack = []; | ||||||
|  | 
 | ||||||
|  | function fail(message) { | ||||||
|  |   currentStack.push(message); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function define(classOrName, check) { | ||||||
|  |   var cls = classOrName; | ||||||
|  | 
 | ||||||
|  |   if (typeof classOrName === 'string') { | ||||||
|  |     cls = function() {}; | ||||||
|  |     cls.__assertName = classOrName; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   cls.assert = function(value) { | ||||||
|  |     // var parentStack = currentStack; | ||||||
|  | 
 | ||||||
|  |     // currentStack = []; | ||||||
|  | 
 | ||||||
|  |     return check(value); | ||||||
|  | 
 | ||||||
|  |     // if (currentStack.length) { | ||||||
|  |     //   parentStack.push(currentStack) | ||||||
|  |     // } | ||||||
|  |     // currentStack = parentStack; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   return cls; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | function assert(value) { | ||||||
|  |   return { | ||||||
|  |     is: function is(...types) { | ||||||
|  |       // var errors = [] | ||||||
|  |       var allErrors = []; | ||||||
|  |       var errors; | ||||||
|  | 
 | ||||||
|  |       for (var type of types) { | ||||||
|  |         errors = []; | ||||||
|  | 
 | ||||||
|  |         if (isType(value, type, errors)) { | ||||||
|  |           return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 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 | ||||||
|  | 
 | ||||||
|  | // asserting API | ||||||
|  | 
 | ||||||
|  | // throw if no type provided | ||||||
|  | assert.type = type; | ||||||
|  | 
 | ||||||
|  | // throw if odd number of args | ||||||
|  | assert.argumentTypes = assertArgumentTypes; | ||||||
|  | assert.returnType = returnType; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // define AP; | ||||||
|  | assert.define = define; | ||||||
|  | assert.fail = fail; | ||||||
|  | 
 | ||||||
|  | // primitive value type; | ||||||
|  | assert.string = string; | ||||||
|  | assert.number = number; | ||||||
|  | assert.boolean = boolean; | ||||||
|  | 
 | ||||||
|  | // custom types | ||||||
|  | assert.arrayOf = arrayOf; | ||||||
|  | assert.structure = structure; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | export {assert} | ||||||
							
								
								
									
										377
									
								
								modules/rtts_assert/test/rtts_assert_spec.es6
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										377
									
								
								modules/rtts_assert/test/rtts_assert_spec.es6
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,377 @@ | |||||||
|  | // # 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'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // ## 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() { | ||||||
|  |       assert.type(true, primitive.boolean); | ||||||
|  |       assert.type(false, primitive.boolean); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     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> | ||||||
| @ -7,6 +7,9 @@ Object.keys(window.__karma__.files).forEach(function(path) { | |||||||
|       .replace(/\/src\//, '/') |       .replace(/\/src\//, '/') | ||||||
|       .replace(/\/test\//, '/') |       .replace(/\/test\//, '/') | ||||||
|       .replace(/\.\w*$/, ''); |       .replace(/\.\w*$/, ''); | ||||||
|     System.get(moduleName).main(); |     var mod = System.get(moduleName); | ||||||
|  |     if (mod.main) { | ||||||
|  |       mod.main(); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| }); | }); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user