2015-04-07 20:54:20 -07:00
|
|
|
import {Injector, bind} from 'angular2/di';
|
2015-03-30 16:37:33 +02:00
|
|
|
|
|
|
|
import {Type, isPresent, BaseException} from 'angular2/src/facade/lang';
|
|
|
|
import {Promise} from 'angular2/src/facade/async';
|
|
|
|
import {isBlank} from 'angular2/src/facade/lang';
|
|
|
|
import {List} from 'angular2/src/facade/collection';
|
|
|
|
|
2015-04-09 21:20:11 +02:00
|
|
|
import {View} from 'angular2/src/core/annotations/view';
|
2015-03-30 16:37:33 +02:00
|
|
|
|
|
|
|
import {TemplateResolver} from 'angular2/src/core/compiler/template_resolver';
|
|
|
|
import {Compiler} from 'angular2/src/core/compiler/compiler';
|
2015-04-09 21:20:11 +02:00
|
|
|
import {AppView} from 'angular2/src/core/compiler/view';
|
2015-04-07 20:54:20 -07:00
|
|
|
import {ViewFactory} from 'angular2/src/core/compiler/view_factory';
|
2015-04-15 21:51:30 -07:00
|
|
|
import {AppViewHydrator} from 'angular2/src/core/compiler/view_hydrator';
|
2015-03-30 16:37:33 +02:00
|
|
|
|
2015-04-07 20:54:20 -07:00
|
|
|
import {DirectiveBinding} from 'angular2/src/core/compiler/element_injector';
|
|
|
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
2015-03-30 16:37:33 +02:00
|
|
|
|
2015-04-07 20:54:20 -07:00
|
|
|
import {queryView, viewRootNodes, el} from './utils';
|
2015-03-30 16:37:33 +02:00
|
|
|
import {instantiateType, getTypeOf} from './lang_utils';
|
|
|
|
|
2015-04-14 23:26:49 +00:00
|
|
|
/**
|
|
|
|
* @exportedAs angular2/test
|
|
|
|
*/
|
2015-03-30 16:37:33 +02:00
|
|
|
export class TestBed {
|
|
|
|
_injector: Injector;
|
|
|
|
|
|
|
|
constructor(injector: Injector) {
|
|
|
|
this._injector = injector;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-04-09 21:20:11 +02:00
|
|
|
* Overrides the [View] of a [Component].
|
2015-03-30 16:37:33 +02:00
|
|
|
*
|
|
|
|
* @see setInlineTemplate() to only override the html
|
|
|
|
*
|
|
|
|
* @param {Type} component
|
2015-04-09 21:20:11 +02:00
|
|
|
* @param {ViewDefinition} template
|
2015-03-30 16:37:33 +02:00
|
|
|
*/
|
2015-04-09 21:20:11 +02:00
|
|
|
overrideView(component: Type, template: View): void {
|
|
|
|
this._injector.get(TemplateResolver).setView(component, template);
|
2015-03-30 16:37:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Overrides only the html of a [Component].
|
2015-04-09 21:20:11 +02:00
|
|
|
* All the other propoerties of the component's [View] are preserved.
|
2015-03-30 16:37:33 +02:00
|
|
|
*
|
|
|
|
* @param {Type} component
|
|
|
|
* @param {string} html
|
|
|
|
*/
|
|
|
|
setInlineTemplate(component: Type, html: string): void {
|
|
|
|
this._injector.get(TemplateResolver).setInlineTemplate(component, html);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-04-09 21:20:11 +02:00
|
|
|
* Overrides the directives from the component [View].
|
2015-03-30 16:37:33 +02:00
|
|
|
*
|
|
|
|
* @param {Type} component
|
|
|
|
* @param {Type} from
|
|
|
|
* @param {Type} to
|
|
|
|
*/
|
|
|
|
overrideDirective(component: Type, from: Type, to: Type): void {
|
|
|
|
this._injector.get(TemplateResolver).overrideTemplateDirective(component, from, to);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-04-09 21:20:11 +02:00
|
|
|
* Creates a [AppView] for the given component.
|
2015-03-30 16:37:33 +02:00
|
|
|
*
|
|
|
|
* Only either a component or a context needs to be specified but both can be provided for
|
|
|
|
* advanced use cases (ie subclassing the context).
|
|
|
|
*
|
|
|
|
* @param {Type} component
|
|
|
|
* @param {*} context
|
|
|
|
* @param {string} html Use as the component template when specified (shortcut for setInlineTemplate)
|
|
|
|
* @return {Promise<ViewProxy>}
|
|
|
|
*/
|
|
|
|
createView(component: Type,
|
2015-04-09 21:20:11 +02:00
|
|
|
{context = null, html = null}: {context:any, html: string} = {}): Promise<AppView> {
|
2015-03-30 16:37:33 +02:00
|
|
|
|
|
|
|
if (isBlank(component) && isBlank(context)) {
|
|
|
|
throw new BaseException('You must specified at least a component or a context');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isBlank(component)) {
|
|
|
|
component = getTypeOf(context);
|
|
|
|
} else if (isBlank(context)) {
|
|
|
|
context = instantiateType(component);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isPresent(html)) {
|
|
|
|
this.setInlineTemplate(component, html);
|
|
|
|
}
|
|
|
|
|
2015-04-07 20:54:20 -07:00
|
|
|
var rootEl = el('<div></div>');
|
|
|
|
var metadataReader = this._injector.get(DirectiveMetadataReader);
|
|
|
|
var componentBinding = DirectiveBinding.createFromBinding(
|
|
|
|
bind(component).toValue(context),
|
|
|
|
metadataReader.read(component).annotation
|
|
|
|
);
|
2015-04-15 21:51:30 -07:00
|
|
|
return this._injector.get(Compiler).compileInHost(componentBinding).then((pv) => {
|
2015-04-07 20:54:20 -07:00
|
|
|
var viewFactory = this._injector.get(ViewFactory);
|
2015-04-15 21:51:30 -07:00
|
|
|
var viewHydrator = this._injector.get(AppViewHydrator);
|
|
|
|
var hostView = viewFactory.getView(pv);
|
|
|
|
viewHydrator.hydrateInPlaceHostView(null, rootEl, hostView, this._injector);
|
|
|
|
|
|
|
|
return new ViewProxy(this._injector, hostView.componentChildViews[0]);
|
2015-03-30 16:37:33 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-04-09 21:20:11 +02:00
|
|
|
* Proxy to [AppView] return by [TestBed.createView] which offers a high level API for tests.
|
2015-03-30 16:37:33 +02:00
|
|
|
*/
|
|
|
|
export class ViewProxy {
|
2015-04-09 21:20:11 +02:00
|
|
|
_view: AppView;
|
2015-04-15 21:51:30 -07:00
|
|
|
_injector: Injector;
|
2015-03-30 16:37:33 +02:00
|
|
|
|
2015-04-15 21:51:30 -07:00
|
|
|
constructor(injector: Injector, view: AppView) {
|
2015-03-30 16:37:33 +02:00
|
|
|
this._view = view;
|
2015-04-15 21:51:30 -07:00
|
|
|
this._injector = injector;
|
2015-03-30 16:37:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
get context(): any {
|
|
|
|
return this._view.context;
|
|
|
|
}
|
|
|
|
|
2015-04-07 20:54:20 -07:00
|
|
|
get rootNodes(): List {
|
|
|
|
return viewRootNodes(this._view);
|
2015-03-30 16:37:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
detectChanges(): void {
|
|
|
|
this._view.changeDetector.detectChanges();
|
|
|
|
}
|
|
|
|
|
|
|
|
querySelector(selector) {
|
|
|
|
return queryView(this._view, selector);
|
|
|
|
}
|
|
|
|
|
2015-04-15 21:51:30 -07:00
|
|
|
destroy() {
|
|
|
|
var viewHydrator = this._injector.get(AppViewHydrator);
|
|
|
|
viewHydrator.dehydrateInPlaceHostView(null, this._view);
|
|
|
|
}
|
|
|
|
|
2015-03-30 16:37:33 +02:00
|
|
|
/**
|
2015-04-09 21:20:11 +02:00
|
|
|
* @returns {AppView} return the underlying [AppView].
|
2015-03-30 16:37:33 +02:00
|
|
|
*
|
|
|
|
* Prefer using the other methods which hide implementation details.
|
|
|
|
*/
|
2015-04-09 21:20:11 +02:00
|
|
|
get rawView(): AppView {
|
2015-03-30 16:37:33 +02:00
|
|
|
return this._view;
|
|
|
|
}
|
|
|
|
}
|