2015-03-23 17:10:55 -04:00
|
|
|
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';
|
2015-05-18 14:57:20 -04:00
|
|
|
import {isPresent, NumberWrapper, StringWrapper, IMPLEMENTS} from 'angular2/src/facade/lang';
|
2015-03-23 17:10:55 -04:00
|
|
|
|
|
|
|
import {CompilePipeline} from 'angular2/src/render/dom/compiler/compile_pipeline';
|
|
|
|
import {CompileElement} from 'angular2/src/render/dom/compiler/compile_element';
|
2015-05-26 12:25:39 -04:00
|
|
|
import {CompileStep} from 'angular2/src/render/dom/compiler/compile_step';
|
2015-03-23 17:10:55 -04:00
|
|
|
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
|
|
|
|
|
|
|
|
import {ProtoViewBuilder} from 'angular2/src/render/dom/view/proto_view_builder';
|
2015-07-24 18:28:44 -04:00
|
|
|
import {ProtoViewDto, ViewType, ViewEncapsulation, ViewDefinition} from 'angular2/src/render/api';
|
2015-03-23 17:10:55 -04:00
|
|
|
|
|
|
|
export function main() {
|
|
|
|
describe('compile_pipeline', () => {
|
2015-07-24 18:28:44 -04:00
|
|
|
function createViewDefinition(): ViewDefinition {
|
|
|
|
return new ViewDefinition({componentId: 'someComponent'});
|
|
|
|
}
|
|
|
|
|
2015-03-23 17:10:55 -04:00
|
|
|
describe('children compilation', () => {
|
|
|
|
it('should walk the tree in depth first order including template contents', () => {
|
|
|
|
var element = el('<div id="1"><template id="2"><span id="3"></span></template></div>');
|
|
|
|
|
|
|
|
var step0Log = [];
|
2015-07-24 18:28:44 -04:00
|
|
|
var results = new CompilePipeline([createLoggerStep(step0Log)])
|
|
|
|
.processElements(element, ViewType.COMPONENT, createViewDefinition());
|
2015-03-23 17:10:55 -04:00
|
|
|
|
|
|
|
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', () => {
|
2015-05-26 12:25:39 -04:00
|
|
|
var element = el(
|
|
|
|
'<div id="1"><template id="2" ignore-children><span id="3"></span></template></div>');
|
2015-03-23 17:10:55 -04:00
|
|
|
|
|
|
|
var step0Log = [];
|
|
|
|
var pipeline = new CompilePipeline([new IgnoreChildrenStep(), createLoggerStep(step0Log)]);
|
2015-07-24 18:28:44 -04:00
|
|
|
var results = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition());
|
2015-03-23 17:10:55 -04:00
|
|
|
|
|
|
|
expect(step0Log).toEqual(['1', '1<2']);
|
|
|
|
expect(resultIdLog(results)).toEqual(['1', '2']);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should inherit protoViewBuilders to children', () => {
|
|
|
|
var element = el('<div><div><span viewroot><span></span></span></div></div>');
|
2015-06-03 16:42:57 -04:00
|
|
|
var pipeline = new CompilePipeline([
|
|
|
|
new MockStep((parent, current, control) => {
|
|
|
|
if (isPresent(DOM.getAttribute(current.element, 'viewroot'))) {
|
2015-07-24 18:28:44 -04:00
|
|
|
current.inheritedProtoView =
|
|
|
|
new ProtoViewBuilder(current.element, ViewType.EMBEDDED, ViewEncapsulation.NONE);
|
2015-06-03 16:42:57 -04:00
|
|
|
}
|
|
|
|
})
|
|
|
|
]);
|
2015-07-24 18:28:44 -04:00
|
|
|
var results = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition());
|
2015-03-23 17:10:55 -04:00
|
|
|
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('<div bind><div><span bind><span></span></span></div></div>');
|
2015-06-03 16:42:57 -04:00
|
|
|
var pipeline = new CompilePipeline([
|
|
|
|
new MockStep((parent, current, control) => {
|
|
|
|
if (isPresent(DOM.getAttribute(current.element, 'bind'))) {
|
|
|
|
current.bindElement();
|
|
|
|
}
|
|
|
|
})
|
|
|
|
]);
|
2015-07-24 18:28:44 -04:00
|
|
|
var results = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition());
|
2015-03-23 17:10:55 -04:00
|
|
|
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('<div></div>');
|
2015-07-24 18:28:44 -04:00
|
|
|
var results = new CompilePipeline([])
|
|
|
|
.processElements(rootElement, ViewType.COMPONENT, createViewDefinition());
|
2015-03-23 17:10:55 -04:00
|
|
|
expect(results[0].isViewRoot).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should calculate distanceToParent / parent correctly', () => {
|
|
|
|
var element = el('<div bind><div bind></div><div><div bind></div></div></div>');
|
2015-06-03 16:42:57 -04:00
|
|
|
var pipeline = new CompilePipeline([
|
|
|
|
new MockStep((parent, current, control) => {
|
|
|
|
if (isPresent(DOM.getAttribute(current.element, 'bind'))) {
|
|
|
|
current.bindElement();
|
|
|
|
}
|
|
|
|
})
|
|
|
|
]);
|
2015-07-24 18:28:44 -04:00
|
|
|
var results = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition());
|
2015-03-23 17:10:55 -04:00
|
|
|
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);
|
|
|
|
});
|
|
|
|
|
2015-04-10 10:12:37 -04:00
|
|
|
it('should not execute further steps when ignoreCurrentElement has been called', () => {
|
|
|
|
var element = el('<div id="1"><span id="2" ignore-current></span><span id="3"></span></div>');
|
|
|
|
var logs = [];
|
|
|
|
var pipeline = new CompilePipeline([
|
|
|
|
new IgnoreCurrentElementStep(),
|
|
|
|
createLoggerStep(logs),
|
|
|
|
]);
|
2015-07-24 18:28:44 -04:00
|
|
|
var results = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition());
|
2015-04-10 10:12:37 -04:00
|
|
|
|
|
|
|
expect(results.length).toBe(2);
|
|
|
|
expect(logs).toEqual(['1', '1<3'])
|
|
|
|
});
|
|
|
|
|
2015-03-23 17:10:55 -04:00
|
|
|
describe('control.addParent', () => {
|
|
|
|
it('should report the new parent to the following processor and the result', () => {
|
|
|
|
var element = el('<div id="1"><span wrap0="1" id="2"><b id="3"></b></span></div>');
|
|
|
|
var step0Log = [];
|
|
|
|
var step1Log = [];
|
2015-06-03 16:42:57 -04:00
|
|
|
var pipeline =
|
|
|
|
new CompilePipeline([createWrapperStep('wrap0', step0Log), createLoggerStep(step1Log)]);
|
2015-07-24 18:28:44 -04:00
|
|
|
var result = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition());
|
2015-03-23 17:10:55 -04:00
|
|
|
expect(step0Log).toEqual(['1', '1<2', '2<3']);
|
|
|
|
expect(step1Log).toEqual(['1', '1<wrap0#0', 'wrap0#0<2', '2<3']);
|
|
|
|
expect(resultIdLog(result)).toEqual(['1', 'wrap0#0', '2', '3']);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should allow to add a parent by multiple processors to the same element', () => {
|
2015-05-26 12:25:39 -04:00
|
|
|
var element =
|
|
|
|
el('<div id="1"><span wrap0="1" wrap1="1" id="2"><b id="3"></b></span></div>');
|
2015-03-23 17:10:55 -04:00
|
|
|
var step0Log = [];
|
|
|
|
var step1Log = [];
|
|
|
|
var step2Log = [];
|
|
|
|
var pipeline = new CompilePipeline([
|
|
|
|
createWrapperStep('wrap0', step0Log),
|
|
|
|
createWrapperStep('wrap1', step1Log),
|
|
|
|
createLoggerStep(step2Log)
|
|
|
|
]);
|
2015-07-24 18:28:44 -04:00
|
|
|
var result = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition());
|
2015-03-23 17:10:55 -04:00
|
|
|
expect(step0Log).toEqual(['1', '1<2', '2<3']);
|
|
|
|
expect(step1Log).toEqual(['1', '1<wrap0#0', 'wrap0#0<2', '2<3']);
|
|
|
|
expect(step2Log).toEqual(['1', '1<wrap0#0', 'wrap0#0<wrap1#0', 'wrap1#0<2', '2<3']);
|
|
|
|
expect(resultIdLog(result)).toEqual(['1', 'wrap0#0', 'wrap1#0', '2', '3']);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should allow to add a parent by multiple processors to different elements', () => {
|
2015-05-26 12:25:39 -04:00
|
|
|
var element =
|
|
|
|
el('<div id="1"><span wrap0="1" id="2"><b id="3" wrap1="1"></b></span></div>');
|
2015-03-23 17:10:55 -04:00
|
|
|
var step0Log = [];
|
|
|
|
var step1Log = [];
|
|
|
|
var step2Log = [];
|
|
|
|
var pipeline = new CompilePipeline([
|
|
|
|
createWrapperStep('wrap0', step0Log),
|
|
|
|
createWrapperStep('wrap1', step1Log),
|
|
|
|
createLoggerStep(step2Log)
|
|
|
|
]);
|
2015-07-24 18:28:44 -04:00
|
|
|
var result = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition());
|
2015-03-23 17:10:55 -04:00
|
|
|
expect(step0Log).toEqual(['1', '1<2', '2<3']);
|
|
|
|
expect(step1Log).toEqual(['1', '1<wrap0#0', 'wrap0#0<2', '2<3']);
|
|
|
|
expect(step2Log).toEqual(['1', '1<wrap0#0', 'wrap0#0<2', '2<wrap1#0', 'wrap1#0<3']);
|
|
|
|
expect(resultIdLog(result)).toEqual(['1', 'wrap0#0', '2', 'wrap1#0', '3']);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should allow to add multiple parents by the same processor', () => {
|
|
|
|
var element = el('<div id="1"><span wrap0="2" id="2"><b id="3"></b></span></div>');
|
|
|
|
var step0Log = [];
|
|
|
|
var step1Log = [];
|
2015-06-03 16:42:57 -04:00
|
|
|
var pipeline =
|
|
|
|
new CompilePipeline([createWrapperStep('wrap0', step0Log), createLoggerStep(step1Log)]);
|
2015-07-24 18:28:44 -04:00
|
|
|
var result = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition());
|
2015-03-23 17:10:55 -04:00
|
|
|
expect(step0Log).toEqual(['1', '1<2', '2<3']);
|
|
|
|
expect(step1Log).toEqual(['1', '1<wrap0#0', 'wrap0#0<wrap0#1', 'wrap0#1<2', '2<3']);
|
|
|
|
expect(resultIdLog(result)).toEqual(['1', 'wrap0#0', 'wrap0#1', '2', '3']);
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('control.addChild', () => {
|
|
|
|
it('should report the new child to all processors and the result', () => {
|
|
|
|
var element = el('<div id="1"><div id="2"></div></div>');
|
|
|
|
var resultLog = [];
|
|
|
|
var newChild = new CompileElement(el('<div id="3"></div>'));
|
|
|
|
var pipeline = new CompilePipeline([
|
2015-06-03 16:42:57 -04:00
|
|
|
new MockStep((parent, current, control) => {
|
|
|
|
if (StringWrapper.equals(DOM.getAttribute(current.element, 'id'), '1')) {
|
|
|
|
control.addChild(newChild);
|
|
|
|
}
|
|
|
|
}),
|
2015-03-23 17:10:55 -04:00
|
|
|
createLoggerStep(resultLog)
|
|
|
|
]);
|
2015-07-24 18:28:44 -04:00
|
|
|
var result = pipeline.processElements(element, ViewType.COMPONENT, createViewDefinition());
|
2015-03-23 17:10:55 -04:00
|
|
|
expect(result[2]).toBe(newChild);
|
|
|
|
expect(resultLog).toEqual(['1', '1<2', '1<3']);
|
|
|
|
expect(resultIdLog(result)).toEqual(['1', '2', '3']);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-07-24 18:28:44 -04:00
|
|
|
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);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-03-23 17:10:55 -04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-07-24 18:28:44 -04:00
|
|
|
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;
|
|
|
|
}
|
2015-03-23 17:10:55 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-26 12:25:39 -04:00
|
|
|
export class IgnoreChildrenStep implements CompileStep {
|
2015-07-24 18:28:44 -04:00
|
|
|
processElement(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
2015-03-23 17:10:55 -04:00
|
|
|
var attributeMap = DOM.attributeMap(current.element);
|
2015-06-18 00:42:56 -04:00
|
|
|
if (attributeMap.has('ignore-children')) {
|
2015-03-23 17:10:55 -04:00
|
|
|
current.compileChildren = false;
|
|
|
|
}
|
|
|
|
}
|
2015-07-24 18:28:44 -04:00
|
|
|
processStyle(style: string): string { return style; }
|
2015-03-23 17:10:55 -04:00
|
|
|
}
|
|
|
|
|
2015-05-26 12:25:39 -04:00
|
|
|
class IgnoreCurrentElementStep implements CompileStep {
|
2015-07-24 18:28:44 -04:00
|
|
|
processElement(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
2015-04-10 10:12:37 -04:00
|
|
|
var attributeMap = DOM.attributeMap(current.element);
|
2015-06-18 00:42:56 -04:00
|
|
|
if (attributeMap.has('ignore-current')) {
|
2015-04-10 10:12:37 -04:00
|
|
|
control.ignoreCurrentElement();
|
|
|
|
}
|
|
|
|
}
|
2015-07-24 18:28:44 -04:00
|
|
|
processStyle(style: string): string { return style; }
|
2015-04-10 10:12:37 -04:00
|
|
|
}
|
|
|
|
|
2015-06-17 14:17:21 -04:00
|
|
|
function logEntry(log: string[], parent, current) {
|
2015-03-23 17:10:55 -04:00
|
|
|
var parentId = '';
|
|
|
|
if (isPresent(parent)) {
|
|
|
|
parentId = DOM.getAttribute(parent.element, 'id') + '<';
|
|
|
|
}
|
2015-06-17 14:17:21 -04:00
|
|
|
log.push(parentId + DOM.getAttribute(current.element, 'id'));
|
2015-03-23 17:10:55 -04:00
|
|
|
}
|
|
|
|
|
2015-06-17 14:17:21 -04:00
|
|
|
function createLoggerStep(log: string[]) {
|
2015-05-26 12:25:39 -04:00
|
|
|
return new MockStep((parent, current, control) => { logEntry(log, parent, current); });
|
2015-03-23 17:10:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
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(`<a id="${wrapperId}#${nextElementId++}"></a>`)));
|
|
|
|
parentCount--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
logEntry(log, parent, current);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function resultIdLog(result) {
|
|
|
|
var idLog = [];
|
2015-05-26 12:25:39 -04:00
|
|
|
ListWrapper.forEach(result, (current) => { logEntry(idLog, null, current); });
|
2015-03-23 17:10:55 -04:00
|
|
|
return idLog;
|
2015-04-10 10:12:37 -04:00
|
|
|
}
|