import {describe, beforeEach, it, expect, iit, ddescribe, el} from 'angular2/test_lib'; import {ListWrapper, List, MapWrapper} from 'angular2/src/facade/collection'; import {DOM} from 'angular2/src/dom/dom_adapter'; import {isPresent, NumberWrapper, StringWrapper, IMPLEMENTS} from 'angular2/src/facade/lang'; import {CompilePipeline} from 'angular2/src/render/dom/compiler/compile_pipeline'; import {CompileElement} from 'angular2/src/render/dom/compiler/compile_element'; import {CompileStep} from 'angular2/src/render/dom/compiler/compile_step'; import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control'; import {ProtoViewBuilder} from 'angular2/src/render/dom/view/proto_view_builder'; import {ProtoViewDto, ViewType, ViewEncapsulation, ViewDefinition} from 'angular2/src/render/api'; export function main() { describe('compile_pipeline', () => { function createViewDefinition(): ViewDefinition { return new ViewDefinition({componentId: 'someComponent'}); } describe('children compilation', () => { it('should walk the tree in depth first order including template contents', () => { var element = el('
'); var step0Log = []; var results = new CompilePipeline([createLoggerStep(step0Log)]) .processElements(element, ViewType.COMPONENT, createViewDefinition()); expect(step0Log).toEqual(['1', '1<2', '2<3']); expect(resultIdLog(results)).toEqual(['1', '2', '3']); }); it('should stop walking the tree when compileChildren is false', () => { var element = el( '
'); var step0Log = []; var pipeline = new CompilePipeline([new IgnoreChildrenStep(), createLoggerStep(step0Log)]); var results = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition()); expect(step0Log).toEqual(['1', '1<2']); expect(resultIdLog(results)).toEqual(['1', '2']); }); }); it('should inherit protoViewBuilders to children', () => { var element = el('
'); var pipeline = new CompilePipeline([ new MockStep((parent, current, control) => { if (isPresent(DOM.getAttribute(current.element, 'viewroot'))) { current.inheritedProtoView = new ProtoViewBuilder(current.element, ViewType.EMBEDDED, ViewEncapsulation.NONE); } }) ]); var results = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition()); expect(results[0].inheritedProtoView).toBe(results[1].inheritedProtoView); expect(results[2].inheritedProtoView).toBe(results[3].inheritedProtoView); }); it('should inherit elementBinderBuilders to children', () => { var element = el('
'); var pipeline = new CompilePipeline([ new MockStep((parent, current, control) => { if (isPresent(DOM.getAttribute(current.element, 'bind'))) { current.bindElement(); } }) ]); var results = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition()); expect(results[0].inheritedElementBinder).toBe(results[1].inheritedElementBinder); expect(results[2].inheritedElementBinder).toBe(results[3].inheritedElementBinder); }); it('should mark root elements as viewRoot', () => { var rootElement = el('
'); var results = new CompilePipeline([]) .processElements(rootElement, ViewType.COMPONENT, createViewDefinition()); expect(results[0].isViewRoot).toBe(true); }); it('should calculate distanceToParent / parent correctly', () => { var element = el('
'); var pipeline = new CompilePipeline([ new MockStep((parent, current, control) => { if (isPresent(DOM.getAttribute(current.element, 'bind'))) { current.bindElement(); } }) ]); var results = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition()); expect(results[0].inheritedElementBinder.distanceToParent).toBe(0); expect(results[1].inheritedElementBinder.distanceToParent).toBe(1); expect(results[3].inheritedElementBinder.distanceToParent).toBe(2); expect(results[1].inheritedElementBinder.parent).toBe(results[0].inheritedElementBinder); expect(results[3].inheritedElementBinder.parent).toBe(results[0].inheritedElementBinder); }); it('should not execute further steps when ignoreCurrentElement has been called', () => { var element = el('
'); var logs = []; var pipeline = new CompilePipeline([ new IgnoreCurrentElementStep(), createLoggerStep(logs), ]); var results = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition()); expect(results.length).toBe(2); expect(logs).toEqual(['1', '1<3']) }); describe('control.addParent', () => { it('should report the new parent to the following processor and the result', () => { var element = el('
'); var step0Log = []; var step1Log = []; var pipeline = new CompilePipeline([createWrapperStep('wrap0', step0Log), createLoggerStep(step1Log)]); var result = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition()); expect(step0Log).toEqual(['1', '1<2', '2<3']); expect(step1Log).toEqual(['1', '1 { var element = el('
'); var step0Log = []; var step1Log = []; var step2Log = []; var pipeline = new CompilePipeline([ createWrapperStep('wrap0', step0Log), createWrapperStep('wrap1', step1Log), createLoggerStep(step2Log) ]); var result = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition()); expect(step0Log).toEqual(['1', '1<2', '2<3']); expect(step1Log).toEqual(['1', '1 { var element = el('
'); var step0Log = []; var step1Log = []; var step2Log = []; var pipeline = new CompilePipeline([ createWrapperStep('wrap0', step0Log), createWrapperStep('wrap1', step1Log), createLoggerStep(step2Log) ]); var result = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition()); expect(step0Log).toEqual(['1', '1<2', '2<3']); expect(step1Log).toEqual(['1', '1 { var element = el('
'); var step0Log = []; var step1Log = []; var pipeline = new CompilePipeline([createWrapperStep('wrap0', step0Log), createLoggerStep(step1Log)]); var result = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition()); expect(step0Log).toEqual(['1', '1<2', '2<3']); expect(step1Log).toEqual(['1', '1 { it('should report the new child to all processors and the result', () => { var element = el('
'); var resultLog = []; var newChild = new CompileElement(el('
')); var pipeline = new CompilePipeline([ new MockStep((parent, current, control) => { if (StringWrapper.equals(DOM.getAttribute(current.element, 'id'), '1')) { control.addChild(newChild); } }), createLoggerStep(resultLog) ]); var result = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition()); expect(result[2]).toBe(newChild); expect(resultLog).toEqual(['1', '1<2', '1<3']); expect(resultIdLog(result)).toEqual(['1', '2', '3']); }); }); describe('processStyles', () => { it('should call the steps for every style', () => { var stepCalls = []; var pipeline = new CompilePipeline([ new MockStep(null, (style) => { stepCalls.push(style); return style; }) ]); var result = pipeline.processStyles(['a', 'b']); expect(result[0]).toEqual('a'); expect(result[1]).toEqual('b'); expect(result).toEqual(stepCalls); }); }); }); } export class MockStep implements CompileStep { constructor(private processElementClosure: Function, private processStyleClosure: Function = null) {} processElement(parent: CompileElement, current: CompileElement, control: CompileControl) { if (isPresent(this.processElementClosure)) { this.processElementClosure(parent, current, control); } } processStyle(style: string): string { if (isPresent(this.processStyleClosure)) { return this.processStyleClosure(style); } else { return style; } } } export class IgnoreChildrenStep implements CompileStep { processElement(parent: CompileElement, current: CompileElement, control: CompileControl) { var attributeMap = DOM.attributeMap(current.element); if (attributeMap.has('ignore-children')) { current.compileChildren = false; } } processStyle(style: string): string { return style; } } class IgnoreCurrentElementStep implements CompileStep { processElement(parent: CompileElement, current: CompileElement, control: CompileControl) { var attributeMap = DOM.attributeMap(current.element); if (attributeMap.has('ignore-current')) { control.ignoreCurrentElement(); } } processStyle(style: string): string { return style; } } function logEntry(log: string[], parent, current) { var parentId = ''; if (isPresent(parent)) { parentId = DOM.getAttribute(parent.element, 'id') + '<'; } log.push(parentId + DOM.getAttribute(current.element, 'id')); } function createLoggerStep(log: string[]) { return new MockStep((parent, current, control) => { logEntry(log, parent, current); }); } function createWrapperStep(wrapperId, log) { var nextElementId = 0; return new MockStep((parent, current, control) => { var parentCountStr = DOM.getAttribute(current.element, wrapperId); if (isPresent(parentCountStr)) { var parentCount = NumberWrapper.parseInt(parentCountStr, 10); while (parentCount > 0) { control.addParent(new CompileElement(el(``))); parentCount--; } } logEntry(log, parent, current); }); } function resultIdLog(result) { var idLog = []; ListWrapper.forEach(result, (current) => { logEntry(idLog, null, current); }); return idLog; }