From 376bdf4dc75e2d4e133c3f65970492739b02a5ab Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Wed, 18 Mar 2015 18:30:45 -0700 Subject: [PATCH] fix(bootstrap): report error on bootstrapping non-Component directive Fixes #951. Test case added to exercise new error reporting. Also added extra test for when Template is missing. Closes #961 --- modules/angular2/src/core/application.js | 9 ++++++- .../angular2/test/core/application_spec.js | 25 ++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/modules/angular2/src/core/application.js b/modules/angular2/src/core/application.js index 52bbc992e4..2ce080137c 100644 --- a/modules/angular2/src/core/application.js +++ b/modules/angular2/src/core/application.js @@ -1,5 +1,5 @@ import {Injector, bind, OpaqueToken} from 'angular2/di'; -import {Type, isBlank, isPresent, BaseException, assertionsEnabled, print} from 'angular2/src/facade/lang'; +import {Type, isBlank, isPresent, BaseException, assertionsEnabled, print, stringify} from 'angular2/src/facade/lang'; import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter'; import {DOM} from 'angular2/src/dom/dom_adapter'; import {Compiler, CompilerCache} from './compiler/compiler'; @@ -25,6 +25,7 @@ import {UrlResolver} from 'angular2/src/core/compiler/url_resolver'; import {StyleUrlResolver} from 'angular2/src/core/compiler/style_url_resolver'; import {StyleInliner} from 'angular2/src/core/compiler/style_inliner'; import {CssProcessor} from 'angular2/src/core/compiler/css_processor'; +import {Component} from 'angular2/src/core/annotations/annotations'; var _rootInjector: Injector; @@ -58,6 +59,12 @@ function _injectorBindings(appComponentType): List { bind(appViewToken).toAsyncFactory((changeDetection, compiler, injector, appElement, appComponentAnnotatedType, strategy, eventManager) => { + var annotation = appComponentAnnotatedType.annotation; + if(!isBlank(annotation) && !(annotation instanceof Component)) { + var type = appComponentAnnotatedType.type; + throw new BaseException(`Only Components can be bootstrapped; ` + + `Directive of ${stringify(type)} is not a Component`); + } return compiler.compile(appComponentAnnotatedType.type).then( (protoView) => { var appProtoView = ProtoView.createRootProtoView(protoView, appElement, diff --git a/modules/angular2/test/core/application_spec.js b/modules/angular2/test/core/application_spec.js index 65c94663dd..cdf5594611 100644 --- a/modules/angular2/test/core/application_spec.js +++ b/modules/angular2/test/core/application_spec.js @@ -12,7 +12,7 @@ import { } from 'angular2/test_lib'; import {bootstrap, appDocumentToken, appElementToken} from 'angular2/src/core/application'; -import {Component} from 'angular2/src/core/annotations/annotations'; +import {Component, Decorator} from 'angular2/src/core/annotations/annotations'; import {DOM} from 'angular2/src/dom/dom_adapter'; import {ListWrapper} from 'angular2/src/facade/collection'; import {PromiseWrapper} from 'angular2/src/facade/async'; @@ -64,6 +64,12 @@ class HelloRootCmp4 { } } +@Component({selector: 'hello-app'}) +class HelloRootMissingTemplate { } + +@Decorator({selector: 'hello-app'}) +class HelloRootDirectiveIsNotCmp { } + export function main() { var fakeDoc, el, el2, testBindings, lightDom; @@ -80,6 +86,23 @@ export function main() { }); describe('bootstrap factory method', () => { + it('should throw if no Template found', inject([AsyncTestCompleter], (async) => { + var injectorPromise = bootstrap(HelloRootMissingTemplate, testBindings, (e,t) => {throw e;}); + PromiseWrapper.then(injectorPromise, null, (reason) => { + expect(reason.message).toContain('No template found for HelloRootMissingTemplate'); + async.done(); + }); + })); + + it('should throw if bootstrapped Directive is not a Component', inject([AsyncTestCompleter], (async) => { + var injectorPromise = bootstrap(HelloRootDirectiveIsNotCmp, testBindings, (e,t) => {throw e;}); + PromiseWrapper.then(injectorPromise, null, (reason) => { + expect(reason.message).toContain('Only Components can be bootstrapped; ' + + 'Directive of HelloRootDirectiveIsNotCmp is not a Component'); + async.done(); + }); + })); + it('should throw if no element is found', inject([AsyncTestCompleter], (async) => { var injectorPromise = bootstrap(HelloRootCmp, [], (e,t) => {throw e;}); PromiseWrapper.then(injectorPromise, null, (reason) => {