Files
angular-cn/modules/angular2/src/test_lib/test_component_builder.ts
T

153 lines
4.9 KiB
TypeScript
Raw Normal View History

2015-05-15 16:42:52 -07: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';
import {ViewResolver} from 'angular2/src/core/compiler/view_resolver';
2015-05-15 16:42:52 -07:00
import {AppView} from 'angular2/src/core/compiler/view';
2015-07-11 17:26:48 +02:00
import {internalView, ViewRef} from 'angular2/src/core/compiler/view_ref';
2015-05-15 16:42:52 -07:00
import {
DynamicComponentLoader,
ComponentRef
} from 'angular2/src/core/compiler/dynamic_component_loader';
import {el} from './utils';
2015-08-10 21:42:47 -07:00
import {DOCUMENT} from 'angular2/src/render/render';
2015-05-15 16:42:52 -07:00
import {DOM} from 'angular2/src/dom/dom_adapter';
2015-05-28 15:02:20 -07:00
import {DebugElement} from 'angular2/src/debug/debug_element';
2015-05-15 16:42:52 -07:00
2015-05-28 15:02:20 -07:00
export class RootTestComponent extends DebugElement {
2015-05-15 16:42:52 -07:00
_componentRef: ComponentRef;
_componentParentView: AppView;
constructor(componentRef: ComponentRef) {
2015-07-11 17:26:48 +02:00
super(internalView(<ViewRef>componentRef.hostView), 0);
2015-05-15 16:42:52 -07:00
2015-07-11 17:26:48 +02:00
this._componentParentView = internalView(<ViewRef>componentRef.hostView);
2015-05-15 16:42:52 -07:00
this._componentRef = componentRef;
}
detectChanges(): void {
this._componentParentView.changeDetector.detectChanges();
this._componentParentView.changeDetector.checkNoChanges();
}
destroy(): void { this._componentRef.dispose(); }
}
2015-05-28 15:02:20 -07:00
var _nextRootElementId = 0;
2015-05-15 16:42:52 -07:00
/**
* 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;
this._viewOverrides = new Map();
this._directiveOverrides = new Map();
this._templateOverrides = new Map();
2015-05-15 16:42:52 -07: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}.
* All the other properties of the component's {@link View} are preserved.
2015-05-15 16:42:52 -07:00
*
* @param {Type} component
* @param {string} html
*
* @return {TestComponentBuilder}
*/
overrideTemplate(componentType: Type, template: string): TestComponentBuilder {
var clone = this._clone();
clone._templateOverrides.set(componentType, template);
2015-05-15 16:42:52 -07: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();
clone._viewOverrides.set(componentType, view);
2015-05-15 16:42:52 -07: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();
var overridesForComponent = clone._directiveOverrides.get(componentType);
2015-05-15 16:42:52 -07:00
if (!isPresent(overridesForComponent)) {
clone._directiveOverrides.set(componentType, new Map());
overridesForComponent = clone._directiveOverrides.get(componentType);
2015-05-15 16:42:52 -07:00
}
overridesForComponent.set(from, to);
2015-05-15 16:42:52 -07:00
return clone;
}
/**
* Builds and returns a RootTestComponent.
*
* @return {Promise<RootTestComponent>}
*/
createAsync(rootComponentType: Type): Promise<RootTestComponent> {
var mockViewResolver = this._injector.get(ViewResolver);
2015-05-15 16:42:52 -07:00
MapWrapper.forEach(this._viewOverrides,
(view, type) => { mockViewResolver.setView(type, view); });
MapWrapper.forEach(this._templateOverrides,
(template, type) => { mockViewResolver.setInlineTemplate(type, template); });
2015-05-15 16:42:52 -07:00
MapWrapper.forEach(this._directiveOverrides, (overrides, component) => {
MapWrapper.forEach(overrides, (to, from) => {
mockViewResolver.overrideViewDirective(component, from, to);
2015-05-15 16:42:52 -07:00
});
});
2015-05-28 15:02:20 -07:00
var rootElId = `root${_nextRootElementId++}`;
var rootEl = el(`<div id="${rootElId}"></div>`);
2015-08-10 21:42:47 -07:00
var doc = this._injector.get(DOCUMENT);
2015-05-15 16:42:52 -07:00
// TODO(juliemr): can/should this be optional?
var oldRoots = DOM.querySelectorAll(doc, '[id^=root]');
for (var i = 0; i < oldRoots.length; i++) {
DOM.remove(oldRoots[i]);
}
2015-05-15 16:42:52 -07:00
DOM.appendChild(doc.body, rootEl);
2015-05-15 16:42:52 -07:00
return this._injector.get(DynamicComponentLoader)
2015-05-28 15:02:20 -07:00
.loadAsRoot(rootComponentType, `#${rootElId}`, this._injector)
2015-05-15 16:42:52 -07:00
.then((componentRef) => { return new RootTestComponent(componentRef); });
}
}