repackaging: all the file moves
This commit is contained in:
81
modules/@angular/compiler/testing/directive_resolver_mock.ts
Normal file
81
modules/@angular/compiler/testing/directive_resolver_mock.ts
Normal file
@ -0,0 +1,81 @@
|
||||
import {Injectable} from 'angular2/src/core/di';
|
||||
import {Map, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {Type, isPresent, stringify, isBlank, print} from 'angular2/src/facade/lang';
|
||||
import {DirectiveMetadata, ComponentMetadata} from '../core/metadata';
|
||||
import {DirectiveResolver} from 'angular2/src/compiler/directive_resolver';
|
||||
|
||||
/**
|
||||
* An implementation of {@link DirectiveResolver} that allows overriding
|
||||
* various properties of directives.
|
||||
*/
|
||||
@Injectable()
|
||||
export class MockDirectiveResolver extends DirectiveResolver {
|
||||
private _providerOverrides = new Map<Type, any[]>();
|
||||
private viewProviderOverrides = new Map<Type, any[]>();
|
||||
|
||||
resolve(type: Type): DirectiveMetadata {
|
||||
var dm = super.resolve(type);
|
||||
|
||||
var providerOverrides = this._providerOverrides.get(type);
|
||||
var viewProviderOverrides = this.viewProviderOverrides.get(type);
|
||||
|
||||
var providers = dm.providers;
|
||||
if (isPresent(providerOverrides)) {
|
||||
var originalViewProviders = isPresent(dm.providers) ? dm.providers : [];
|
||||
providers = originalViewProviders.concat(providerOverrides);
|
||||
}
|
||||
|
||||
if (dm instanceof ComponentMetadata) {
|
||||
var viewProviders = dm.viewProviders;
|
||||
if (isPresent(viewProviderOverrides)) {
|
||||
var originalViewProviders = isPresent(dm.viewProviders) ? dm.viewProviders : [];
|
||||
viewProviders = originalViewProviders.concat(viewProviderOverrides);
|
||||
}
|
||||
|
||||
return new ComponentMetadata({
|
||||
selector: dm.selector,
|
||||
inputs: dm.inputs,
|
||||
outputs: dm.outputs,
|
||||
host: dm.host,
|
||||
exportAs: dm.exportAs,
|
||||
moduleId: dm.moduleId,
|
||||
queries: dm.queries,
|
||||
changeDetection: dm.changeDetection,
|
||||
providers: providers,
|
||||
viewProviders: viewProviders
|
||||
});
|
||||
}
|
||||
|
||||
return new DirectiveMetadata({
|
||||
selector: dm.selector,
|
||||
inputs: dm.inputs,
|
||||
outputs: dm.outputs,
|
||||
host: dm.host,
|
||||
providers: providers,
|
||||
exportAs: dm.exportAs,
|
||||
queries: dm.queries
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
setBindingsOverride(type: Type, bindings: any[]): void {
|
||||
this._providerOverrides.set(type, bindings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
setViewBindingsOverride(type: Type, viewBindings: any[]): void {
|
||||
this.viewProviderOverrides.set(type, viewBindings);
|
||||
}
|
||||
|
||||
setProvidersOverride(type: Type, providers: any[]): void {
|
||||
this._providerOverrides.set(type, providers);
|
||||
}
|
||||
|
||||
setViewProvidersOverride(type: Type, viewProviders: any[]): void {
|
||||
this.viewProviderOverrides.set(type, viewProviders);
|
||||
}
|
||||
}
|
16
modules/@angular/compiler/testing/schema_registry_mock.ts
Normal file
16
modules/@angular/compiler/testing/schema_registry_mock.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import {ElementSchemaRegistry} from 'angular2/src/compiler/schema/element_schema_registry';
|
||||
import {isPresent} from 'angular2/src/facade/lang';
|
||||
|
||||
export class MockSchemaRegistry implements ElementSchemaRegistry {
|
||||
constructor(public existingProperties: {[key: string]: boolean},
|
||||
public attrPropMapping: {[key: string]: string}) {}
|
||||
hasProperty(tagName: string, property: string): boolean {
|
||||
var result = this.existingProperties[property];
|
||||
return isPresent(result) ? result : true;
|
||||
}
|
||||
|
||||
getMappedPropName(attrName: string): string {
|
||||
var result = this.attrPropMapping[attrName];
|
||||
return isPresent(result) ? result : attrName;
|
||||
}
|
||||
}
|
405
modules/@angular/compiler/testing/test_component_builder.ts
Normal file
405
modules/@angular/compiler/testing/test_component_builder.ts
Normal file
@ -0,0 +1,405 @@
|
||||
import {
|
||||
OpaqueToken,
|
||||
ComponentRef,
|
||||
ComponentFactory,
|
||||
ComponentResolver,
|
||||
Injector,
|
||||
Injectable,
|
||||
ViewMetadata,
|
||||
ElementRef,
|
||||
EmbeddedViewRef,
|
||||
ChangeDetectorRef,
|
||||
provide,
|
||||
NgZone,
|
||||
NgZoneError
|
||||
} from 'angular2/core';
|
||||
import {DirectiveResolver, ViewResolver} from 'angular2/compiler';
|
||||
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {Type, isPresent, isBlank, IS_DART} from 'angular2/src/facade/lang';
|
||||
import {PromiseWrapper, ObservableWrapper, PromiseCompleter} from 'angular2/src/facade/async';
|
||||
import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
import {el} from './utils';
|
||||
|
||||
import {DOCUMENT} from 'angular2/src/platform/dom/dom_tokens';
|
||||
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
|
||||
|
||||
import {DebugNode, DebugElement, getDebugNode} from 'angular2/src/core/debug/debug_node';
|
||||
|
||||
import {tick} from './fake_async';
|
||||
|
||||
export var ComponentFixtureAutoDetect = new OpaqueToken("ComponentFixtureAutoDetect");
|
||||
export var ComponentFixtureNoNgZone = new OpaqueToken("ComponentFixtureNoNgZone");
|
||||
|
||||
/**
|
||||
* Fixture for debugging and testing a component.
|
||||
*/
|
||||
export class ComponentFixture<T> {
|
||||
/**
|
||||
* The DebugElement associated with the root element of this component.
|
||||
*/
|
||||
debugElement: DebugElement;
|
||||
|
||||
/**
|
||||
* The instance of the root component class.
|
||||
*/
|
||||
componentInstance: any;
|
||||
|
||||
/**
|
||||
* The native element at the root of the component.
|
||||
*/
|
||||
nativeElement: any;
|
||||
|
||||
/**
|
||||
* The ElementRef for the element at the root of the component.
|
||||
*/
|
||||
elementRef: ElementRef;
|
||||
|
||||
/**
|
||||
* The ComponentRef for the component
|
||||
*/
|
||||
componentRef: ComponentRef<T>;
|
||||
|
||||
/**
|
||||
* The ChangeDetectorRef for the component
|
||||
*/
|
||||
changeDetectorRef: ChangeDetectorRef;
|
||||
|
||||
/**
|
||||
* The NgZone in which this component was instantiated.
|
||||
*/
|
||||
ngZone: NgZone;
|
||||
|
||||
private _autoDetect: boolean;
|
||||
|
||||
private _isStable: boolean = true;
|
||||
private _completer: PromiseCompleter<any> = null;
|
||||
private _onUnstableSubscription = null;
|
||||
private _onStableSubscription = null;
|
||||
private _onMicrotaskEmptySubscription = null;
|
||||
private _onErrorSubscription = null;
|
||||
|
||||
constructor(componentRef: ComponentRef<T>, ngZone: NgZone, autoDetect: boolean) {
|
||||
this.changeDetectorRef = componentRef.changeDetectorRef;
|
||||
this.elementRef = componentRef.location;
|
||||
this.debugElement = <DebugElement>getDebugNode(this.elementRef.nativeElement);
|
||||
this.componentInstance = componentRef.instance;
|
||||
this.nativeElement = this.elementRef.nativeElement;
|
||||
this.componentRef = componentRef;
|
||||
this.ngZone = ngZone;
|
||||
this._autoDetect = autoDetect;
|
||||
|
||||
if (ngZone != null) {
|
||||
this._onUnstableSubscription =
|
||||
ObservableWrapper.subscribe(ngZone.onUnstable, (_) => { this._isStable = false; });
|
||||
this._onMicrotaskEmptySubscription =
|
||||
ObservableWrapper.subscribe(ngZone.onMicrotaskEmpty, (_) => {
|
||||
if (this._autoDetect) {
|
||||
// Do a change detection run with checkNoChanges set to true to check
|
||||
// there are no changes on the second run.
|
||||
this.detectChanges(true);
|
||||
}
|
||||
});
|
||||
this._onStableSubscription = ObservableWrapper.subscribe(ngZone.onStable, (_) => {
|
||||
this._isStable = true;
|
||||
if (this._completer != null) {
|
||||
this._completer.resolve(true);
|
||||
this._completer = null;
|
||||
}
|
||||
});
|
||||
|
||||
this._onErrorSubscription = ObservableWrapper.subscribe(
|
||||
ngZone.onError, (error: NgZoneError) => { throw error.error; });
|
||||
}
|
||||
}
|
||||
|
||||
private _tick(checkNoChanges: boolean) {
|
||||
this.changeDetectorRef.detectChanges();
|
||||
if (checkNoChanges) {
|
||||
this.checkNoChanges();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a change detection cycle for the component.
|
||||
*/
|
||||
detectChanges(checkNoChanges: boolean = true): void {
|
||||
if (this.ngZone != null) {
|
||||
// Run the change detection inside the NgZone so that any async tasks as part of the change
|
||||
// detection are captured by the zone and can be waited for in isStable.
|
||||
this.ngZone.run(() => { this._tick(checkNoChanges); });
|
||||
} else {
|
||||
// Running without zone. Just do the change detection.
|
||||
this._tick(checkNoChanges);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a change detection run to make sure there were no changes.
|
||||
*/
|
||||
checkNoChanges(): void { this.changeDetectorRef.checkNoChanges(); }
|
||||
|
||||
/**
|
||||
* Set whether the fixture should autodetect changes.
|
||||
*
|
||||
* Also runs detectChanges once so that any existing change is detected.
|
||||
*/
|
||||
autoDetectChanges(autoDetect: boolean = true) {
|
||||
if (this.ngZone == null) {
|
||||
throw new BaseException('Cannot call autoDetectChanges when ComponentFixtureNoNgZone is set');
|
||||
}
|
||||
this._autoDetect = autoDetect;
|
||||
this.detectChanges();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the fixture is currently stable or has async tasks that have not been completed
|
||||
* yet.
|
||||
*/
|
||||
isStable(): boolean { return this._isStable; }
|
||||
|
||||
/**
|
||||
* Get a promise that resolves when the fixture is stable.
|
||||
*
|
||||
* This can be used to resume testing after events have triggered asynchronous activity or
|
||||
* asynchronous change detection.
|
||||
*/
|
||||
whenStable(): Promise<any> {
|
||||
if (this._isStable) {
|
||||
return PromiseWrapper.resolve(false);
|
||||
} else {
|
||||
this._completer = new PromiseCompleter<any>();
|
||||
return this._completer.promise;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger component destruction.
|
||||
*/
|
||||
destroy(): void {
|
||||
this.componentRef.destroy();
|
||||
if (this._onUnstableSubscription != null) {
|
||||
ObservableWrapper.dispose(this._onUnstableSubscription);
|
||||
this._onUnstableSubscription = null;
|
||||
}
|
||||
if (this._onStableSubscription != null) {
|
||||
ObservableWrapper.dispose(this._onStableSubscription);
|
||||
this._onStableSubscription = null;
|
||||
}
|
||||
if (this._onMicrotaskEmptySubscription != null) {
|
||||
ObservableWrapper.dispose(this._onMicrotaskEmptySubscription);
|
||||
this._onMicrotaskEmptySubscription = null;
|
||||
}
|
||||
if (this._onErrorSubscription != null) {
|
||||
ObservableWrapper.dispose(this._onErrorSubscription);
|
||||
this._onErrorSubscription = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var _nextRootElementId = 0;
|
||||
|
||||
/**
|
||||
* Builds a ComponentFixture for use in component level tests.
|
||||
*/
|
||||
@Injectable()
|
||||
export class TestComponentBuilder {
|
||||
/** @internal */
|
||||
_bindingsOverrides = new Map<Type, any[]>();
|
||||
/** @internal */
|
||||
_directiveOverrides = new Map<Type, Map<Type, Type>>();
|
||||
/** @internal */
|
||||
_templateOverrides = new Map<Type, string>();
|
||||
/** @internal */
|
||||
_viewBindingsOverrides = new Map<Type, any[]>();
|
||||
/** @internal */
|
||||
_viewOverrides = new Map<Type, ViewMetadata>();
|
||||
|
||||
|
||||
constructor(private _injector: Injector) {}
|
||||
|
||||
/** @internal */
|
||||
_clone(): TestComponentBuilder {
|
||||
let clone = new TestComponentBuilder(this._injector);
|
||||
clone._viewOverrides = MapWrapper.clone(this._viewOverrides);
|
||||
clone._directiveOverrides = MapWrapper.clone(this._directiveOverrides);
|
||||
clone._templateOverrides = MapWrapper.clone(this._templateOverrides);
|
||||
clone._bindingsOverrides = MapWrapper.clone(this._bindingsOverrides);
|
||||
clone._viewBindingsOverrides = MapWrapper.clone(this._viewBindingsOverrides);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides only the html of a {@link ComponentMetadata}.
|
||||
* All the other properties of the component's {@link ViewMetadata} are preserved.
|
||||
*
|
||||
* @param {Type} component
|
||||
* @param {string} html
|
||||
*
|
||||
* @return {TestComponentBuilder}
|
||||
*/
|
||||
overrideTemplate(componentType: Type, template: string): TestComponentBuilder {
|
||||
let clone = this._clone();
|
||||
clone._templateOverrides.set(componentType, template);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides a component's {@link ViewMetadata}.
|
||||
*
|
||||
* @param {Type} component
|
||||
* @param {view} View
|
||||
*
|
||||
* @return {TestComponentBuilder}
|
||||
*/
|
||||
overrideView(componentType: Type, view: ViewMetadata): TestComponentBuilder {
|
||||
let clone = this._clone();
|
||||
clone._viewOverrides.set(componentType, view);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the directives from the component {@link ViewMetadata}.
|
||||
*
|
||||
* @param {Type} component
|
||||
* @param {Type} from
|
||||
* @param {Type} to
|
||||
*
|
||||
* @return {TestComponentBuilder}
|
||||
*/
|
||||
overrideDirective(componentType: Type, from: Type, to: Type): TestComponentBuilder {
|
||||
let clone = this._clone();
|
||||
let overridesForComponent = clone._directiveOverrides.get(componentType);
|
||||
if (!isPresent(overridesForComponent)) {
|
||||
clone._directiveOverrides.set(componentType, new Map<Type, Type>());
|
||||
overridesForComponent = clone._directiveOverrides.get(componentType);
|
||||
}
|
||||
overridesForComponent.set(from, to);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides one or more injectables configured via `providers` metadata property of a directive
|
||||
* or
|
||||
* component.
|
||||
* Very useful when certain providers need to be mocked out.
|
||||
*
|
||||
* The providers specified via this method are appended to the existing `providers` causing the
|
||||
* duplicated providers to
|
||||
* be overridden.
|
||||
*
|
||||
* @param {Type} component
|
||||
* @param {any[]} providers
|
||||
*
|
||||
* @return {TestComponentBuilder}
|
||||
*/
|
||||
overrideProviders(type: Type, providers: any[]): TestComponentBuilder {
|
||||
let clone = this._clone();
|
||||
clone._bindingsOverrides.set(type, providers);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
overrideBindings(type: Type, providers: any[]): TestComponentBuilder {
|
||||
return this.overrideProviders(type, providers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides one or more injectables configured via `providers` metadata property of a directive
|
||||
* or
|
||||
* component.
|
||||
* Very useful when certain providers need to be mocked out.
|
||||
*
|
||||
* The providers specified via this method are appended to the existing `providers` causing the
|
||||
* duplicated providers to
|
||||
* be overridden.
|
||||
*
|
||||
* @param {Type} component
|
||||
* @param {any[]} providers
|
||||
*
|
||||
* @return {TestComponentBuilder}
|
||||
*/
|
||||
overrideViewProviders(type: Type, providers: any[]): TestComponentBuilder {
|
||||
let clone = this._clone();
|
||||
clone._viewBindingsOverrides.set(type, providers);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
overrideViewBindings(type: Type, providers: any[]): TestComponentBuilder {
|
||||
return this.overrideViewProviders(type, providers);
|
||||
}
|
||||
|
||||
private _create<C>(ngZone: NgZone, componentFactory: ComponentFactory<C>): ComponentFixture<C> {
|
||||
let rootElId = `root${_nextRootElementId++}`;
|
||||
let rootEl = el(`<div id="${rootElId}"></div>`);
|
||||
let doc = this._injector.get(DOCUMENT);
|
||||
|
||||
// TODO(juliemr): can/should this be optional?
|
||||
let oldRoots = DOM.querySelectorAll(doc, '[id^=root]');
|
||||
for (let i = 0; i < oldRoots.length; i++) {
|
||||
DOM.remove(oldRoots[i]);
|
||||
}
|
||||
DOM.appendChild(doc.body, rootEl);
|
||||
var componentRef = componentFactory.create(this._injector, [], `#${rootElId}`);
|
||||
let autoDetect: boolean = this._injector.get(ComponentFixtureAutoDetect, false);
|
||||
return new ComponentFixture<any /*C*/>(componentRef, ngZone, autoDetect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns a ComponentFixture.
|
||||
*
|
||||
* @return {Promise<ComponentFixture>}
|
||||
*/
|
||||
createAsync(rootComponentType: Type): Promise<ComponentFixture<any>> {
|
||||
let noNgZone = IS_DART || this._injector.get(ComponentFixtureNoNgZone, false);
|
||||
let ngZone: NgZone = noNgZone ? null : this._injector.get(NgZone, null);
|
||||
|
||||
let initComponent = () => {
|
||||
let mockDirectiveResolver = this._injector.get(DirectiveResolver);
|
||||
let mockViewResolver = this._injector.get(ViewResolver);
|
||||
this._viewOverrides.forEach((view, type) => mockViewResolver.setView(type, view));
|
||||
this._templateOverrides.forEach((template, type) =>
|
||||
mockViewResolver.setInlineTemplate(type, template));
|
||||
this._directiveOverrides.forEach((overrides, component) => {
|
||||
overrides.forEach(
|
||||
(to, from) => { mockViewResolver.overrideViewDirective(component, from, to); });
|
||||
});
|
||||
this._bindingsOverrides.forEach(
|
||||
(bindings, type) => mockDirectiveResolver.setBindingsOverride(type, bindings));
|
||||
this._viewBindingsOverrides.forEach(
|
||||
(bindings, type) => mockDirectiveResolver.setViewBindingsOverride(type, bindings));
|
||||
|
||||
let promise: Promise<ComponentFactory<any>> =
|
||||
this._injector.get(ComponentResolver).resolveComponent(rootComponentType);
|
||||
return promise.then(componentFactory => this._create(ngZone, componentFactory));
|
||||
};
|
||||
|
||||
return ngZone == null ? initComponent() : ngZone.run(initComponent);
|
||||
}
|
||||
|
||||
createFakeAsync(rootComponentType: Type): ComponentFixture<any> {
|
||||
let result;
|
||||
let error;
|
||||
PromiseWrapper.then(this.createAsync(rootComponentType), (_result) => { result = _result; },
|
||||
(_error) => { error = _error; });
|
||||
tick();
|
||||
if (isPresent(error)) {
|
||||
throw error;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
createSync<C>(componentFactory: ComponentFactory<C>): ComponentFixture<C> {
|
||||
let noNgZone = IS_DART || this._injector.get(ComponentFixtureNoNgZone, false);
|
||||
let ngZone: NgZone = noNgZone ? null : this._injector.get(NgZone, null);
|
||||
|
||||
let initComponent = () => this._create(ngZone, componentFactory);
|
||||
return ngZone == null ? initComponent() : ngZone.run(initComponent);
|
||||
}
|
||||
}
|
141
modules/@angular/compiler/testing/view_resolver_mock.ts
Normal file
141
modules/@angular/compiler/testing/view_resolver_mock.ts
Normal file
@ -0,0 +1,141 @@
|
||||
import {resolveForwardRef} from 'angular2/src/core/di';
|
||||
import {Injectable} from 'angular2/src/core/di';
|
||||
import {Map, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {Type, isPresent, isArray, stringify, isBlank} from 'angular2/src/facade/lang';
|
||||
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
||||
|
||||
import {ViewMetadata} from '../core/metadata';
|
||||
import {ViewResolver} from 'angular2/src/compiler/view_resolver';
|
||||
|
||||
@Injectable()
|
||||
export class MockViewResolver extends ViewResolver {
|
||||
/** @internal */
|
||||
_views = new Map<Type, ViewMetadata>();
|
||||
/** @internal */
|
||||
_inlineTemplates = new Map<Type, string>();
|
||||
/** @internal */
|
||||
_viewCache = new Map<Type, ViewMetadata>();
|
||||
/** @internal */
|
||||
_directiveOverrides = new Map<Type, Map<Type, Type>>();
|
||||
|
||||
constructor() { super(); }
|
||||
|
||||
/**
|
||||
* Overrides the {@link ViewMetadata} for a component.
|
||||
*
|
||||
* @param {Type} component
|
||||
* @param {ViewDefinition} view
|
||||
*/
|
||||
setView(component: Type, view: ViewMetadata): void {
|
||||
this._checkOverrideable(component);
|
||||
this._views.set(component, view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the inline template for a component - other configuration remains unchanged.
|
||||
*
|
||||
* @param {Type} component
|
||||
* @param {string} template
|
||||
*/
|
||||
setInlineTemplate(component: Type, template: string): void {
|
||||
this._checkOverrideable(component);
|
||||
this._inlineTemplates.set(component, template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides a directive from the component {@link ViewMetadata}.
|
||||
*
|
||||
* @param {Type} component
|
||||
* @param {Type} from
|
||||
* @param {Type} to
|
||||
*/
|
||||
overrideViewDirective(component: Type, from: Type, to: Type): void {
|
||||
this._checkOverrideable(component);
|
||||
|
||||
var overrides = this._directiveOverrides.get(component);
|
||||
|
||||
if (isBlank(overrides)) {
|
||||
overrides = new Map<Type, Type>();
|
||||
this._directiveOverrides.set(component, overrides);
|
||||
}
|
||||
|
||||
overrides.set(from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ViewMetadata} for a component:
|
||||
* - Set the {@link ViewMetadata} to the overridden view when it exists or fallback to the default
|
||||
* `ViewResolver`,
|
||||
* see `setView`.
|
||||
* - Override the directives, see `overrideViewDirective`.
|
||||
* - Override the @View definition, see `setInlineTemplate`.
|
||||
*
|
||||
* @param component
|
||||
* @returns {ViewDefinition}
|
||||
*/
|
||||
resolve(component: Type): ViewMetadata {
|
||||
var view = this._viewCache.get(component);
|
||||
if (isPresent(view)) return view;
|
||||
|
||||
view = this._views.get(component);
|
||||
if (isBlank(view)) {
|
||||
view = super.resolve(component);
|
||||
}
|
||||
|
||||
var directives = [];
|
||||
var overrides = this._directiveOverrides.get(component);
|
||||
|
||||
if (isPresent(overrides) && isPresent(view.directives)) {
|
||||
flattenArray(view.directives, directives);
|
||||
overrides.forEach((to, from) => {
|
||||
var srcIndex = directives.indexOf(from);
|
||||
if (srcIndex == -1) {
|
||||
throw new BaseException(
|
||||
`Overriden directive ${stringify(from)} not found in the template of ${stringify(component)}`);
|
||||
}
|
||||
directives[srcIndex] = to;
|
||||
});
|
||||
view = new ViewMetadata(
|
||||
{template: view.template, templateUrl: view.templateUrl, directives: directives});
|
||||
}
|
||||
|
||||
var inlineTemplate = this._inlineTemplates.get(component);
|
||||
if (isPresent(inlineTemplate)) {
|
||||
view = new ViewMetadata(
|
||||
{template: inlineTemplate, templateUrl: null, directives: view.directives});
|
||||
}
|
||||
|
||||
this._viewCache.set(component, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Once a component has been compiled, the AppProtoView is stored in the compiler cache.
|
||||
*
|
||||
* Then it should not be possible to override the component configuration after the component
|
||||
* has been compiled.
|
||||
*
|
||||
* @param {Type} component
|
||||
*/
|
||||
_checkOverrideable(component: Type): void {
|
||||
var cached = this._viewCache.get(component);
|
||||
|
||||
if (isPresent(cached)) {
|
||||
throw new BaseException(
|
||||
`The component ${stringify(component)} has already been compiled, its configuration can not be changed`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function flattenArray(tree: any[], out: Array<Type | any[]>): void {
|
||||
for (var i = 0; i < tree.length; i++) {
|
||||
var item = resolveForwardRef(tree[i]);
|
||||
if (isArray(item)) {
|
||||
flattenArray(item, out);
|
||||
} else {
|
||||
out.push(item);
|
||||
}
|
||||
}
|
||||
}
|
122
modules/@angular/compiler/testing/xhr_mock.ts
Normal file
122
modules/@angular/compiler/testing/xhr_mock.ts
Normal file
@ -0,0 +1,122 @@
|
||||
import {XHR} from 'angular2/src/compiler/xhr';
|
||||
import {ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection';
|
||||
import {isBlank, isPresent, normalizeBlank} from 'angular2/src/facade/lang';
|
||||
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
||||
import {PromiseCompleter, PromiseWrapper} from 'angular2/src/facade/async';
|
||||
|
||||
/**
|
||||
* A mock implementation of {@link XHR} that allows outgoing requests to be mocked
|
||||
* and responded to within a single test, without going to the network.
|
||||
*/
|
||||
export class MockXHR extends XHR {
|
||||
private _expectations: _Expectation[] = [];
|
||||
private _definitions = new Map<string, string>();
|
||||
private _requests: _PendingRequest[] = [];
|
||||
|
||||
get(url: string): Promise<string> {
|
||||
var request = new _PendingRequest(url);
|
||||
this._requests.push(request);
|
||||
return request.getPromise();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an expectation for the given URL. Incoming requests will be checked against
|
||||
* the next expectation (in FIFO order). The `verifyNoOutstandingExpectations` method
|
||||
* can be used to check if any expectations have not yet been met.
|
||||
*
|
||||
* The response given will be returned if the expectation matches.
|
||||
*/
|
||||
expect(url: string, response: string) {
|
||||
var expectation = new _Expectation(url, response);
|
||||
this._expectations.push(expectation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a definition for the given URL to return the given response. Unlike expectations,
|
||||
* definitions have no order and will satisfy any matching request at any time. Also
|
||||
* unlike expectations, unused definitions do not cause `verifyNoOutstandingExpectations`
|
||||
* to return an error.
|
||||
*/
|
||||
when(url: string, response: string) { this._definitions.set(url, response); }
|
||||
|
||||
/**
|
||||
* Process pending requests and verify there are no outstanding expectations. Also fails
|
||||
* if no requests are pending.
|
||||
*/
|
||||
flush() {
|
||||
if (this._requests.length === 0) {
|
||||
throw new BaseException('No pending requests to flush');
|
||||
}
|
||||
|
||||
do {
|
||||
this._processRequest(this._requests.shift());
|
||||
} while (this._requests.length > 0);
|
||||
|
||||
this.verifyNoOutstandingExpectations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception if any expectations have not been satisfied.
|
||||
*/
|
||||
verifyNoOutstandingExpectations() {
|
||||
if (this._expectations.length === 0) return;
|
||||
|
||||
var urls = [];
|
||||
for (var i = 0; i < this._expectations.length; i++) {
|
||||
var expectation = this._expectations[i];
|
||||
urls.push(expectation.url);
|
||||
}
|
||||
|
||||
throw new BaseException(`Unsatisfied requests: ${urls.join(', ')}`);
|
||||
}
|
||||
|
||||
private _processRequest(request: _PendingRequest) {
|
||||
var url = request.url;
|
||||
|
||||
if (this._expectations.length > 0) {
|
||||
var expectation = this._expectations[0];
|
||||
if (expectation.url == url) {
|
||||
ListWrapper.remove(this._expectations, expectation);
|
||||
request.complete(expectation.response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._definitions.has(url)) {
|
||||
var response = this._definitions.get(url);
|
||||
request.complete(normalizeBlank(response));
|
||||
return;
|
||||
}
|
||||
|
||||
throw new BaseException(`Unexpected request ${url}`);
|
||||
}
|
||||
}
|
||||
|
||||
class _PendingRequest {
|
||||
url: string;
|
||||
completer: PromiseCompleter<string>;
|
||||
|
||||
constructor(url) {
|
||||
this.url = url;
|
||||
this.completer = PromiseWrapper.completer();
|
||||
}
|
||||
|
||||
complete(response: string) {
|
||||
if (isBlank(response)) {
|
||||
this.completer.reject(`Failed to load ${this.url}`, null);
|
||||
} else {
|
||||
this.completer.resolve(response);
|
||||
}
|
||||
}
|
||||
|
||||
getPromise(): Promise<string> { return this.completer.promise; }
|
||||
}
|
||||
|
||||
class _Expectation {
|
||||
url: string;
|
||||
response: string;
|
||||
constructor(url: string, response: string) {
|
||||
this.url = url;
|
||||
this.response = response;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user