2015-03-23 17:10:55 -04:00
|
|
|
import {describe, beforeEach, it, xit, expect, iit, ddescribe, el} from 'angular2/test_lib';
|
|
|
|
import {isPresent, assertionsEnabled} from 'angular2/src/facade/lang';
|
|
|
|
import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
|
|
|
import {DirectiveParser} from 'angular2/src/render/dom/compiler/directive_parser';
|
|
|
|
import {CompilePipeline} from 'angular2/src/render/dom/compiler/compile_pipeline';
|
|
|
|
import {CompileStep} from 'angular2/src/render/dom/compiler/compile_step';
|
|
|
|
import {CompileElement} from 'angular2/src/render/dom/compiler/compile_element';
|
|
|
|
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
|
2015-04-09 15:20:11 -04:00
|
|
|
import {ViewDefinition, DirectiveMetadata} from 'angular2/src/render/api';
|
2015-03-23 17:10:55 -04:00
|
|
|
import {Lexer, Parser} from 'angular2/change_detection';
|
|
|
|
|
|
|
|
export function main() {
|
|
|
|
describe('DirectiveParser', () => {
|
|
|
|
var parser, annotatedDirectives;
|
|
|
|
|
|
|
|
beforeEach( () => {
|
|
|
|
annotatedDirectives = [
|
|
|
|
someComponent,
|
|
|
|
someComponent2,
|
2015-03-19 18:38:48 -04:00
|
|
|
someComponent3,
|
2015-03-23 17:10:55 -04:00
|
|
|
someViewport,
|
|
|
|
someViewport2,
|
|
|
|
someDecorator,
|
|
|
|
someDecoratorIgnoringChildren,
|
|
|
|
someDecoratorWithProps,
|
2015-04-21 14:47:53 -04:00
|
|
|
someDecoratorWithHostProperties,
|
2015-04-02 09:56:58 -04:00
|
|
|
someDecoratorWithEvents,
|
|
|
|
someDecoratorWithGlobalEvents
|
2015-03-23 17:10:55 -04:00
|
|
|
];
|
|
|
|
parser = new Parser(new Lexer());
|
|
|
|
});
|
|
|
|
|
|
|
|
function createPipeline(propertyBindings = null) {
|
|
|
|
return new CompilePipeline([
|
|
|
|
new MockStep( (parent, current, control) => {
|
|
|
|
if (isPresent(propertyBindings)) {
|
|
|
|
StringMapWrapper.forEach(propertyBindings, (ast, name) => {
|
|
|
|
current.bindElement().bindProperty(name, ast);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
new DirectiveParser(parser, annotatedDirectives)
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
function process(el, propertyBindings = null) {
|
|
|
|
var pipeline = createPipeline(propertyBindings);
|
|
|
|
return ListWrapper.map(pipeline.process(el), (ce) => ce.inheritedElementBinder );
|
|
|
|
}
|
|
|
|
|
|
|
|
it('should not add directives if they are not used', () => {
|
|
|
|
var results = process(el('<div></div>'));
|
|
|
|
expect(results[0]).toBe(null);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should detect directives in attributes', () => {
|
|
|
|
var results = process(el('<div some-decor></div>'));
|
|
|
|
expect(results[0].directives[0].directiveIndex).toBe(
|
|
|
|
annotatedDirectives.indexOf(someDecorator)
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2015-03-19 18:38:48 -04:00
|
|
|
it('should detect directives with multiple attributes', () => {
|
|
|
|
var results = process(el('<input type=text control=one></input>'));
|
|
|
|
expect(results[0].directives[0].directiveIndex).toBe(
|
|
|
|
annotatedDirectives.indexOf(someComponent3)
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2015-03-23 17:10:55 -04:00
|
|
|
it('should compile children by default', () => {
|
|
|
|
var results = createPipeline().process(el('<div some-decor></div>'));
|
|
|
|
expect(results[0].compileChildren).toEqual(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should stop compiling children when specified in the directive config', () => {
|
|
|
|
var results = createPipeline().process(el('<div some-decor-ignoring-children></div>'));
|
|
|
|
expect(results[0].compileChildren).toEqual(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should bind directive properties from bound properties', () => {
|
|
|
|
var results = process(
|
|
|
|
el('<div some-decor-props></div>'),
|
|
|
|
{
|
|
|
|
'elProp': parser.parseBinding('someExpr', '')
|
|
|
|
}
|
|
|
|
);
|
|
|
|
var directiveBinding = results[0].directives[0];
|
|
|
|
expect(MapWrapper.get(directiveBinding.propertyBindings, 'dirProp').source)
|
|
|
|
.toEqual('someExpr');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should bind directive properties with pipes', () => {
|
|
|
|
var results = process(
|
|
|
|
el('<div some-decor-props></div>'),
|
|
|
|
{
|
|
|
|
'elProp': parser.parseBinding('someExpr', '')
|
|
|
|
}
|
|
|
|
);
|
|
|
|
var directiveBinding = results[0].directives[0];
|
|
|
|
var pipedProp = MapWrapper.get(directiveBinding.propertyBindings, 'doubleProp');
|
|
|
|
var simpleProp = MapWrapper.get(directiveBinding.propertyBindings, 'dirProp');
|
|
|
|
expect(pipedProp.ast.name).toEqual('double');
|
|
|
|
expect(pipedProp.ast.exp).toEqual(simpleProp.ast);
|
|
|
|
expect(simpleProp.source).toEqual('someExpr');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should bind directive properties from attribute values', () => {
|
|
|
|
var results = process(
|
|
|
|
el('<div some-decor-props el-prop="someValue"></div>')
|
|
|
|
);
|
|
|
|
var directiveBinding = results[0].directives[0];
|
|
|
|
var simpleProp = MapWrapper.get(directiveBinding.propertyBindings, 'dirProp');
|
|
|
|
expect(simpleProp.source).toEqual('someValue');
|
|
|
|
});
|
|
|
|
|
2015-04-21 14:47:53 -04:00
|
|
|
it('should bind host directive properties', () => {
|
|
|
|
var element = el('<input some-decor-with-host-props>');
|
2015-03-23 17:10:55 -04:00
|
|
|
var results = process(element);
|
2015-04-21 14:47:53 -04:00
|
|
|
|
|
|
|
var directiveBinding = results[0].directives[0];
|
|
|
|
|
|
|
|
var ast = MapWrapper.get(directiveBinding.hostPropertyBindings, 'hostProperty');
|
|
|
|
expect(ast.source).toEqual('dirProp');
|
2015-03-23 17:10:55 -04:00
|
|
|
});
|
|
|
|
|
2015-04-02 17:40:49 -04:00
|
|
|
it('should read attribute values', () => {
|
|
|
|
var element = el('<input some-decor-props some-attr="someValue">');
|
|
|
|
var results = process(element);
|
|
|
|
expect(MapWrapper.get(results[0].readAttributes, 'some-attr')).toEqual('someValue');
|
|
|
|
});
|
|
|
|
|
2015-03-23 17:10:55 -04:00
|
|
|
it('should bind directive events', () => {
|
|
|
|
var results = process(
|
|
|
|
el('<div some-decor-events></div>')
|
|
|
|
);
|
|
|
|
var directiveBinding = results[0].directives[0];
|
2015-04-02 09:56:58 -04:00
|
|
|
expect(directiveBinding.eventBindings.length).toEqual(1);
|
|
|
|
var eventBinding = directiveBinding.eventBindings[0];
|
|
|
|
expect(eventBinding.fullName).toEqual('click');
|
|
|
|
expect(eventBinding.source.source).toEqual('doIt()');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should bind directive global events', () => {
|
|
|
|
var results = process(
|
|
|
|
el('<div some-decor-globalevents></div>')
|
|
|
|
);
|
|
|
|
var directiveBinding = results[0].directives[0];
|
|
|
|
expect(directiveBinding.eventBindings.length).toEqual(1);
|
|
|
|
var eventBinding = directiveBinding.eventBindings[0];
|
|
|
|
expect(eventBinding.fullName).toEqual('window:resize');
|
|
|
|
expect(eventBinding.source.source).toEqual('doItGlobal()');
|
2015-03-23 17:10:55 -04:00
|
|
|
});
|
|
|
|
|
2015-04-14 05:31:35 -04:00
|
|
|
//TODO: assertions should be enabled when running tests: https://github.com/angular/angular/issues/1340
|
2015-03-23 17:10:55 -04:00
|
|
|
describe('viewport directives', () => {
|
|
|
|
it('should not allow multiple viewport directives on the same element', () => {
|
|
|
|
expect( () => {
|
|
|
|
process(
|
|
|
|
el('<template some-vp some-vp2></template>')
|
|
|
|
);
|
2015-04-14 05:31:35 -04:00
|
|
|
}).toThrowError('Only one viewport directive is allowed per element - check '
|
|
|
|
+ (assertionsEnabled() ? '<template some-vp some-vp2>' : 'null'));
|
2015-03-23 17:10:55 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should not allow viewport directives on non <template> elements', () => {
|
|
|
|
expect( () => {
|
|
|
|
process(
|
|
|
|
el('<div some-vp></div>')
|
|
|
|
);
|
2015-04-14 05:31:35 -04:00
|
|
|
}).toThrowError('Viewport directives need to be placed on <template> elements or elements with template attribute - check '
|
|
|
|
+ (assertionsEnabled() ? '<div some-vp>' : 'null'));
|
2015-03-23 17:10:55 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-04-14 05:31:35 -04:00
|
|
|
//TODO: assertions should be enabled when running tests: https://github.com/angular/angular/issues/1340
|
2015-03-23 17:10:55 -04:00
|
|
|
describe('component directives', () => {
|
|
|
|
it('should save the component id', () => {
|
|
|
|
var results = process(
|
|
|
|
el('<div some-comp></div>')
|
|
|
|
);
|
|
|
|
expect(results[0].componentId).toEqual('someComponent');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not allow multiple component directives on the same element', () => {
|
|
|
|
expect( () => {
|
|
|
|
process(
|
|
|
|
el('<div some-comp some-comp2></div>')
|
|
|
|
);
|
2015-04-14 05:31:35 -04:00
|
|
|
}).toThrowError('Only one component directive is allowed per element - check '
|
|
|
|
+ (assertionsEnabled() ? '<div some-comp some-comp2>' : 'null'));
|
2015-03-23 17:10:55 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should not allow component directives on <template> elements', () => {
|
|
|
|
expect( () => {
|
|
|
|
process(
|
|
|
|
el('<template some-comp></template>')
|
|
|
|
);
|
2015-04-14 05:31:35 -04:00
|
|
|
}).toThrowError('Only template directives are allowed on template elements - check '
|
|
|
|
+ (assertionsEnabled() ? '<template some-comp>' : 'null'));
|
2015-03-23 17:10:55 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
class MockStep extends CompileStep {
|
|
|
|
processClosure:Function;
|
|
|
|
constructor(process) {
|
|
|
|
super();
|
|
|
|
this.processClosure = process;
|
|
|
|
}
|
|
|
|
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
|
|
|
this.processClosure(parent, current, control);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var someComponent = new DirectiveMetadata({
|
|
|
|
selector: '[some-comp]',
|
|
|
|
id: 'someComponent',
|
|
|
|
type: DirectiveMetadata.COMPONENT_TYPE
|
|
|
|
});
|
|
|
|
|
|
|
|
var someComponent2 = new DirectiveMetadata({
|
|
|
|
selector: '[some-comp2]',
|
|
|
|
id: 'someComponent2',
|
|
|
|
type: DirectiveMetadata.COMPONENT_TYPE
|
|
|
|
});
|
|
|
|
|
2015-03-19 18:38:48 -04:00
|
|
|
var someComponent3 = new DirectiveMetadata({
|
|
|
|
selector: 'input[type=text][control]',
|
|
|
|
id: 'someComponent3',
|
|
|
|
type: DirectiveMetadata.COMPONENT_TYPE
|
|
|
|
});
|
|
|
|
|
2015-03-23 17:10:55 -04:00
|
|
|
var someViewport = new DirectiveMetadata({
|
|
|
|
selector: '[some-vp]',
|
|
|
|
id: 'someViewport',
|
|
|
|
type: DirectiveMetadata.VIEWPORT_TYPE
|
|
|
|
});
|
|
|
|
|
|
|
|
var someViewport2 = new DirectiveMetadata({
|
|
|
|
selector: '[some-vp2]',
|
|
|
|
id: 'someViewport2',
|
|
|
|
type: DirectiveMetadata.VIEWPORT_TYPE
|
|
|
|
});
|
|
|
|
|
|
|
|
var someDecorator = new DirectiveMetadata({
|
|
|
|
selector: '[some-decor]'
|
|
|
|
});
|
|
|
|
|
|
|
|
var someDecoratorIgnoringChildren = new DirectiveMetadata({
|
|
|
|
selector: '[some-decor-ignoring-children]',
|
|
|
|
compileChildren: false
|
|
|
|
});
|
|
|
|
|
|
|
|
var someDecoratorWithProps = new DirectiveMetadata({
|
|
|
|
selector: '[some-decor-props]',
|
2015-04-09 15:20:11 -04:00
|
|
|
properties: MapWrapper.createFromStringMap({
|
2015-03-23 17:10:55 -04:00
|
|
|
'dirProp': 'elProp',
|
|
|
|
'doubleProp': 'elProp | double'
|
|
|
|
}),
|
2015-04-02 17:40:49 -04:00
|
|
|
readAttributes: ['some-attr']
|
2015-03-23 17:10:55 -04:00
|
|
|
});
|
|
|
|
|
2015-04-21 14:47:53 -04:00
|
|
|
var someDecoratorWithHostProperties = new DirectiveMetadata({
|
|
|
|
selector: '[some-decor-with-host-props]',
|
|
|
|
hostProperties: MapWrapper.createFromStringMap({
|
|
|
|
'dirProp': 'hostProperty'
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
2015-03-23 17:10:55 -04:00
|
|
|
var someDecoratorWithEvents = new DirectiveMetadata({
|
|
|
|
selector: '[some-decor-events]',
|
2015-04-09 15:20:11 -04:00
|
|
|
hostListeners: MapWrapper.createFromStringMap({
|
2015-03-23 17:10:55 -04:00
|
|
|
'click': 'doIt()'
|
|
|
|
})
|
|
|
|
});
|
2015-04-02 09:56:58 -04:00
|
|
|
|
|
|
|
var someDecoratorWithGlobalEvents = new DirectiveMetadata({
|
|
|
|
selector: '[some-decor-globalevents]',
|
|
|
|
hostListeners: MapWrapper.createFromStringMap({
|
|
|
|
'window:resize': 'doItGlobal()'
|
|
|
|
})
|
|
|
|
});
|