import {Inject, Injectable} from 'angular2/di'; import {MapWrapper, ListWrapper, List, Map} from 'angular2/src/facade/collection'; import {PromiseWrapper, Promise} from 'angular2/src/facade/async'; import {DOM} from 'angular2/src/dom/dom_adapter'; import {DomRenderer, DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer'; import {DefaultDomCompiler} from 'angular2/src/render/dom/compiler/compiler'; import {DomView} from 'angular2/src/render/dom/view/view'; import { RenderViewRef, ProtoViewDto, ViewDefinition, EventDispatcher, DirectiveMetadata, RenderElementRef } from 'angular2/src/render/api'; import {resolveInternalDomView} from 'angular2/src/render/dom/view/view'; import {el, dispatchEvent} from 'angular2/test_lib'; export class TestView { rawView: DomView; viewRef: RenderViewRef; events: List>; constructor(viewRef: RenderViewRef) { this.viewRef = viewRef; this.rawView = resolveInternalDomView(viewRef); this.events = []; } } export function elRef(renderView: RenderViewRef, boundElementIndex: number) { return new TestRenderElementRef(renderView, boundElementIndex); } class TestRenderElementRef implements RenderElementRef { constructor(public renderView: RenderViewRef, public boundElementIndex: number) {} } class LoggingEventDispatcher implements EventDispatcher { log: List>; constructor(log: List>) { this.log = log; } dispatchEvent(elementIndex: number, eventName: string, locals: Map) { this.log.push([elementIndex, eventName, locals]); return true; } } @Injectable() export class DomTestbed { renderer: DomRenderer; compiler: DefaultDomCompiler; rootEl; constructor(renderer: DomRenderer, compiler: DefaultDomCompiler, @Inject(DOCUMENT_TOKEN) document) { this.renderer = renderer; this.compiler = compiler; this.rootEl = el('
'); var oldRoots = DOM.querySelectorAll(document, '#root'); for (var i = 0; i < oldRoots.length; i++) { DOM.remove(oldRoots[i]); } DOM.appendChild(DOM.querySelector(document, 'body'), this.rootEl); } compileAll(directivesOrViewDefinitions: List): Promise> { return PromiseWrapper.all(ListWrapper.map(directivesOrViewDefinitions, (entry) => { if (entry instanceof DirectiveMetadata) { return this.compiler.compileHost(entry); } else { return this.compiler.compile(entry); } })); } _createTestView(viewRef: RenderViewRef) { var testView = new TestView(viewRef); this.renderer.setEventDispatcher(viewRef, new LoggingEventDispatcher(testView.events)); return testView; } createRootView(rootProtoView: ProtoViewDto): TestView { var viewRef = this.renderer.createRootHostView(rootProtoView.render, '#root'); this.renderer.hydrateView(viewRef); return this._createTestView(viewRef); } createComponentView(parentViewRef: RenderViewRef, boundElementIndex: number, componentProtoView: ProtoViewDto): TestView { var componentViewRef = this.renderer.createView(componentProtoView.render); this.renderer.attachComponentView(elRef(parentViewRef, boundElementIndex), componentViewRef); this.renderer.hydrateView(componentViewRef); return this._createTestView(componentViewRef); } createRootViews(protoViews: List): List { var views = []; var lastView = this.createRootView(protoViews[0]); views.push(lastView); for (var i = 1; i < protoViews.length; i++) { lastView = this.createComponentView(lastView.viewRef, 0, protoViews[i]); views.push(lastView); } return views; } destroyComponentView(parentViewRef: RenderViewRef, boundElementIndex: number, componentView: RenderViewRef) { this.renderer.dehydrateView(componentView); this.renderer.detachComponentView(elRef(parentViewRef, boundElementIndex), componentView); } createViewInContainer(parentViewRef: RenderViewRef, boundElementIndex: number, atIndex: number, protoView: ProtoViewDto): TestView { var viewRef = this.renderer.createView(protoView.render); this.renderer.attachViewInContainer(elRef(parentViewRef, boundElementIndex), atIndex, viewRef); this.renderer.hydrateView(viewRef); return this._createTestView(viewRef); } destroyViewInContainer(parentViewRef: RenderViewRef, boundElementIndex: number, atIndex: number, viewRef: RenderViewRef) { this.renderer.dehydrateView(viewRef); this.renderer.detachViewInContainer(elRef(parentViewRef, boundElementIndex), atIndex, viewRef); this.renderer.destroyView(viewRef); } triggerEvent(viewRef: RenderViewRef, boundElementIndex: number, eventName: string) { var element = resolveInternalDomView(viewRef).boundElements[boundElementIndex].element; dispatchEvent(element, eventName); } }