2015-05-15 19:42:52 -04:00
|
|
|
import {Injector, bind, Injectable} from 'angular2/di';
|
|
|
|
|
|
|
|
import {Type, isPresent, BaseException, isBlank} from 'angular2/src/facade/lang';
|
|
|
|
import {Promise} from 'angular2/src/facade/async';
|
|
|
|
import {List, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
|
|
|
|
|
|
|
import {View} from 'angular2/src/core/annotations_impl/view';
|
|
|
|
|
2015-06-24 04:54:04 -04:00
|
|
|
import {ViewResolver} from 'angular2/src/core/compiler/view_resolver';
|
2015-05-15 19:42:52 -04:00
|
|
|
import {AppView} from 'angular2/src/core/compiler/view';
|
|
|
|
import {internalView} from 'angular2/src/core/compiler/view_ref';
|
|
|
|
import {
|
|
|
|
DynamicComponentLoader,
|
|
|
|
ComponentRef
|
|
|
|
} from 'angular2/src/core/compiler/dynamic_component_loader';
|
|
|
|
|
|
|
|
import {el} from './utils';
|
|
|
|
|
|
|
|
import {DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer';
|
|
|
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
|
|
|
|
2015-05-28 18:02:20 -04:00
|
|
|
import {DebugElement} from 'angular2/src/debug/debug_element';
|
2015-05-15 19:42:52 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @exportedAs angular2/test
|
|
|
|
*/
|
2015-05-28 18:02:20 -04:00
|
|
|
export class RootTestComponent extends DebugElement {
|
2015-05-15 19:42:52 -04:00
|
|
|
_componentRef: ComponentRef;
|
|
|
|
_componentParentView: AppView;
|
|
|
|
|
|
|
|
constructor(componentRef: ComponentRef) {
|
|
|
|
super(internalView(componentRef.hostView), 0);
|
|
|
|
|
|
|
|
this._componentParentView = internalView(componentRef.hostView);
|
|
|
|
this._componentRef = componentRef;
|
|
|
|
}
|
|
|
|
|
|
|
|
detectChanges(): void {
|
|
|
|
this._componentParentView.changeDetector.detectChanges();
|
|
|
|
this._componentParentView.changeDetector.checkNoChanges();
|
|
|
|
}
|
|
|
|
|
|
|
|
destroy(): void { this._componentRef.dispose(); }
|
|
|
|
}
|
|
|
|
|
2015-05-28 18:02:20 -04:00
|
|
|
var _nextRootElementId = 0;
|
2015-05-15 19:42:52 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @exportedAs angular2/test
|
|
|
|
*
|
|
|
|
* Builds a RootTestComponent for use in component level tests.
|
|
|
|
*/
|
|
|
|
@Injectable()
|
|
|
|
export class TestComponentBuilder {
|
|
|
|
_injector: Injector;
|
|
|
|
_viewOverrides: Map<Type, View>;
|
|
|
|
_directiveOverrides: Map<Type, Map<Type, Type>>;
|
|
|
|
_templateOverrides: Map<Type, string>;
|
|
|
|
|
|
|
|
constructor(injector: Injector) {
|
|
|
|
this._injector = injector;
|
2015-06-17 19:21:40 -04:00
|
|
|
this._viewOverrides = new Map();
|
|
|
|
this._directiveOverrides = new Map();
|
|
|
|
this._templateOverrides = new Map();
|
2015-05-15 19:42:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
_clone(): TestComponentBuilder {
|
|
|
|
var clone = new TestComponentBuilder(this._injector);
|
|
|
|
clone._viewOverrides = MapWrapper.clone(this._viewOverrides);
|
|
|
|
clone._directiveOverrides = MapWrapper.clone(this._directiveOverrides);
|
|
|
|
clone._templateOverrides = MapWrapper.clone(this._templateOverrides);
|
|
|
|
return clone;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Overrides only the html of a {@link Component}.
|
2015-06-24 05:10:29 -04:00
|
|
|
* All the other properties of the component's {@link View} are preserved.
|
2015-05-15 19:42:52 -04:00
|
|
|
*
|
|
|
|
* @param {Type} component
|
|
|
|
* @param {string} html
|
|
|
|
*
|
|
|
|
* @return {TestComponentBuilder}
|
|
|
|
*/
|
|
|
|
overrideTemplate(componentType: Type, template: string): TestComponentBuilder {
|
|
|
|
var clone = this._clone();
|
2015-06-17 19:21:40 -04:00
|
|
|
clone._templateOverrides.set(componentType, template);
|
2015-05-15 19:42:52 -04:00
|
|
|
return clone;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Overrides a component's {@link View}.
|
|
|
|
*
|
|
|
|
* @param {Type} component
|
|
|
|
* @param {view} View
|
|
|
|
*
|
|
|
|
* @return {TestComponentBuilder}
|
|
|
|
*/
|
|
|
|
overrideView(componentType: Type, view: View): TestComponentBuilder {
|
|
|
|
var clone = this._clone();
|
2015-06-17 19:21:40 -04:00
|
|
|
clone._viewOverrides.set(componentType, view);
|
2015-05-15 19:42:52 -04:00
|
|
|
return clone;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Overrides the directives from the component {@link View}.
|
|
|
|
*
|
|
|
|
* @param {Type} component
|
|
|
|
* @param {Type} from
|
|
|
|
* @param {Type} to
|
|
|
|
*
|
|
|
|
* @return {TestComponentBuilder}
|
|
|
|
*/
|
|
|
|
overrideDirective(componentType: Type, from: Type, to: Type): TestComponentBuilder {
|
|
|
|
var clone = this._clone();
|
2015-06-17 19:21:40 -04:00
|
|
|
var overridesForComponent = clone._directiveOverrides.get(componentType);
|
2015-05-15 19:42:52 -04:00
|
|
|
if (!isPresent(overridesForComponent)) {
|
2015-06-17 19:21:40 -04:00
|
|
|
clone._directiveOverrides.set(componentType, new Map());
|
|
|
|
overridesForComponent = clone._directiveOverrides.get(componentType);
|
2015-05-15 19:42:52 -04:00
|
|
|
}
|
2015-06-17 19:21:40 -04:00
|
|
|
overridesForComponent.set(from, to);
|
2015-05-15 19:42:52 -04:00
|
|
|
return clone;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Builds and returns a RootTestComponent.
|
|
|
|
*
|
|
|
|
* @return {Promise<RootTestComponent>}
|
|
|
|
*/
|
|
|
|
createAsync(rootComponentType: Type): Promise<RootTestComponent> {
|
2015-06-24 04:54:04 -04:00
|
|
|
var mockViewResolver = this._injector.get(ViewResolver);
|
2015-05-15 19:42:52 -04:00
|
|
|
MapWrapper.forEach(this._viewOverrides,
|
2015-06-24 04:54:04 -04:00
|
|
|
(view, type) => { mockViewResolver.setView(type, view); });
|
2015-06-24 05:10:29 -04:00
|
|
|
MapWrapper.forEach(this._templateOverrides,
|
|
|
|
(template, type) => { mockViewResolver.setInlineTemplate(type, template); });
|
2015-05-15 19:42:52 -04:00
|
|
|
MapWrapper.forEach(this._directiveOverrides, (overrides, component) => {
|
|
|
|
MapWrapper.forEach(overrides, (to, from) => {
|
2015-06-24 04:54:04 -04:00
|
|
|
mockViewResolver.overrideViewDirective(component, from, to);
|
2015-05-15 19:42:52 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-05-28 18:02:20 -04:00
|
|
|
var rootElId = `root${_nextRootElementId++}`;
|
|
|
|
var rootEl = el(`<div id="${rootElId}"></div>`);
|
2015-05-15 19:42:52 -04:00
|
|
|
var doc = this._injector.get(DOCUMENT_TOKEN);
|
|
|
|
|
|
|
|
// TODO(juliemr): can/should this be optional?
|
|
|
|
DOM.appendChild(doc.body, rootEl);
|
|
|
|
return this._injector.get(DynamicComponentLoader)
|
2015-05-28 18:02:20 -04:00
|
|
|
.loadAsRoot(rootComponentType, `#${rootElId}`, this._injector)
|
2015-05-15 19:42:52 -04:00
|
|
|
.then((componentRef) => { return new RootTestComponent(componentRef); });
|
|
|
|
}
|
|
|
|
}
|