refactor(render): ts’ify tests
This commit is contained in:
parent
d773b6a00a
commit
1dc8ba6920
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Runs compiler tests using in-browser DOM adapter.
|
* Runs compiler tests using in-browser DOM adapter.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {runCompilerCommonTests} from './compiler_common_tests';
|
import {runCompilerCommonTests} from './compiler_common_tests';
|
||||||
|
|
|
@ -1,229 +0,0 @@
|
||||||
import {
|
|
||||||
AsyncTestCompleter,
|
|
||||||
beforeEach,
|
|
||||||
ddescribe,
|
|
||||||
describe,
|
|
||||||
el,
|
|
||||||
expect,
|
|
||||||
iit,
|
|
||||||
inject,
|
|
||||||
IS_DARTIUM,
|
|
||||||
it,
|
|
||||||
} from 'angular2/test_lib';
|
|
||||||
|
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
|
||||||
import {List, ListWrapper, Map, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
|
||||||
import {Type, isBlank, stringify, isPresent} from 'angular2/src/facade/lang';
|
|
||||||
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
|
||||||
|
|
||||||
import {DomCompiler} from 'angular2/src/render/dom/compiler/compiler';
|
|
||||||
import {ProtoViewDto, ViewDefinition, DirectiveMetadata} from 'angular2/src/render/api';
|
|
||||||
import {CompileElement} from 'angular2/src/render/dom/compiler/compile_element';
|
|
||||||
import {CompileStep} from 'angular2/src/render/dom/compiler/compile_step'
|
|
||||||
import {CompileStepFactory} from 'angular2/src/render/dom/compiler/compile_step_factory';
|
|
||||||
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
|
|
||||||
import {TemplateLoader} from 'angular2/src/render/dom/compiler/template_loader';
|
|
||||||
|
|
||||||
import {UrlResolver} from 'angular2/src/services/url_resolver';
|
|
||||||
|
|
||||||
import {resolveInternalDomProtoView} from 'angular2/src/render/dom/view/proto_view';
|
|
||||||
|
|
||||||
export function runCompilerCommonTests() {
|
|
||||||
describe('DomCompiler', function() {
|
|
||||||
var mockStepFactory;
|
|
||||||
|
|
||||||
function createCompiler(processClosure, urlData = null) {
|
|
||||||
if (isBlank(urlData)) {
|
|
||||||
urlData = MapWrapper.create();
|
|
||||||
}
|
|
||||||
var tplLoader = new FakeTemplateLoader(urlData);
|
|
||||||
mockStepFactory = new MockStepFactory([new MockStep(processClosure)]);
|
|
||||||
return new DomCompiler(mockStepFactory, tplLoader);
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('compile', () => {
|
|
||||||
|
|
||||||
it('should run the steps and build the AppProtoView of the root element', inject([AsyncTestCompleter], (async) => {
|
|
||||||
var compiler = createCompiler((parent, current, control) => {
|
|
||||||
current.inheritedProtoView.bindVariable('b', 'a');
|
|
||||||
});
|
|
||||||
compiler.compile(new ViewDefinition({
|
|
||||||
componentId: 'someComponent',
|
|
||||||
template: '<div></div>'
|
|
||||||
})).then( (protoView) => {
|
|
||||||
expect(protoView.variableBindings).toEqual(MapWrapper.createFromStringMap({
|
|
||||||
'a': 'b'
|
|
||||||
}));
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should run the steps and build the proto view', inject([AsyncTestCompleter], (async) => {
|
|
||||||
var compiler = createCompiler((parent, current, control) => {
|
|
||||||
current.inheritedProtoView.bindVariable('b', 'a');
|
|
||||||
});
|
|
||||||
|
|
||||||
var dirMetadata = new DirectiveMetadata({id: 'id', selector: 'CUSTOM', type: DirectiveMetadata.COMPONENT_TYPE});
|
|
||||||
compiler.compileHost(dirMetadata).then( (protoView) => {
|
|
||||||
expect(DOM.tagName(resolveInternalDomProtoView(protoView.render).element)).toEqual('CUSTOM')
|
|
||||||
expect(mockStepFactory.viewDef.directives).toEqual([dirMetadata]);
|
|
||||||
expect(protoView.variableBindings).toEqual(MapWrapper.createFromStringMap({
|
|
||||||
'a': 'b'
|
|
||||||
}));
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should use the inline template and compile in sync', inject([AsyncTestCompleter], (async) => {
|
|
||||||
var compiler = createCompiler(EMPTY_STEP);
|
|
||||||
compiler.compile(new ViewDefinition({
|
|
||||||
componentId: 'someId',
|
|
||||||
template: 'inline component'
|
|
||||||
})).then( (protoView) => {
|
|
||||||
expect(DOM.getInnerHTML(resolveInternalDomProtoView(protoView.render).element)).toEqual('inline component');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should load url templates', inject([AsyncTestCompleter], (async) => {
|
|
||||||
var urlData = MapWrapper.createFromStringMap({
|
|
||||||
'someUrl': 'url component'
|
|
||||||
});
|
|
||||||
var compiler = createCompiler(EMPTY_STEP, urlData);
|
|
||||||
compiler.compile(new ViewDefinition({
|
|
||||||
componentId: 'someId',
|
|
||||||
absUrl: 'someUrl'
|
|
||||||
})).then( (protoView) => {
|
|
||||||
expect(DOM.getInnerHTML(resolveInternalDomProtoView(protoView.render).element)).toEqual('url component');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should report loading errors', inject([AsyncTestCompleter], (async) => {
|
|
||||||
var compiler = createCompiler(EMPTY_STEP, MapWrapper.create());
|
|
||||||
PromiseWrapper.catchError(compiler.compile(new ViewDefinition({
|
|
||||||
componentId: 'someId',
|
|
||||||
absUrl: 'someUrl'
|
|
||||||
})), (e) => {
|
|
||||||
expect(e.message).toContain(`Failed to load the template "someId"`);
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should wait for async subtasks to be resolved', inject([AsyncTestCompleter], (async) => {
|
|
||||||
var subTasksCompleted = false;
|
|
||||||
|
|
||||||
var completer = PromiseWrapper.completer();
|
|
||||||
|
|
||||||
var compiler = createCompiler( (parent, current, control) => {
|
|
||||||
ListWrapper.push(mockStepFactory.subTaskPromises, completer.promise.then((_) => {
|
|
||||||
subTasksCompleted = true;
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
// It should always return a Promise because the subtask is async
|
|
||||||
var pvPromise = compiler.compile(new ViewDefinition({
|
|
||||||
componentId: 'someId',
|
|
||||||
template: 'some component'
|
|
||||||
}));
|
|
||||||
expect(pvPromise).toBePromise();
|
|
||||||
expect(subTasksCompleted).toEqual(false);
|
|
||||||
|
|
||||||
// The Promise should resolve after the subtask is ready
|
|
||||||
completer.resolve(null);
|
|
||||||
pvPromise.then((protoView) => {
|
|
||||||
expect(subTasksCompleted).toEqual(true);
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should return ProtoViews of type COMPONENT_VIEW_TYPE', inject([AsyncTestCompleter], (async) => {
|
|
||||||
var compiler = createCompiler(EMPTY_STEP);
|
|
||||||
compiler.compile(new ViewDefinition({
|
|
||||||
componentId: 'someId',
|
|
||||||
template: 'inline component'
|
|
||||||
})).then( (protoView) => {
|
|
||||||
expect(protoView.type).toEqual(ProtoViewDto.COMPONENT_VIEW_TYPE);
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('compileHost', () => {
|
|
||||||
|
|
||||||
it('should return ProtoViews of type HOST_VIEW_TYPE', inject([AsyncTestCompleter], (async) => {
|
|
||||||
var compiler = createCompiler(EMPTY_STEP);
|
|
||||||
compiler.compileHost(someComponent).then( (protoView) => {
|
|
||||||
expect(protoView.type).toEqual(ProtoViewDto.HOST_VIEW_TYPE);
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class MockStepFactory extends CompileStepFactory {
|
|
||||||
steps:List<CompileStep>;
|
|
||||||
subTaskPromises:List<Promise>;
|
|
||||||
viewDef:ViewDefinition;
|
|
||||||
|
|
||||||
constructor(steps) {
|
|
||||||
super();
|
|
||||||
this.steps = steps;
|
|
||||||
}
|
|
||||||
createSteps(viewDef, subTaskPromises) {
|
|
||||||
this.viewDef = viewDef;
|
|
||||||
this.subTaskPromises = subTaskPromises;
|
|
||||||
ListWrapper.forEach(this.subTaskPromises, (p) => ListWrapper.push(subTaskPromises, p) );
|
|
||||||
return this.steps;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MockStep /*implements CompileStep*/ {
|
|
||||||
processClosure:Function;
|
|
||||||
constructor(process) {
|
|
||||||
this.processClosure = process;
|
|
||||||
}
|
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
|
||||||
this.processClosure(parent, current, control);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var EMPTY_STEP = (parent, current, control) => {
|
|
||||||
if (isPresent(parent)) {
|
|
||||||
current.inheritedProtoView = parent.inheritedProtoView;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class FakeTemplateLoader extends TemplateLoader {
|
|
||||||
_urlData: Map<string, string>;
|
|
||||||
constructor(urlData) {
|
|
||||||
super(null, new UrlResolver());
|
|
||||||
this._urlData = urlData;
|
|
||||||
}
|
|
||||||
|
|
||||||
load(template: ViewDefinition) {
|
|
||||||
if (isPresent(template.template)) {
|
|
||||||
return PromiseWrapper.resolve(DOM.createTemplate(template.template));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isPresent(template.absUrl)) {
|
|
||||||
var content = MapWrapper.get(this._urlData, template.absUrl);
|
|
||||||
if (isPresent(content)) {
|
|
||||||
return PromiseWrapper.resolve(DOM.createTemplate(content));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return PromiseWrapper.reject('Load failed', null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var someComponent = new DirectiveMetadata({
|
|
||||||
selector: 'some-comp',
|
|
||||||
id: 'someComponent',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
|
@ -0,0 +1,221 @@
|
||||||
|
import {
|
||||||
|
AsyncTestCompleter,
|
||||||
|
beforeEach,
|
||||||
|
ddescribe,
|
||||||
|
describe,
|
||||||
|
el,
|
||||||
|
expect,
|
||||||
|
iit,
|
||||||
|
inject,
|
||||||
|
IS_DARTIUM,
|
||||||
|
it,
|
||||||
|
} from 'angular2/test_lib';
|
||||||
|
|
||||||
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
|
import {List, ListWrapper, Map, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
|
import {Type, isBlank, stringify, isPresent} from 'angular2/src/facade/lang';
|
||||||
|
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
|
import {DomCompiler} from 'angular2/src/render/dom/compiler/compiler';
|
||||||
|
import {ProtoViewDto, ViewDefinition, DirectiveMetadata} from 'angular2/src/render/api';
|
||||||
|
import {CompileElement} from 'angular2/src/render/dom/compiler/compile_element';
|
||||||
|
import {CompileStep} from 'angular2/src/render/dom/compiler/compile_step';
|
||||||
|
import {CompileStepFactory} from 'angular2/src/render/dom/compiler/compile_step_factory';
|
||||||
|
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
|
||||||
|
import {TemplateLoader} from 'angular2/src/render/dom/compiler/template_loader';
|
||||||
|
|
||||||
|
import {UrlResolver} from 'angular2/src/services/url_resolver';
|
||||||
|
|
||||||
|
import {resolveInternalDomProtoView} from 'angular2/src/render/dom/view/proto_view';
|
||||||
|
|
||||||
|
export function runCompilerCommonTests() {
|
||||||
|
describe('DomCompiler', function() {
|
||||||
|
var mockStepFactory;
|
||||||
|
|
||||||
|
function createCompiler(processClosure, urlData = null) {
|
||||||
|
if (isBlank(urlData)) {
|
||||||
|
urlData = MapWrapper.create();
|
||||||
|
}
|
||||||
|
var tplLoader = new FakeTemplateLoader(urlData);
|
||||||
|
mockStepFactory = new MockStepFactory([new MockStep(processClosure)]);
|
||||||
|
return new DomCompiler(mockStepFactory, tplLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('compile', () => {
|
||||||
|
|
||||||
|
it('should run the steps and build the AppProtoView of the root element',
|
||||||
|
inject([AsyncTestCompleter], (async) => {
|
||||||
|
var compiler = createCompiler((parent, current, control) => {
|
||||||
|
current.inheritedProtoView.bindVariable('b', 'a');
|
||||||
|
});
|
||||||
|
compiler.compile(
|
||||||
|
new ViewDefinition({componentId: 'someComponent', template: '<div></div>'}))
|
||||||
|
.then((protoView) => {
|
||||||
|
expect(protoView.variableBindings)
|
||||||
|
.toEqual(MapWrapper.createFromStringMap({'a': 'b'}));
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should run the steps and build the proto view', inject([AsyncTestCompleter], (async) => {
|
||||||
|
var compiler = createCompiler((parent, current, control) => {
|
||||||
|
current.inheritedProtoView.bindVariable('b', 'a');
|
||||||
|
});
|
||||||
|
|
||||||
|
var dirMetadata = new DirectiveMetadata(
|
||||||
|
{id: 'id', selector: 'CUSTOM', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||||
|
compiler.compileHost(dirMetadata)
|
||||||
|
.then((protoView) => {
|
||||||
|
expect(DOM.tagName(resolveInternalDomProtoView(protoView.render).element))
|
||||||
|
.toEqual('CUSTOM');
|
||||||
|
expect(mockStepFactory.viewDef.directives).toEqual([dirMetadata]);
|
||||||
|
expect(protoView.variableBindings)
|
||||||
|
.toEqual(MapWrapper.createFromStringMap({'a': 'b'}));
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should use the inline template and compile in sync',
|
||||||
|
inject([AsyncTestCompleter], (async) => {
|
||||||
|
var compiler = createCompiler(EMPTY_STEP);
|
||||||
|
compiler.compile(
|
||||||
|
new ViewDefinition({componentId: 'someId', template: 'inline component'}))
|
||||||
|
.then((protoView) => {
|
||||||
|
expect(DOM.getInnerHTML(resolveInternalDomProtoView(protoView.render).element))
|
||||||
|
.toEqual('inline component');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should load url templates', inject([AsyncTestCompleter], (async) => {
|
||||||
|
var urlData = MapWrapper.createFromStringMap({'someUrl': 'url component'});
|
||||||
|
var compiler = createCompiler(EMPTY_STEP, urlData);
|
||||||
|
compiler.compile(new ViewDefinition({componentId: 'someId', absUrl: 'someUrl'}))
|
||||||
|
.then((protoView) => {
|
||||||
|
expect(DOM.getInnerHTML(resolveInternalDomProtoView(protoView.render).element))
|
||||||
|
.toEqual('url component');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should report loading errors', inject([AsyncTestCompleter], (async) => {
|
||||||
|
var compiler = createCompiler(EMPTY_STEP, MapWrapper.create());
|
||||||
|
PromiseWrapper.catchError(
|
||||||
|
compiler.compile(new ViewDefinition({componentId: 'someId', absUrl: 'someUrl'})),
|
||||||
|
(e) => {
|
||||||
|
expect(e.message).toContain(`Failed to load the template "someId"`);
|
||||||
|
async.done();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should wait for async subtasks to be resolved', inject([AsyncTestCompleter], (async) => {
|
||||||
|
var subTasksCompleted = false;
|
||||||
|
|
||||||
|
var completer = PromiseWrapper.completer();
|
||||||
|
|
||||||
|
var compiler = createCompiler((parent, current, control) => {
|
||||||
|
ListWrapper.push(mockStepFactory.subTaskPromises,
|
||||||
|
completer.promise.then((_) => { subTasksCompleted = true; }));
|
||||||
|
});
|
||||||
|
|
||||||
|
// It should always return a Promise because the subtask is async
|
||||||
|
var pvPromise = compiler.compile(
|
||||||
|
new ViewDefinition({componentId: 'someId', template: 'some component'}));
|
||||||
|
expect(pvPromise).toBePromise();
|
||||||
|
expect(subTasksCompleted).toEqual(false);
|
||||||
|
|
||||||
|
// The Promise should resolve after the subtask is ready
|
||||||
|
completer.resolve(null);
|
||||||
|
pvPromise.then((protoView) => {
|
||||||
|
expect(subTasksCompleted).toEqual(true);
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should return ProtoViews of type COMPONENT_VIEW_TYPE',
|
||||||
|
inject([AsyncTestCompleter], (async) => {
|
||||||
|
var compiler = createCompiler(EMPTY_STEP);
|
||||||
|
compiler.compile(
|
||||||
|
new ViewDefinition({componentId: 'someId', template: 'inline component'}))
|
||||||
|
.then((protoView) => {
|
||||||
|
expect(protoView.type).toEqual(ProtoViewDto.COMPONENT_VIEW_TYPE);
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('compileHost', () => {
|
||||||
|
|
||||||
|
it('should return ProtoViews of type HOST_VIEW_TYPE',
|
||||||
|
inject([AsyncTestCompleter], (async) => {
|
||||||
|
var compiler = createCompiler(EMPTY_STEP);
|
||||||
|
compiler.compileHost(someComponent)
|
||||||
|
.then((protoView) => {
|
||||||
|
expect(protoView.type).toEqual(ProtoViewDto.HOST_VIEW_TYPE);
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockStepFactory extends CompileStepFactory {
|
||||||
|
steps: List<CompileStep>;
|
||||||
|
subTaskPromises: List<Promise<any>>;
|
||||||
|
viewDef: ViewDefinition;
|
||||||
|
|
||||||
|
constructor(steps) {
|
||||||
|
super();
|
||||||
|
this.steps = steps;
|
||||||
|
}
|
||||||
|
createSteps(viewDef, subTaskPromises) {
|
||||||
|
this.viewDef = viewDef;
|
||||||
|
this.subTaskPromises = subTaskPromises;
|
||||||
|
ListWrapper.forEach(this.subTaskPromises, (p) => ListWrapper.push(subTaskPromises, p));
|
||||||
|
return this.steps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockStep implements CompileStep {
|
||||||
|
processClosure: Function;
|
||||||
|
constructor(process) { this.processClosure = process; }
|
||||||
|
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||||
|
this.processClosure(parent, current, control);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var EMPTY_STEP = (parent, current, control) => {
|
||||||
|
if (isPresent(parent)) {
|
||||||
|
current.inheritedProtoView = parent.inheritedProtoView;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FakeTemplateLoader extends TemplateLoader {
|
||||||
|
_urlData: Map<string, string>;
|
||||||
|
constructor(urlData) {
|
||||||
|
super(null, new UrlResolver());
|
||||||
|
this._urlData = urlData;
|
||||||
|
}
|
||||||
|
|
||||||
|
load(template: ViewDefinition) {
|
||||||
|
if (isPresent(template.template)) {
|
||||||
|
return PromiseWrapper.resolve(DOM.createTemplate(template.template));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPresent(template.absUrl)) {
|
||||||
|
var content = MapWrapper.get(this._urlData, template.absUrl);
|
||||||
|
if (isPresent(content)) {
|
||||||
|
return PromiseWrapper.resolve(DOM.createTemplate(content));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PromiseWrapper.reject('Load failed', null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var someComponent = new DirectiveMetadata(
|
||||||
|
{selector: 'some-comp', id: 'someComponent', type: DirectiveMetadata.COMPONENT_TYPE});
|
|
@ -9,12 +9,13 @@ import {CompileElement} from 'angular2/src/render/dom/compiler/compile_element';
|
||||||
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
|
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
|
||||||
import {ViewDefinition, DirectiveMetadata} from 'angular2/src/render/api';
|
import {ViewDefinition, DirectiveMetadata} from 'angular2/src/render/api';
|
||||||
import {Lexer, Parser} from 'angular2/change_detection';
|
import {Lexer, Parser} from 'angular2/change_detection';
|
||||||
|
import {ElementBinderBuilder} from 'angular2/src/render/dom/view/proto_view_builder';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('DirectiveParser', () => {
|
describe('DirectiveParser', () => {
|
||||||
var parser, annotatedDirectives;
|
var parser, annotatedDirectives;
|
||||||
|
|
||||||
beforeEach( () => {
|
beforeEach(() => {
|
||||||
annotatedDirectives = [
|
annotatedDirectives = [
|
||||||
someComponent,
|
someComponent,
|
||||||
someComponent2,
|
someComponent2,
|
||||||
|
@ -35,20 +36,21 @@ export function main() {
|
||||||
if (isBlank(directives)) directives = annotatedDirectives;
|
if (isBlank(directives)) directives = annotatedDirectives;
|
||||||
|
|
||||||
return new CompilePipeline([
|
return new CompilePipeline([
|
||||||
new MockStep( (parent, current, control) => {
|
new MockStep((parent, current, control) =>
|
||||||
if (isPresent(propertyBindings)) {
|
{
|
||||||
StringMapWrapper.forEach(propertyBindings, (ast, name) => {
|
if (isPresent(propertyBindings)) {
|
||||||
current.bindElement().bindProperty(name, ast);
|
StringMapWrapper.forEach(propertyBindings, (ast, name) => {
|
||||||
});
|
current.bindElement().bindProperty(name, ast);
|
||||||
}
|
});
|
||||||
}),
|
}
|
||||||
|
}),
|
||||||
new DirectiveParser(parser, directives)
|
new DirectiveParser(parser, directives)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function process(el, propertyBindings = null, directives = null) {
|
function process(el, propertyBindings = null, directives = null): List<ElementBinderBuilder> {
|
||||||
var pipeline = createPipeline(propertyBindings, directives);
|
var pipeline = createPipeline(propertyBindings, directives);
|
||||||
return ListWrapper.map(pipeline.process(el), (ce) => ce.inheritedElementBinder );
|
return ListWrapper.map(pipeline.process(el), (ce) => ce.inheritedElementBinder);
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should not add directives if they are not used', () => {
|
it('should not add directives if they are not used', () => {
|
||||||
|
@ -58,16 +60,14 @@ export function main() {
|
||||||
|
|
||||||
it('should detect directives in attributes', () => {
|
it('should detect directives in attributes', () => {
|
||||||
var results = process(el('<div some-decor></div>'));
|
var results = process(el('<div some-decor></div>'));
|
||||||
expect(results[0].directives[0].directiveIndex).toBe(
|
expect(results[0].directives[0].directiveIndex)
|
||||||
annotatedDirectives.indexOf(someDirective)
|
.toBe(annotatedDirectives.indexOf(someDirective));
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should detect directives with multiple attributes', () => {
|
it('should detect directives with multiple attributes', () => {
|
||||||
var results = process(el('<input type=text control=one></input>'));
|
var results = process(el('<input type=text control=one></input>'));
|
||||||
expect(results[0].directives[0].directiveIndex).toBe(
|
expect(results[0].directives[0].directiveIndex)
|
||||||
annotatedDirectives.indexOf(decoratorWithMultipleAttrs)
|
.toBe(annotatedDirectives.indexOf(decoratorWithMultipleAttrs));
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should compile children by default', () => {
|
it('should compile children by default', () => {
|
||||||
|
@ -81,36 +81,26 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bind directive properties from bound properties', () => {
|
it('should bind directive properties from bound properties', () => {
|
||||||
var results = process(
|
var results = process(el('<div some-decor-props></div>'),
|
||||||
el('<div some-decor-props></div>'),
|
{'elProp': parser.parseBinding('someExpr', '')});
|
||||||
{
|
|
||||||
'elProp': parser.parseBinding('someExpr', '')
|
|
||||||
}
|
|
||||||
);
|
|
||||||
var directiveBinding = results[0].directives[0];
|
var directiveBinding = results[0].directives[0];
|
||||||
expect(MapWrapper.get(directiveBinding.propertyBindings, 'dirProp').source)
|
expect(MapWrapper.get(directiveBinding.propertyBindings, 'dirProp').source)
|
||||||
.toEqual('someExpr');
|
.toEqual('someExpr');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bind directive properties with pipes', () => {
|
it('should bind directive properties with pipes', () => {
|
||||||
var results = process(
|
var results = process(el('<div some-decor-props></div>'),
|
||||||
el('<div some-decor-props></div>'),
|
{'elProp': parser.parseBinding('someExpr', '')});
|
||||||
{
|
|
||||||
'elProp': parser.parseBinding('someExpr', '')
|
|
||||||
}
|
|
||||||
);
|
|
||||||
var directiveBinding = results[0].directives[0];
|
var directiveBinding = results[0].directives[0];
|
||||||
var pipedProp = MapWrapper.get(directiveBinding.propertyBindings, 'doubleProp');
|
var pipedProp = <any>MapWrapper.get(directiveBinding.propertyBindings, 'doubleProp');
|
||||||
var simpleProp = MapWrapper.get(directiveBinding.propertyBindings, 'dirProp');
|
var simpleProp = <any>MapWrapper.get(directiveBinding.propertyBindings, 'dirProp');
|
||||||
expect(pipedProp.ast.name).toEqual('double');
|
expect(pipedProp.ast.name).toEqual('double');
|
||||||
expect(pipedProp.ast.exp).toEqual(simpleProp.ast);
|
expect(pipedProp.ast.exp).toEqual(simpleProp.ast);
|
||||||
expect(simpleProp.source).toEqual('someExpr');
|
expect(simpleProp.source).toEqual('someExpr');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bind directive properties from attribute values', () => {
|
it('should bind directive properties from attribute values', () => {
|
||||||
var results = process(
|
var results = process(el('<div some-decor-props el-prop="someValue"></div>'));
|
||||||
el('<div some-decor-props el-prop="someValue"></div>')
|
|
||||||
);
|
|
||||||
var directiveBinding = results[0].directives[0];
|
var directiveBinding = results[0].directives[0];
|
||||||
var simpleProp = MapWrapper.get(directiveBinding.propertyBindings, 'dirProp');
|
var simpleProp = MapWrapper.get(directiveBinding.propertyBindings, 'dirProp');
|
||||||
expect(simpleProp.source).toEqual('someValue');
|
expect(simpleProp.source).toEqual('someValue');
|
||||||
|
@ -160,9 +150,7 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bind directive events', () => {
|
it('should bind directive events', () => {
|
||||||
var results = process(
|
var results = process(el('<div some-decor-events></div>'));
|
||||||
el('<div some-decor-events></div>')
|
|
||||||
);
|
|
||||||
var directiveBinding = results[0].directives[0];
|
var directiveBinding = results[0].directives[0];
|
||||||
expect(directiveBinding.eventBindings.length).toEqual(1);
|
expect(directiveBinding.eventBindings.length).toEqual(1);
|
||||||
var eventBinding = directiveBinding.eventBindings[0];
|
var eventBinding = directiveBinding.eventBindings[0];
|
||||||
|
@ -171,9 +159,7 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bind directive global events', () => {
|
it('should bind directive global events', () => {
|
||||||
var results = process(
|
var results = process(el('<div some-decor-globalevents></div>'));
|
||||||
el('<div some-decor-globalevents></div>')
|
|
||||||
);
|
|
||||||
var directiveBinding = results[0].directives[0];
|
var directiveBinding = results[0].directives[0];
|
||||||
expect(directiveBinding.eventBindings.length).toEqual(1);
|
expect(directiveBinding.eventBindings.length).toEqual(1);
|
||||||
var eventBinding = directiveBinding.eventBindings[0];
|
var eventBinding = directiveBinding.eventBindings[0];
|
||||||
|
@ -182,83 +168,61 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bind directive host actions', () => {
|
it('should bind directive host actions', () => {
|
||||||
var results = process(
|
var results = process(el('<div some-decor-host-actions></div>'));
|
||||||
el('<div some-decor-host-actions></div>')
|
|
||||||
);
|
|
||||||
var directiveBinding = results[0].directives[0];
|
var directiveBinding = results[0].directives[0];
|
||||||
expect(directiveBinding.hostActions[0].actionName).toEqual('focus');
|
expect(directiveBinding.hostActions[0].actionName).toEqual('focus');
|
||||||
});
|
});
|
||||||
|
|
||||||
//TODO: assertions should be enabled when running tests: https://github.com/angular/angular/issues/1340
|
// TODO: assertions should be enabled when running tests:
|
||||||
|
// https://github.com/angular/angular/issues/1340
|
||||||
describe('component directives', () => {
|
describe('component directives', () => {
|
||||||
it('should save the component id', () => {
|
it('should save the component id', () => {
|
||||||
var results = process(
|
var results = process(el('<some-comp></some-comp>'));
|
||||||
el('<some-comp></some-comp>')
|
|
||||||
);
|
|
||||||
expect(results[0].componentId).toEqual('someComponent');
|
expect(results[0].componentId).toEqual('someComponent');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when the provided selector is not an element selector', () => {
|
it('should throw when the provided selector is not an element selector', () => {
|
||||||
expect( () => {
|
expect(() => { createPipeline(null, [componentWithNonElementSelector]); })
|
||||||
createPipeline(null, [componentWithNonElementSelector]);
|
.toThrowError(
|
||||||
}).toThrowError(`Component 'componentWithNonElementSelector' can only have an element selector, but had '[attr]'`);
|
`Component 'componentWithNonElementSelector' can only have an element selector, but had '[attr]'`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not allow multiple component directives on the same element', () => {
|
it('should not allow multiple component directives on the same element', () => {
|
||||||
expect( () => {
|
expect(() => {
|
||||||
process(
|
process(el('<some-comp></some-comp>'), null, [someComponent, someComponentDup]);
|
||||||
el('<some-comp></some-comp>'),
|
}).toThrowError(new RegExp('Only one component directive is allowed per element'));
|
||||||
null,
|
|
||||||
[someComponent, someComponentDup]
|
|
||||||
);
|
|
||||||
}).toThrowError(new RegExp('Only one component directive is allowed per element' ));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should sort the directives and store the component as the first directive', () => {
|
it('should sort the directives and store the component as the first directive', () => {
|
||||||
var results = process(
|
var results = process(el('<some-comp some-decor></some-comp>'));
|
||||||
el('<some-comp some-decor></some-comp>')
|
expect(annotatedDirectives[results[0].directives[0].directiveIndex].id)
|
||||||
);
|
.toEqual('someComponent');
|
||||||
expect(annotatedDirectives[results[0].directives[0].directiveIndex].id).toEqual('someComponent');
|
expect(annotatedDirectives[results[0].directives[1].directiveIndex].id)
|
||||||
expect(annotatedDirectives[results[0].directives[1].directiveIndex].id).toEqual('someDirective');
|
.toEqual('someDirective');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@IMPLEMENTS(CompileStep)
|
class MockStep implements CompileStep {
|
||||||
class MockStep {
|
processClosure: Function;
|
||||||
processClosure:Function;
|
constructor(process) { this.processClosure = process; }
|
||||||
constructor(process) {
|
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||||
this.processClosure = process;
|
|
||||||
}
|
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
|
||||||
this.processClosure(parent, current, control);
|
this.processClosure(parent, current, control);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var someComponent = new DirectiveMetadata({
|
var someComponent = new DirectiveMetadata(
|
||||||
selector: 'some-comp',
|
{selector: 'some-comp', id: 'someComponent', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||||
id: 'someComponent',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var someComponentDup = new DirectiveMetadata({
|
var someComponentDup = new DirectiveMetadata(
|
||||||
selector: 'some-comp',
|
{selector: 'some-comp', id: 'someComponentDup', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||||
id: 'someComponentDup',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var someComponent2 = new DirectiveMetadata({
|
var someComponent2 = new DirectiveMetadata(
|
||||||
selector: 'some-comp2',
|
{selector: 'some-comp2', id: 'someComponent2', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||||
id: 'someComponent2',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var someDirective = new DirectiveMetadata({
|
var someDirective = new DirectiveMetadata(
|
||||||
selector: '[some-decor]',
|
{selector: '[some-decor]', id: 'someDirective', type: DirectiveMetadata.DIRECTIVE_TYPE});
|
||||||
id: 'someDirective',
|
|
||||||
type: DirectiveMetadata.DIRECTIVE_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var someDirectiveIgnoringChildren = new DirectiveMetadata({
|
var someDirectiveIgnoringChildren = new DirectiveMetadata({
|
||||||
selector: '[some-decor-ignoring-children]',
|
selector: '[some-decor-ignoring-children]',
|
||||||
|
@ -275,47 +239,34 @@ var decoratorWithMultipleAttrs = new DirectiveMetadata({
|
||||||
|
|
||||||
var someDirectiveWithProps = new DirectiveMetadata({
|
var someDirectiveWithProps = new DirectiveMetadata({
|
||||||
selector: '[some-decor-props]',
|
selector: '[some-decor-props]',
|
||||||
properties: MapWrapper.createFromStringMap({
|
properties:
|
||||||
'dirProp': 'elProp',
|
MapWrapper.createFromStringMap({'dirProp': 'elProp', 'doubleProp': 'elProp | double'}),
|
||||||
'doubleProp': 'elProp | double'
|
|
||||||
}),
|
|
||||||
readAttributes: ['some-attr']
|
readAttributes: ['some-attr']
|
||||||
});
|
});
|
||||||
|
|
||||||
var someDirectiveWithHostProperties = new DirectiveMetadata({
|
var someDirectiveWithHostProperties = new DirectiveMetadata({
|
||||||
selector: '[some-decor-with-host-props]',
|
selector: '[some-decor-with-host-props]',
|
||||||
hostProperties: MapWrapper.createFromStringMap({
|
hostProperties: MapWrapper.createFromStringMap({'dirProp': 'hostProperty'})
|
||||||
'dirProp': 'hostProperty'
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var someDirectiveWithHostAttributes = new DirectiveMetadata({
|
var someDirectiveWithHostAttributes = new DirectiveMetadata({
|
||||||
selector: '[some-decor-with-host-attrs]',
|
selector: '[some-decor-with-host-attrs]',
|
||||||
hostAttributes: MapWrapper.createFromStringMap({
|
hostAttributes: MapWrapper.createFromStringMap({'attr_name': 'attr_val', 'class': 'foo bar'})
|
||||||
'attr_name': 'attr_val',
|
|
||||||
'class': 'foo bar'
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var someDirectiveWithEvents = new DirectiveMetadata({
|
var someDirectiveWithEvents = new DirectiveMetadata({
|
||||||
selector: '[some-decor-events]',
|
selector: '[some-decor-events]',
|
||||||
hostListeners: MapWrapper.createFromStringMap({
|
hostListeners: MapWrapper.createFromStringMap({'click': 'doIt()'})
|
||||||
'click': 'doIt()'
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var someDirectiveWithHostActions = new DirectiveMetadata({
|
var someDirectiveWithHostActions = new DirectiveMetadata({
|
||||||
selector: '[some-decor-host-actions]',
|
selector: '[some-decor-host-actions]',
|
||||||
hostActions: MapWrapper.createFromStringMap({
|
hostActions: MapWrapper.createFromStringMap({'focus': 'focus()'})
|
||||||
'focus': 'focus()'
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var someDirectiveWithGlobalEvents = new DirectiveMetadata({
|
var someDirectiveWithGlobalEvents = new DirectiveMetadata({
|
||||||
selector: '[some-decor-globalevents]',
|
selector: '[some-decor-globalevents]',
|
||||||
hostListeners: MapWrapper.createFromStringMap({
|
hostListeners: MapWrapper.createFromStringMap({'window:resize': 'doItGlobal()'})
|
||||||
'window:resize': 'doItGlobal()'
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var componentWithNonElementSelector = new DirectiveMetadata({
|
var componentWithNonElementSelector = new DirectiveMetadata({
|
|
@ -5,7 +5,7 @@ import {isPresent, NumberWrapper, StringWrapper, IMPLEMENTS} from 'angular2/src/
|
||||||
|
|
||||||
import {CompilePipeline} from 'angular2/src/render/dom/compiler/compile_pipeline';
|
import {CompilePipeline} from 'angular2/src/render/dom/compiler/compile_pipeline';
|
||||||
import {CompileElement} from 'angular2/src/render/dom/compiler/compile_element';
|
import {CompileElement} from 'angular2/src/render/dom/compiler/compile_element';
|
||||||
import {CompileStep} from 'angular2/src/render/dom/compiler/compile_step'
|
import {CompileStep} from 'angular2/src/render/dom/compiler/compile_step';
|
||||||
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
|
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
|
||||||
|
|
||||||
import {ProtoViewBuilder} from 'angular2/src/render/dom/view/proto_view_builder';
|
import {ProtoViewBuilder} from 'angular2/src/render/dom/view/proto_view_builder';
|
||||||
|
@ -25,7 +25,8 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should stop walking the tree when compileChildren is false', () => {
|
it('should stop walking the tree when compileChildren is false', () => {
|
||||||
var element = el('<div id="1"><template id="2" ignore-children><span id="3"></span></template></div>');
|
var element = el(
|
||||||
|
'<div id="1"><template id="2" ignore-children><span id="3"></span></template></div>');
|
||||||
|
|
||||||
var step0Log = [];
|
var step0Log = [];
|
||||||
var pipeline = new CompilePipeline([new IgnoreChildrenStep(), createLoggerStep(step0Log)]);
|
var pipeline = new CompilePipeline([new IgnoreChildrenStep(), createLoggerStep(step0Log)]);
|
||||||
|
@ -40,7 +41,8 @@ export function main() {
|
||||||
var element = el('<div><div><span viewroot><span></span></span></div></div>');
|
var element = el('<div><div><span viewroot><span></span></span></div></div>');
|
||||||
var pipeline = new CompilePipeline([new MockStep((parent, current, control) => {
|
var pipeline = new CompilePipeline([new MockStep((parent, current, control) => {
|
||||||
if (isPresent(DOM.getAttribute(current.element, 'viewroot'))) {
|
if (isPresent(DOM.getAttribute(current.element, 'viewroot'))) {
|
||||||
current.inheritedProtoView = new ProtoViewBuilder(current.element, ProtoViewDto.EMBEDDED_VIEW_TYPE);
|
current.inheritedProtoView =
|
||||||
|
new ProtoViewBuilder(current.element, ProtoViewDto.EMBEDDED_VIEW_TYPE);
|
||||||
}
|
}
|
||||||
})]);
|
})]);
|
||||||
var results = pipeline.process(element);
|
var results = pipeline.process(element);
|
||||||
|
@ -99,10 +101,8 @@ export function main() {
|
||||||
var element = el('<div id="1"><span wrap0="1" id="2"><b id="3"></b></span></div>');
|
var element = el('<div id="1"><span wrap0="1" id="2"><b id="3"></b></span></div>');
|
||||||
var step0Log = [];
|
var step0Log = [];
|
||||||
var step1Log = [];
|
var step1Log = [];
|
||||||
var pipeline = new CompilePipeline([
|
var pipeline = new CompilePipeline(
|
||||||
createWrapperStep('wrap0', step0Log),
|
[createWrapperStep('wrap0', step0Log), createLoggerStep(step1Log)]);
|
||||||
createLoggerStep(step1Log)
|
|
||||||
]);
|
|
||||||
var result = pipeline.process(element);
|
var result = pipeline.process(element);
|
||||||
expect(step0Log).toEqual(['1', '1<2', '2<3']);
|
expect(step0Log).toEqual(['1', '1<2', '2<3']);
|
||||||
expect(step1Log).toEqual(['1', '1<wrap0#0', 'wrap0#0<2', '2<3']);
|
expect(step1Log).toEqual(['1', '1<wrap0#0', 'wrap0#0<2', '2<3']);
|
||||||
|
@ -110,7 +110,8 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow to add a parent by multiple processors to the same element', () => {
|
it('should allow to add a parent by multiple processors to the same element', () => {
|
||||||
var element = el('<div id="1"><span wrap0="1" wrap1="1" id="2"><b id="3"></b></span></div>');
|
var element =
|
||||||
|
el('<div id="1"><span wrap0="1" wrap1="1" id="2"><b id="3"></b></span></div>');
|
||||||
var step0Log = [];
|
var step0Log = [];
|
||||||
var step1Log = [];
|
var step1Log = [];
|
||||||
var step2Log = [];
|
var step2Log = [];
|
||||||
|
@ -127,7 +128,8 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow to add a parent by multiple processors to different elements', () => {
|
it('should allow to add a parent by multiple processors to different elements', () => {
|
||||||
var element = el('<div id="1"><span wrap0="1" id="2"><b id="3" wrap1="1"></b></span></div>');
|
var element =
|
||||||
|
el('<div id="1"><span wrap0="1" id="2"><b id="3" wrap1="1"></b></span></div>');
|
||||||
var step0Log = [];
|
var step0Log = [];
|
||||||
var step1Log = [];
|
var step1Log = [];
|
||||||
var step2Log = [];
|
var step2Log = [];
|
||||||
|
@ -147,10 +149,8 @@ export function main() {
|
||||||
var element = el('<div id="1"><span wrap0="2" id="2"><b id="3"></b></span></div>');
|
var element = el('<div id="1"><span wrap0="2" id="2"><b id="3"></b></span></div>');
|
||||||
var step0Log = [];
|
var step0Log = [];
|
||||||
var step1Log = [];
|
var step1Log = [];
|
||||||
var pipeline = new CompilePipeline([
|
var pipeline = new CompilePipeline(
|
||||||
createWrapperStep('wrap0', step0Log),
|
[createWrapperStep('wrap0', step0Log), createLoggerStep(step1Log)]);
|
||||||
createLoggerStep(step1Log)
|
|
||||||
]);
|
|
||||||
var result = pipeline.process(element);
|
var result = pipeline.process(element);
|
||||||
expect(step0Log).toEqual(['1', '1<2', '2<3']);
|
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(step1Log).toEqual(['1', '1<wrap0#0', 'wrap0#0<wrap0#1', 'wrap0#1<2', '2<3']);
|
||||||
|
@ -165,11 +165,12 @@ export function main() {
|
||||||
var resultLog = [];
|
var resultLog = [];
|
||||||
var newChild = new CompileElement(el('<div id="3"></div>'));
|
var newChild = new CompileElement(el('<div id="3"></div>'));
|
||||||
var pipeline = new CompilePipeline([
|
var pipeline = new CompilePipeline([
|
||||||
new MockStep((parent, current, control) => {
|
new MockStep((parent, current, control) =>
|
||||||
if (StringWrapper.equals(DOM.getAttribute(current.element, 'id'), '1')) {
|
{
|
||||||
control.addChild(newChild);
|
if (StringWrapper.equals(DOM.getAttribute(current.element, 'id'), '1')) {
|
||||||
}
|
control.addChild(newChild);
|
||||||
}),
|
}
|
||||||
|
}),
|
||||||
createLoggerStep(resultLog)
|
createLoggerStep(resultLog)
|
||||||
]);
|
]);
|
||||||
var result = pipeline.process(element);
|
var result = pipeline.process(element);
|
||||||
|
@ -182,20 +183,16 @@ export function main() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@IMPLEMENTS(CompileStep)
|
class MockStep implements CompileStep {
|
||||||
class MockStep {
|
processClosure: Function;
|
||||||
processClosure:Function;
|
constructor(process) { this.processClosure = process; }
|
||||||
constructor(process) {
|
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||||
this.processClosure = process;
|
|
||||||
}
|
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
|
||||||
this.processClosure(parent, current, control);
|
this.processClosure(parent, current, control);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@IMPLEMENTS(CompileStep)
|
export class IgnoreChildrenStep implements CompileStep {
|
||||||
export class IgnoreChildrenStep {
|
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
|
||||||
var attributeMap = DOM.attributeMap(current.element);
|
var attributeMap = DOM.attributeMap(current.element);
|
||||||
if (MapWrapper.contains(attributeMap, 'ignore-children')) {
|
if (MapWrapper.contains(attributeMap, 'ignore-children')) {
|
||||||
current.compileChildren = false;
|
current.compileChildren = false;
|
||||||
|
@ -203,9 +200,8 @@ export class IgnoreChildrenStep {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@IMPLEMENTS(CompileStep)
|
class IgnoreCurrentElementStep implements CompileStep {
|
||||||
class IgnoreCurrentElementStep {
|
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
|
||||||
var attributeMap = DOM.attributeMap(current.element);
|
var attributeMap = DOM.attributeMap(current.element);
|
||||||
if (MapWrapper.contains(attributeMap, 'ignore-current')) {
|
if (MapWrapper.contains(attributeMap, 'ignore-current')) {
|
||||||
control.ignoreCurrentElement();
|
control.ignoreCurrentElement();
|
||||||
|
@ -222,9 +218,7 @@ function logEntry(log, parent, current) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function createLoggerStep(log) {
|
function createLoggerStep(log) {
|
||||||
return new MockStep((parent, current, control) => {
|
return new MockStep((parent, current, control) => { logEntry(log, parent, current); });
|
||||||
logEntry(log, parent, current);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createWrapperStep(wrapperId, log) {
|
function createWrapperStep(wrapperId, log) {
|
||||||
|
@ -244,8 +238,6 @@ function createWrapperStep(wrapperId, log) {
|
||||||
|
|
||||||
function resultIdLog(result) {
|
function resultIdLog(result) {
|
||||||
var idLog = [];
|
var idLog = [];
|
||||||
ListWrapper.forEach(result, (current) => {
|
ListWrapper.forEach(result, (current) => { logEntry(idLog, null, current); });
|
||||||
logEntry(idLog, null, current);
|
|
||||||
});
|
|
||||||
return idLog;
|
return idLog;
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ import {CompileElement} from 'angular2/src/render/dom/compiler/compile_element';
|
||||||
import {CompileStep} from 'angular2/src/render/dom/compiler/compile_step';
|
import {CompileStep} from 'angular2/src/render/dom/compiler/compile_step';
|
||||||
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
|
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
|
||||||
import {Lexer, Parser} from 'angular2/change_detection';
|
import {Lexer, Parser} from 'angular2/change_detection';
|
||||||
|
import {ElementBinderBuilder} from 'angular2/src/render/dom/view/proto_view_builder';
|
||||||
|
|
||||||
var EMPTY_MAP = MapWrapper.create();
|
var EMPTY_MAP = MapWrapper.create();
|
||||||
|
|
||||||
|
@ -14,19 +15,19 @@ export function main() {
|
||||||
describe('PropertyBindingParser', () => {
|
describe('PropertyBindingParser', () => {
|
||||||
function createPipeline(hasNestedProtoView = false) {
|
function createPipeline(hasNestedProtoView = false) {
|
||||||
return new CompilePipeline([
|
return new CompilePipeline([
|
||||||
new MockStep((parent, current, control) => {
|
new MockStep((parent, current, control) =>
|
||||||
if (hasNestedProtoView) {
|
{
|
||||||
current.bindElement().bindNestedProtoView(el('<template></template>'));
|
if (hasNestedProtoView) {
|
||||||
}
|
current.bindElement().bindNestedProtoView(el('<template></template>'));
|
||||||
}),
|
}
|
||||||
new PropertyBindingParser(new Parser(new Lexer()))]);
|
}),
|
||||||
|
new PropertyBindingParser(new Parser(new Lexer()))
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function process(element, hasNestedProtoView = false) {
|
function process(element, hasNestedProtoView = false): List<ElementBinderBuilder> {
|
||||||
return ListWrapper.map(
|
return ListWrapper.map(createPipeline(hasNestedProtoView).process(element),
|
||||||
createPipeline(hasNestedProtoView).process(element),
|
(compileElement) => compileElement.inheritedElementBinder);
|
||||||
(compileElement) => compileElement.inheritedElementBinder
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should detect [] syntax', () => {
|
it('should detect [] syntax', () => {
|
||||||
|
@ -44,9 +45,8 @@ export function main() {
|
||||||
expect(MapWrapper.get(results[0].propertyBindings, 'a').source).toEqual('b');
|
expect(MapWrapper.get(results[0].propertyBindings, 'a').source).toEqual('b');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should detect bind- syntax only if an attribute name starts with bind', () => {
|
it('should detect bind- syntax only if an attribute name starts with bind',
|
||||||
expect(process(el('<div _bind-a="b"></div>'))[0]).toEqual(null);
|
() => { expect(process(el('<div _bind-a="b"></div>'))[0]).toEqual(null); });
|
||||||
});
|
|
||||||
|
|
||||||
it('should detect interpolation syntax', () => {
|
it('should detect interpolation syntax', () => {
|
||||||
var results = process(el('<div a="{{b}}"></div>'));
|
var results = process(el('<div a="{{b}}"></div>'));
|
||||||
|
@ -67,14 +67,17 @@ export function main() {
|
||||||
it('should store variable binding for a template element on the nestedProtoView', () => {
|
it('should store variable binding for a template element on the nestedProtoView', () => {
|
||||||
var results = process(el('<template var-george="washington"></p>'), true);
|
var results = process(el('<template var-george="washington"></p>'), true);
|
||||||
expect(results[0].variableBindings).toEqual(EMPTY_MAP);
|
expect(results[0].variableBindings).toEqual(EMPTY_MAP);
|
||||||
expect(MapWrapper.get(results[0].nestedProtoView.variableBindings, 'washington')).toEqual('george');
|
expect(MapWrapper.get(results[0].nestedProtoView.variableBindings, 'washington'))
|
||||||
|
.toEqual('george');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should store variable binding for a non-template element using shorthand syntax on the nestedProtoView', () => {
|
it('should store variable binding for a non-template element using shorthand syntax on the nestedProtoView',
|
||||||
var results = process(el('<template #george="washington"></template>'), true);
|
() => {
|
||||||
expect(results[0].variableBindings).toEqual(EMPTY_MAP);
|
var results = process(el('<template #george="washington"></template>'), true);
|
||||||
expect(MapWrapper.get(results[0].nestedProtoView.variableBindings, 'washington')).toEqual('george');
|
expect(results[0].variableBindings).toEqual(EMPTY_MAP);
|
||||||
});
|
expect(MapWrapper.get(results[0].nestedProtoView.variableBindings, 'washington'))
|
||||||
|
.toEqual('george');
|
||||||
|
});
|
||||||
|
|
||||||
it('should store variable binding for a non-template element', () => {
|
it('should store variable binding for a non-template element', () => {
|
||||||
var results = process(el('<p var-george="washington"></p>'));
|
var results = process(el('<p var-george="washington"></p>'));
|
||||||
|
@ -165,13 +168,10 @@ export function main() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@IMPLEMENTS(CompileStep)
|
class MockStep implements CompileStep {
|
||||||
class MockStep {
|
processClosure: Function;
|
||||||
processClosure:Function;
|
constructor(process) { this.processClosure = process; }
|
||||||
constructor(process) {
|
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||||
this.processClosure = process;
|
|
||||||
}
|
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
|
||||||
this.processClosure(parent, current, control);
|
this.processClosure(parent, current, control);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,9 +8,7 @@ export function main() {
|
||||||
describe('SelectorMatcher', () => {
|
describe('SelectorMatcher', () => {
|
||||||
var matcher, matched, selectableCollector, s1, s2, s3, s4;
|
var matcher, matched, selectableCollector, s1, s2, s3, s4;
|
||||||
|
|
||||||
function reset() {
|
function reset() { matched = ListWrapper.create(); }
|
||||||
matched = ListWrapper.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
reset();
|
reset();
|
||||||
|
@ -18,52 +16,58 @@ export function main() {
|
||||||
selectableCollector = (selector, context) => {
|
selectableCollector = (selector, context) => {
|
||||||
ListWrapper.push(matched, selector);
|
ListWrapper.push(matched, selector);
|
||||||
ListWrapper.push(matched, context);
|
ListWrapper.push(matched, context);
|
||||||
}
|
};
|
||||||
matcher = new SelectorMatcher();
|
matcher = new SelectorMatcher();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should select by element name case insensitive', () => {
|
it('should select by element name case insensitive', () => {
|
||||||
matcher.addSelectables(s1 = CssSelector.parse('someTag'), 1);
|
matcher.addSelectables(s1 = CssSelector.parse('someTag'), 1);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('SOMEOTHERTAG')[0], selectableCollector)).toEqual(false);
|
expect(matcher.match(CssSelector.parse('SOMEOTHERTAG')[0], selectableCollector))
|
||||||
|
.toEqual(false);
|
||||||
expect(matched).toEqual([]);
|
expect(matched).toEqual([]);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('SOMETAG')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('SOMETAG')[0], selectableCollector)).toEqual(true);
|
||||||
expect(matched).toEqual([s1[0],1]);
|
expect(matched).toEqual([s1[0], 1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should select by class name case insensitive', () => {
|
it('should select by class name case insensitive', () => {
|
||||||
matcher.addSelectables(s1 = CssSelector.parse('.someClass'), 1);
|
matcher.addSelectables(s1 = CssSelector.parse('.someClass'), 1);
|
||||||
matcher.addSelectables(s2 = CssSelector.parse('.someClass.class2'), 2);
|
matcher.addSelectables(s2 = CssSelector.parse('.someClass.class2'), 2);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('.SOMEOTHERCLASS')[0], selectableCollector)).toEqual(false);
|
expect(matcher.match(CssSelector.parse('.SOMEOTHERCLASS')[0], selectableCollector))
|
||||||
|
.toEqual(false);
|
||||||
expect(matched).toEqual([]);
|
expect(matched).toEqual([]);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('.SOMECLASS')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('.SOMECLASS')[0], selectableCollector)).toEqual(true);
|
||||||
expect(matched).toEqual([s1[0],1]);
|
expect(matched).toEqual([s1[0], 1]);
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
expect(matcher.match(CssSelector.parse('.someClass.class2')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('.someClass.class2')[0], selectableCollector))
|
||||||
expect(matched).toEqual([s1[0],1,s2[0],2]);
|
.toEqual(true);
|
||||||
|
expect(matched).toEqual([s1[0], 1, s2[0], 2]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should select by attr name case insensitive independent of the value', () => {
|
it('should select by attr name case insensitive independent of the value', () => {
|
||||||
matcher.addSelectables(s1 = CssSelector.parse('[someAttr]'), 1);
|
matcher.addSelectables(s1 = CssSelector.parse('[someAttr]'), 1);
|
||||||
matcher.addSelectables(s2 = CssSelector.parse('[someAttr][someAttr2]'), 2);
|
matcher.addSelectables(s2 = CssSelector.parse('[someAttr][someAttr2]'), 2);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('[SOMEOTHERATTR]')[0], selectableCollector)).toEqual(false);
|
expect(matcher.match(CssSelector.parse('[SOMEOTHERATTR]')[0], selectableCollector))
|
||||||
|
.toEqual(false);
|
||||||
expect(matched).toEqual([]);
|
expect(matched).toEqual([]);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('[SOMEATTR]')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('[SOMEATTR]')[0], selectableCollector)).toEqual(true);
|
||||||
expect(matched).toEqual([s1[0],1]);
|
expect(matched).toEqual([s1[0], 1]);
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
expect(matcher.match(CssSelector.parse('[SOMEATTR=someValue]')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('[SOMEATTR=someValue]')[0], selectableCollector))
|
||||||
expect(matched).toEqual([s1[0],1]);
|
.toEqual(true);
|
||||||
|
expect(matched).toEqual([s1[0], 1]);
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
expect(matcher.match(CssSelector.parse('[someAttr][someAttr2]')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('[someAttr][someAttr2]')[0], selectableCollector))
|
||||||
expect(matched).toEqual([s1[0],1,s2[0],2]);
|
.toEqual(true);
|
||||||
|
expect(matched).toEqual([s1[0], 1, s2[0], 2]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should select by attr name only once if the value is from the DOM', () => {
|
it('should select by attr name only once if the value is from the DOM', () => {
|
||||||
|
@ -74,36 +78,48 @@ export function main() {
|
||||||
var empty = DOM.getAttribute(element, 'attr');
|
var empty = DOM.getAttribute(element, 'attr');
|
||||||
elementSelector.addAttribute('some-decor', empty);
|
elementSelector.addAttribute('some-decor', empty);
|
||||||
matcher.match(elementSelector, selectableCollector);
|
matcher.match(elementSelector, selectableCollector);
|
||||||
expect(matched).toEqual([s1[0],1]);
|
expect(matched).toEqual([s1[0], 1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should select by attr name and value case insensitive', () => {
|
it('should select by attr name and value case insensitive', () => {
|
||||||
matcher.addSelectables(s1 = CssSelector.parse('[someAttr=someValue]'), 1);
|
matcher.addSelectables(s1 = CssSelector.parse('[someAttr=someValue]'), 1);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('[SOMEATTR=SOMEOTHERATTR]')[0], selectableCollector)).toEqual(false);
|
expect(matcher.match(CssSelector.parse('[SOMEATTR=SOMEOTHERATTR]')[0], selectableCollector))
|
||||||
|
.toEqual(false);
|
||||||
expect(matched).toEqual([]);
|
expect(matched).toEqual([]);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('[SOMEATTR=SOMEVALUE]')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('[SOMEATTR=SOMEVALUE]')[0], selectableCollector))
|
||||||
expect(matched).toEqual([s1[0],1]);
|
.toEqual(true);
|
||||||
|
expect(matched).toEqual([s1[0], 1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should select by element name, class name and attribute name with value', () => {
|
it('should select by element name, class name and attribute name with value', () => {
|
||||||
matcher.addSelectables(s1 = CssSelector.parse('someTag.someClass[someAttr=someValue]'), 1);
|
matcher.addSelectables(s1 = CssSelector.parse('someTag.someClass[someAttr=someValue]'), 1);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('someOtherTag.someOtherClass[someOtherAttr]')[0], selectableCollector)).toEqual(false);
|
expect(matcher.match(CssSelector.parse('someOtherTag.someOtherClass[someOtherAttr]')[0],
|
||||||
|
selectableCollector))
|
||||||
|
.toEqual(false);
|
||||||
expect(matched).toEqual([]);
|
expect(matched).toEqual([]);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('someTag.someOtherClass[someOtherAttr]')[0], selectableCollector)).toEqual(false);
|
expect(matcher.match(CssSelector.parse('someTag.someOtherClass[someOtherAttr]')[0],
|
||||||
|
selectableCollector))
|
||||||
|
.toEqual(false);
|
||||||
expect(matched).toEqual([]);
|
expect(matched).toEqual([]);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('someTag.someClass[someOtherAttr]')[0], selectableCollector)).toEqual(false);
|
expect(matcher.match(CssSelector.parse('someTag.someClass[someOtherAttr]')[0],
|
||||||
|
selectableCollector))
|
||||||
|
.toEqual(false);
|
||||||
expect(matched).toEqual([]);
|
expect(matched).toEqual([]);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('someTag.someClass[someAttr]')[0], selectableCollector)).toEqual(false);
|
expect(
|
||||||
|
matcher.match(CssSelector.parse('someTag.someClass[someAttr]')[0], selectableCollector))
|
||||||
|
.toEqual(false);
|
||||||
expect(matched).toEqual([]);
|
expect(matched).toEqual([]);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('someTag.someClass[someAttr=someValue]')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('someTag.someClass[someAttr=someValue]')[0],
|
||||||
expect(matched).toEqual([s1[0],1]);
|
selectableCollector))
|
||||||
|
.toEqual(true);
|
||||||
|
expect(matched).toEqual([s1[0], 1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should select by many attributes and independent of the value', () => {
|
it('should select by many attributes and independent of the value', () => {
|
||||||
|
@ -124,20 +140,24 @@ export function main() {
|
||||||
matcher.addSelectables(s3 = CssSelector.parse('.class1.class2'), 3);
|
matcher.addSelectables(s3 = CssSelector.parse('.class1.class2'), 3);
|
||||||
matcher.addSelectables(s4 = CssSelector.parse('.class2.class1'), 4);
|
matcher.addSelectables(s4 = CssSelector.parse('.class2.class1'), 4);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('[someAttr].someClass')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('[someAttr].someClass')[0], selectableCollector))
|
||||||
expect(matched).toEqual([s1[0],1,s2[0],2]);
|
.toEqual(true);
|
||||||
|
expect(matched).toEqual([s1[0], 1, s2[0], 2]);
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
expect(matcher.match(CssSelector.parse('.someClass[someAttr]')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('.someClass[someAttr]')[0], selectableCollector))
|
||||||
expect(matched).toEqual([s1[0],1,s2[0],2]);
|
.toEqual(true);
|
||||||
|
expect(matched).toEqual([s1[0], 1, s2[0], 2]);
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
expect(matcher.match(CssSelector.parse('.class1.class2')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('.class1.class2')[0], selectableCollector))
|
||||||
expect(matched).toEqual([s3[0],3,s4[0],4]);
|
.toEqual(true);
|
||||||
|
expect(matched).toEqual([s3[0], 3, s4[0], 4]);
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
expect(matcher.match(CssSelector.parse('.class2.class1')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('.class2.class1')[0], selectableCollector))
|
||||||
expect(matched).toEqual([s4[0],4,s3[0],3]);
|
.toEqual(true);
|
||||||
|
expect(matched).toEqual([s4[0], 4, s3[0], 3]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not select with a matching :not selector', () => {
|
it('should not select with a matching :not selector', () => {
|
||||||
|
@ -147,7 +167,8 @@ export function main() {
|
||||||
matcher.addSelectables(CssSelector.parse(':not(p)'), 4);
|
matcher.addSelectables(CssSelector.parse(':not(p)'), 4);
|
||||||
matcher.addSelectables(CssSelector.parse(':not(p[someAttr])'), 5);
|
matcher.addSelectables(CssSelector.parse(':not(p[someAttr])'), 5);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('p.someClass[someAttr]')[0], selectableCollector)).toEqual(false);
|
expect(matcher.match(CssSelector.parse('p.someClass[someAttr]')[0], selectableCollector))
|
||||||
|
.toEqual(false);
|
||||||
expect(matched).toEqual([]);
|
expect(matched).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -157,27 +178,31 @@ export function main() {
|
||||||
matcher.addSelectables(s3 = CssSelector.parse(':not(.someClass)'), 3);
|
matcher.addSelectables(s3 = CssSelector.parse(':not(.someClass)'), 3);
|
||||||
matcher.addSelectables(s4 = CssSelector.parse(':not(.someOtherClass[someAttr])'), 4);
|
matcher.addSelectables(s4 = CssSelector.parse(':not(.someOtherClass[someAttr])'), 4);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('p[someOtherAttr].someOtherClass')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('p[someOtherAttr].someOtherClass')[0],
|
||||||
expect(matched).toEqual([s1[0],1,s2[0],2,s3[0],3,s4[0],4]);
|
selectableCollector))
|
||||||
|
.toEqual(true);
|
||||||
|
expect(matched).toEqual([s1[0], 1, s2[0], 2, s3[0], 3, s4[0], 4]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should select with one match in a list', () => {
|
it('should select with one match in a list', () => {
|
||||||
matcher.addSelectables(s1 = CssSelector.parse('input[type=text], textbox'), 1);
|
matcher.addSelectables(s1 = CssSelector.parse('input[type=text], textbox'), 1);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('textbox')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('textbox')[0], selectableCollector)).toEqual(true);
|
||||||
expect(matched).toEqual([s1[1],1]);
|
expect(matched).toEqual([s1[1], 1]);
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
expect(matcher.match(CssSelector.parse('input[type=text]')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('input[type=text]')[0], selectableCollector))
|
||||||
expect(matched).toEqual([s1[0],1]);
|
.toEqual(true);
|
||||||
|
expect(matched).toEqual([s1[0], 1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not select twice with two matches in a list', () => {
|
it('should not select twice with two matches in a list', () => {
|
||||||
matcher.addSelectables(s1 = CssSelector.parse('input, .someClass'), 1);
|
matcher.addSelectables(s1 = CssSelector.parse('input, .someClass'), 1);
|
||||||
|
|
||||||
expect(matcher.match(CssSelector.parse('input.someclass')[0], selectableCollector)).toEqual(true);
|
expect(matcher.match(CssSelector.parse('input.someclass')[0], selectableCollector))
|
||||||
expect(matched.length).toEqual(2);
|
.toEqual(true);
|
||||||
expect(matched).toEqual([s1[0],1]);
|
expect(matched.length).toEqual(2);
|
||||||
|
expect(matched).toEqual([s1[0], 1]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -251,9 +276,8 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when nested :not', () => {
|
it('should throw when nested :not', () => {
|
||||||
expect(() => {
|
expect(() => { CssSelector.parse('sometag:not(:not([attrname=attrvalue].someclass))')[0]; })
|
||||||
CssSelector.parse('sometag:not(:not([attrname=attrvalue].someclass))')[0];
|
.toThrowError('Nesting :not is not allowed in a selector');
|
||||||
}).toThrowError('Nesting :not is not allowed in a selector');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should detect lists of selectors', () => {
|
it('should detect lists of selectors', () => {
|
||||||
|
@ -266,7 +290,8 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should detect lists of selectors with :not', () => {
|
it('should detect lists of selectors with :not', () => {
|
||||||
var cssSelectors = CssSelector.parse('input[type=text], :not(textarea), textbox:not(.special)');
|
var cssSelectors =
|
||||||
|
CssSelector.parse('input[type=text], :not(textarea), textbox:not(.special)');
|
||||||
expect(cssSelectors.length).toEqual(3);
|
expect(cssSelectors.length).toEqual(3);
|
||||||
|
|
||||||
expect(cssSelectors[0].element).toEqual('input');
|
expect(cssSelectors[0].element).toEqual('input');
|
|
@ -1,100 +0,0 @@
|
||||||
import {
|
|
||||||
AsyncTestCompleter,
|
|
||||||
beforeEach,
|
|
||||||
ddescribe,
|
|
||||||
describe,
|
|
||||||
el,
|
|
||||||
expect,
|
|
||||||
iit,
|
|
||||||
inject,
|
|
||||||
it,
|
|
||||||
xit,
|
|
||||||
} from 'angular2/test_lib';
|
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
|
||||||
import {TemplateLoader} from 'angular2/src/render/dom/compiler/template_loader';
|
|
||||||
import {UrlResolver} from 'angular2/src/services/url_resolver';
|
|
||||||
|
|
||||||
import {ViewDefinition} from 'angular2/src/render/api';
|
|
||||||
import {PromiseWrapper} from 'angular2/src/facade/async';
|
|
||||||
import {MockXHR} from 'angular2/src/mock/xhr_mock';
|
|
||||||
|
|
||||||
export function main() {
|
|
||||||
describe('TemplateLoader', () => {
|
|
||||||
var loader, xhr;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
xhr = new MockXHR();
|
|
||||||
loader = new TemplateLoader(xhr, new FakeUrlResolver());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should load inline templates', inject([AsyncTestCompleter], (async) => {
|
|
||||||
var template = new ViewDefinition({template: 'template template'});
|
|
||||||
loader.load(template).then( (el) => {
|
|
||||||
expect(DOM.content(el)).toHaveText('template template');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should load templates through XHR', inject([AsyncTestCompleter], (async) => {
|
|
||||||
xhr.expect('base/foo', 'xhr template');
|
|
||||||
var template = new ViewDefinition({absUrl: 'base/foo'});
|
|
||||||
loader.load(template).then((el) => {
|
|
||||||
expect(DOM.content(el)).toHaveText('xhr template');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
xhr.flush();
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should cache template loaded through XHR but clone it as the compiler might change it', inject([AsyncTestCompleter], (async) => {
|
|
||||||
var firstEl;
|
|
||||||
// we have only one xhr.expect, so there can only be one xhr call!
|
|
||||||
xhr.expect('base/foo', 'xhr template');
|
|
||||||
var template = new ViewDefinition({absUrl: 'base/foo'});
|
|
||||||
loader.load(template)
|
|
||||||
.then((el) => {
|
|
||||||
expect(DOM.content(el)).toHaveText('xhr template');
|
|
||||||
firstEl = el;
|
|
||||||
return loader.load(template);
|
|
||||||
})
|
|
||||||
.then((el) =>{
|
|
||||||
expect(el).not.toBe(firstEl);
|
|
||||||
expect(DOM.content(el)).toHaveText('xhr template');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
xhr.flush();
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should throw when no template is defined', () => {
|
|
||||||
var template = new ViewDefinition({template: null, absUrl: null});
|
|
||||||
expect(() => loader.load(template))
|
|
||||||
.toThrowError('View should have either the url or template property set');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return a rejected Promise when xhr loading fails', inject([AsyncTestCompleter], (async) => {
|
|
||||||
xhr.expect('base/foo', null);
|
|
||||||
var template = new ViewDefinition({absUrl: 'base/foo'});
|
|
||||||
PromiseWrapper.then(loader.load(template),
|
|
||||||
function(_) { throw 'Unexpected response'; },
|
|
||||||
function(error) {
|
|
||||||
expect(error).toEqual('Failed to load base/foo');
|
|
||||||
async.done();
|
|
||||||
}
|
|
||||||
)
|
|
||||||
xhr.flush();
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
class SomeComponent {
|
|
||||||
}
|
|
||||||
|
|
||||||
class FakeUrlResolver extends UrlResolver {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(baseUrl: string, url: string): string {
|
|
||||||
return baseUrl + url;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
import {
|
||||||
|
AsyncTestCompleter,
|
||||||
|
beforeEach,
|
||||||
|
ddescribe,
|
||||||
|
describe,
|
||||||
|
el,
|
||||||
|
expect,
|
||||||
|
iit,
|
||||||
|
inject,
|
||||||
|
it,
|
||||||
|
xit,
|
||||||
|
} from 'angular2/test_lib';
|
||||||
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
|
import {TemplateLoader} from 'angular2/src/render/dom/compiler/template_loader';
|
||||||
|
import {UrlResolver} from 'angular2/src/services/url_resolver';
|
||||||
|
|
||||||
|
import {ViewDefinition} from 'angular2/src/render/api';
|
||||||
|
import {PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
|
import {MockXHR} from 'angular2/src/mock/xhr_mock';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe('TemplateLoader', () => {
|
||||||
|
var loader, xhr;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
xhr = new MockXHR();
|
||||||
|
loader = new TemplateLoader(xhr, new FakeUrlResolver());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load inline templates', inject([AsyncTestCompleter], (async) => {
|
||||||
|
var template = new ViewDefinition({template: 'template template'});
|
||||||
|
loader.load(template).then((el) => {
|
||||||
|
expect(DOM.content(el)).toHaveText('template template');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should load templates through XHR', inject([AsyncTestCompleter], (async) => {
|
||||||
|
xhr.expect('base/foo', 'xhr template');
|
||||||
|
var template = new ViewDefinition({absUrl: 'base/foo'});
|
||||||
|
loader.load(template).then((el) => {
|
||||||
|
expect(DOM.content(el)).toHaveText('xhr template');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
xhr.flush();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should cache template loaded through XHR but clone it as the compiler might change it',
|
||||||
|
inject([AsyncTestCompleter], (async) => {
|
||||||
|
var firstEl;
|
||||||
|
// we have only one xhr.expect, so there can only be one xhr call!
|
||||||
|
xhr.expect('base/foo', 'xhr template');
|
||||||
|
var template = new ViewDefinition({absUrl: 'base/foo'});
|
||||||
|
loader.load(template)
|
||||||
|
.then((el) =>
|
||||||
|
{
|
||||||
|
expect(DOM.content(el)).toHaveText('xhr template');
|
||||||
|
firstEl = el;
|
||||||
|
return loader.load(template);
|
||||||
|
})
|
||||||
|
.then((el) => {
|
||||||
|
expect(el).not.toBe(firstEl);
|
||||||
|
expect(DOM.content(el)).toHaveText('xhr template');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
xhr.flush();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should throw when no template is defined', () => {
|
||||||
|
var template = new ViewDefinition({template: null, absUrl: null});
|
||||||
|
expect(() => loader.load(template))
|
||||||
|
.toThrowError('View should have either the url or template property set');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a rejected Promise when xhr loading fails',
|
||||||
|
inject([AsyncTestCompleter], (async) => {
|
||||||
|
xhr.expect('base/foo', null);
|
||||||
|
var template = new ViewDefinition({absUrl: 'base/foo'});
|
||||||
|
PromiseWrapper.then(loader.load(template), function(_) { throw 'Unexpected response'; },
|
||||||
|
function(error) {
|
||||||
|
expect(error).toEqual('Failed to load base/foo');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
xhr.flush();
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class SomeComponent {}
|
||||||
|
|
||||||
|
class FakeUrlResolver extends UrlResolver {
|
||||||
|
constructor() { super(); }
|
||||||
|
|
||||||
|
resolve(baseUrl: string, url: string): string { return baseUrl + url; }
|
||||||
|
}
|
|
@ -4,21 +4,18 @@ import {CompilePipeline} from 'angular2/src/render/dom/compiler/compile_pipeline
|
||||||
import {MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
import {MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {Lexer, Parser} from 'angular2/change_detection';
|
import {Lexer, Parser} from 'angular2/change_detection';
|
||||||
import {IgnoreChildrenStep} from './pipeline_spec';
|
import {IgnoreChildrenStep} from './pipeline_spec';
|
||||||
|
import {ElementBinderBuilder} from 'angular2/src/render/dom/view/proto_view_builder';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('TextInterpolationParser', () => {
|
describe('TextInterpolationParser', () => {
|
||||||
function createPipeline() {
|
function createPipeline() {
|
||||||
return new CompilePipeline([
|
return new CompilePipeline(
|
||||||
new IgnoreChildrenStep(),
|
[new IgnoreChildrenStep(), new TextInterpolationParser(new Parser(new Lexer()))]);
|
||||||
new TextInterpolationParser(new Parser(new Lexer()))
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function process(element) {
|
function process(element): List<ElementBinderBuilder> {
|
||||||
return ListWrapper.map(
|
return ListWrapper.map(createPipeline().process(element),
|
||||||
createPipeline().process(element),
|
(compileElement) => compileElement.inheritedElementBinder);
|
||||||
(compileElement) => compileElement.inheritedElementBinder
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertTextBinding(elementBinder, bindingIndex, nodeIndex, expression) {
|
function assertTextBinding(elementBinder, bindingIndex, nodeIndex, expression) {
|
|
@ -21,7 +21,8 @@ export function main() {
|
||||||
var rootElement = el('<div><template if="true">a</template></div>');
|
var rootElement = el('<div><template if="true">a</template></div>');
|
||||||
var results = createPipeline().process(rootElement);
|
var results = createPipeline().process(rootElement);
|
||||||
|
|
||||||
expect(DOM.getOuterHTML(results[1].element)).toEqual('<template if="true" class="ng-binding"></template>');
|
expect(DOM.getOuterHTML(results[1].element))
|
||||||
|
.toEqual('<template if="true" class="ng-binding"></template>');
|
||||||
expect(results[1].isViewRoot).toBe(false);
|
expect(results[1].isViewRoot).toBe(false);
|
||||||
expect(DOM.getOuterHTML(results[2].element)).toEqual('<template>a</template>');
|
expect(DOM.getOuterHTML(results[2].element)).toEqual('<template>a</template>');
|
||||||
expect(results[2].isViewRoot).toBe(true);
|
expect(results[2].isViewRoot).toBe(true);
|
||||||
|
@ -56,9 +57,11 @@ export function main() {
|
||||||
var rootElement = el('<div><template if="true">a</template></div>');
|
var rootElement = el('<div><template if="true">a</template></div>');
|
||||||
var results = createPipeline().process(rootElement);
|
var results = createPipeline().process(rootElement);
|
||||||
expect(results[2].inheritedProtoView).not.toBe(null);
|
expect(results[2].inheritedProtoView).not.toBe(null);
|
||||||
expect(results[2].inheritedProtoView).toBe(results[1].inheritedElementBinder.nestedProtoView);
|
expect(results[2].inheritedProtoView)
|
||||||
|
.toBe(results[1].inheritedElementBinder.nestedProtoView);
|
||||||
expect(results[2].inheritedProtoView.type).toBe(ProtoViewDto.EMBEDDED_VIEW_TYPE);
|
expect(results[2].inheritedProtoView.type).toBe(ProtoViewDto.EMBEDDED_VIEW_TYPE);
|
||||||
expect(DOM.getOuterHTML(results[2].inheritedProtoView.rootElement)).toEqual('<template>a</template>');
|
expect(DOM.getOuterHTML(results[2].inheritedProtoView.rootElement))
|
||||||
|
.toEqual('<template>a</template>');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -70,8 +73,9 @@ export function main() {
|
||||||
var originalChild = rootElement.childNodes[0];
|
var originalChild = rootElement.childNodes[0];
|
||||||
var results = createPipeline().process(rootElement);
|
var results = createPipeline().process(rootElement);
|
||||||
expect(results[0].element).toBe(rootElement);
|
expect(results[0].element).toBe(rootElement);
|
||||||
expect(DOM.getOuterHTML(results[0].element)).toEqual('<div><template class="ng-binding"></template></div>');
|
expect(DOM.getOuterHTML(results[0].element))
|
||||||
expect(DOM.getOuterHTML(results[2].element)).toEqual('<span template=""></span>')
|
.toEqual('<div><template class="ng-binding"></template></div>');
|
||||||
|
expect(DOM.getOuterHTML(results[2].element)).toEqual('<span template=""></span>');
|
||||||
expect(results[2].element).toBe(originalChild);
|
expect(results[2].element).toBe(originalChild);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -83,7 +87,8 @@ export function main() {
|
||||||
expect(results[0].element).toBe(rootElement);
|
expect(results[0].element).toBe(rootElement);
|
||||||
expect(results[0].isViewRoot).toBe(true);
|
expect(results[0].isViewRoot).toBe(true);
|
||||||
expect(results[2].isViewRoot).toBe(true);
|
expect(results[2].isViewRoot).toBe(true);
|
||||||
expect(DOM.getOuterHTML(results[0].element)).toEqual('<template><template class="ng-binding"></template></template>');
|
expect(DOM.getOuterHTML(results[0].element))
|
||||||
|
.toEqual('<template><template class="ng-binding"></template></template>');
|
||||||
expect(results[2].element).toBe(originalChild);
|
expect(results[2].element).toBe(originalChild);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -96,14 +101,17 @@ export function main() {
|
||||||
it('should add property bindings from the template attribute', () => {
|
it('should add property bindings from the template attribute', () => {
|
||||||
var rootElement = el('<div><div template="some-prop:expr"></div></div>');
|
var rootElement = el('<div><div template="some-prop:expr"></div></div>');
|
||||||
var results = createPipeline().process(rootElement);
|
var results = createPipeline().process(rootElement);
|
||||||
expect(MapWrapper.get(results[1].inheritedElementBinder.propertyBindings, 'someProp').source).toEqual('expr');
|
expect(
|
||||||
|
MapWrapper.get(results[1].inheritedElementBinder.propertyBindings, 'someProp').source)
|
||||||
|
.toEqual('expr');
|
||||||
expect(MapWrapper.get(results[1].attrs(), 'some-prop')).toEqual('expr');
|
expect(MapWrapper.get(results[1].attrs(), 'some-prop')).toEqual('expr');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add variable mappings from the template attribute to the nestedProtoView', () => {
|
it('should add variable mappings from the template attribute to the nestedProtoView', () => {
|
||||||
var rootElement = el('<div><div template="var var-name=mapName"></div></div>');
|
var rootElement = el('<div><div template="var var-name=mapName"></div></div>');
|
||||||
var results = createPipeline().process(rootElement);
|
var results = createPipeline().process(rootElement);
|
||||||
expect(results[2].inheritedProtoView.variableBindings).toEqual(MapWrapper.createFromStringMap({'mapName': 'varName'}));
|
expect(results[2].inheritedProtoView.variableBindings)
|
||||||
|
.toEqual(MapWrapper.createFromStringMap({'mapName': 'varName'}));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add entries without value as attributes to the element', () => {
|
it('should add entries without value as attributes to the element', () => {
|
||||||
|
@ -137,8 +145,10 @@ export function main() {
|
||||||
var rootElement = el('<div><span template=""></span></div>');
|
var rootElement = el('<div><span template=""></span></div>');
|
||||||
var results = createPipeline().process(rootElement);
|
var results = createPipeline().process(rootElement);
|
||||||
expect(results[2].inheritedProtoView).not.toBe(null);
|
expect(results[2].inheritedProtoView).not.toBe(null);
|
||||||
expect(results[2].inheritedProtoView).toBe(results[1].inheritedElementBinder.nestedProtoView);
|
expect(results[2].inheritedProtoView)
|
||||||
expect(DOM.getOuterHTML(results[2].inheritedProtoView.rootElement)).toEqual('<span template=""></span>');
|
.toBe(results[1].inheritedElementBinder.nestedProtoView);
|
||||||
|
expect(DOM.getOuterHTML(results[2].inheritedProtoView.rootElement))
|
||||||
|
.toEqual('<span template=""></span>');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -150,8 +160,9 @@ export function main() {
|
||||||
var originalChild = rootElement.childNodes[0];
|
var originalChild = rootElement.childNodes[0];
|
||||||
var results = createPipeline().process(rootElement);
|
var results = createPipeline().process(rootElement);
|
||||||
expect(results[0].element).toBe(rootElement);
|
expect(results[0].element).toBe(rootElement);
|
||||||
expect(DOM.getOuterHTML(results[0].element)).toEqual('<div><template class="ng-binding" ng-if=""></template></div>');
|
expect(DOM.getOuterHTML(results[0].element))
|
||||||
expect(DOM.getOuterHTML(results[2].element)).toEqual('<span *ng-if=""></span>')
|
.toEqual('<div><template class="ng-binding" ng-if=""></template></div>');
|
||||||
|
expect(DOM.getOuterHTML(results[2].element)).toEqual('<span *ng-if=""></span>');
|
||||||
expect(results[2].element).toBe(originalChild);
|
expect(results[2].element).toBe(originalChild);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -169,21 +180,24 @@ export function main() {
|
||||||
expect(results[0].element).toBe(rootElement);
|
expect(results[0].element).toBe(rootElement);
|
||||||
expect(results[0].isViewRoot).toBe(true);
|
expect(results[0].isViewRoot).toBe(true);
|
||||||
expect(results[2].isViewRoot).toBe(true);
|
expect(results[2].isViewRoot).toBe(true);
|
||||||
expect(DOM.getOuterHTML(results[0].element)).toEqual('<template><template class="ng-binding" foo=""></template></template>');
|
expect(DOM.getOuterHTML(results[0].element))
|
||||||
|
.toEqual('<template><template class="ng-binding" foo=""></template></template>');
|
||||||
expect(results[2].element).toBe(originalChild);
|
expect(results[2].element).toBe(originalChild);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add property bindings from the template attribute', () => {
|
it('should add property bindings from the template attribute', () => {
|
||||||
var rootElement = el('<div><div *prop="expr"></div></div>');
|
var rootElement = el('<div><div *prop="expr"></div></div>');
|
||||||
var results = createPipeline().process(rootElement);
|
var results = createPipeline().process(rootElement);
|
||||||
expect(MapWrapper.get(results[1].inheritedElementBinder.propertyBindings, 'prop').source).toEqual('expr');
|
expect(MapWrapper.get(results[1].inheritedElementBinder.propertyBindings, 'prop').source)
|
||||||
|
.toEqual('expr');
|
||||||
expect(MapWrapper.get(results[1].attrs(), 'prop')).toEqual('expr');
|
expect(MapWrapper.get(results[1].attrs(), 'prop')).toEqual('expr');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add variable mappings from the template attribute to the nestedProtoView', () => {
|
it('should add variable mappings from the template attribute to the nestedProtoView', () => {
|
||||||
var rootElement = el('<div><div *foreach="var varName=mapName"></div></div>');
|
var rootElement = el('<div><div *foreach="var varName=mapName"></div></div>');
|
||||||
var results = createPipeline().process(rootElement);
|
var results = createPipeline().process(rootElement);
|
||||||
expect(results[2].inheritedProtoView.variableBindings).toEqual(MapWrapper.createFromStringMap({'mapName': 'varName'}));
|
expect(results[2].inheritedProtoView.variableBindings)
|
||||||
|
.toEqual(MapWrapper.createFromStringMap({'mapName': 'varName'}));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add entries without value as attribute to the element', () => {
|
it('should add entries without value as attribute to the element', () => {
|
||||||
|
@ -217,8 +231,10 @@ export function main() {
|
||||||
var rootElement = el('<div><span *foo></span></div>');
|
var rootElement = el('<div><span *foo></span></div>');
|
||||||
var results = createPipeline().process(rootElement);
|
var results = createPipeline().process(rootElement);
|
||||||
expect(results[2].inheritedProtoView).not.toBe(null);
|
expect(results[2].inheritedProtoView).not.toBe(null);
|
||||||
expect(results[2].inheritedProtoView).toBe(results[1].inheritedElementBinder.nestedProtoView);
|
expect(results[2].inheritedProtoView)
|
||||||
expect(DOM.getOuterHTML(results[2].inheritedProtoView.rootElement)).toEqual('<span *foo=""></span>');
|
.toBe(results[1].inheritedElementBinder.nestedProtoView);
|
||||||
|
expect(DOM.getOuterHTML(results[2].inheritedProtoView.rootElement))
|
||||||
|
.toEqual('<span *foo=""></span>');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
|
@ -1,7 +1,6 @@
|
||||||
import {MapWrapper} from 'angular2/src/facade/collection';
|
import {MapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {DirectiveMetadata} from 'angular2/src/render/api';
|
import {DirectiveMetadata} from 'angular2/src/render/api';
|
||||||
import {directiveMetadataFromMap, directiveMetadataToMap} from
|
import {directiveMetadataFromMap, directiveMetadataToMap} from 'angular2/src/render/dom/convert';
|
||||||
'angular2/src/render/dom/convert';
|
|
||||||
import {ddescribe, describe, expect, it} from 'angular2/test_lib';
|
import {ddescribe, describe, expect, it} from 'angular2/test_lib';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
|
@ -10,10 +9,8 @@ export function main() {
|
||||||
var someComponent = new DirectiveMetadata({
|
var someComponent = new DirectiveMetadata({
|
||||||
compileChildren: false,
|
compileChildren: false,
|
||||||
hostListeners: MapWrapper.createFromPairs([['listenKey', 'listenVal']]),
|
hostListeners: MapWrapper.createFromPairs([['listenKey', 'listenVal']]),
|
||||||
hostProperties:
|
hostProperties: MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]),
|
||||||
MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]),
|
hostActions: MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]),
|
||||||
hostActions:
|
|
||||||
MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]),
|
|
||||||
id: 'someComponent',
|
id: 'someComponent',
|
||||||
properties: MapWrapper.createFromPairs([['propKey', 'propVal']]),
|
properties: MapWrapper.createFromPairs([['propKey', 'propVal']]),
|
||||||
readAttributes: ['read1', 'read2'],
|
readAttributes: ['read1', 'read2'],
|
||||||
|
@ -22,29 +19,26 @@ export function main() {
|
||||||
});
|
});
|
||||||
var map = directiveMetadataToMap(someComponent);
|
var map = directiveMetadataToMap(someComponent);
|
||||||
expect(MapWrapper.get(map, 'compileChildren')).toEqual(false);
|
expect(MapWrapper.get(map, 'compileChildren')).toEqual(false);
|
||||||
expect(MapWrapper.get(map, 'hostListeners')).toEqual(
|
expect(MapWrapper.get(map, 'hostListeners'))
|
||||||
MapWrapper.createFromPairs([['listenKey', 'listenVal']]));
|
.toEqual(MapWrapper.createFromPairs([['listenKey', 'listenVal']]));
|
||||||
expect(MapWrapper.get(map, 'hostProperties')).toEqual(
|
expect(MapWrapper.get(map, 'hostProperties'))
|
||||||
MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]));
|
.toEqual(MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]));
|
||||||
expect(MapWrapper.get(map, 'hostActions')).toEqual(
|
expect(MapWrapper.get(map, 'hostActions'))
|
||||||
MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]));
|
.toEqual(MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]));
|
||||||
expect(MapWrapper.get(map, 'id')).toEqual('someComponent');
|
expect(MapWrapper.get(map, 'id')).toEqual('someComponent');
|
||||||
expect(MapWrapper.get(map, 'properties')).toEqual(
|
expect(MapWrapper.get(map, 'properties'))
|
||||||
MapWrapper.createFromPairs([['propKey', 'propVal']]));
|
.toEqual(MapWrapper.createFromPairs([['propKey', 'propVal']]));
|
||||||
expect(MapWrapper.get(map, 'readAttributes')).toEqual(['read1', 'read2']);
|
expect(MapWrapper.get(map, 'readAttributes')).toEqual(['read1', 'read2']);
|
||||||
expect(MapWrapper.get(map, 'selector')).toEqual('some-comp');
|
expect(MapWrapper.get(map, 'selector')).toEqual('some-comp');
|
||||||
expect(MapWrapper.get(map, 'type')).toEqual(
|
expect(MapWrapper.get(map, 'type')).toEqual(DirectiveMetadata.COMPONENT_TYPE);
|
||||||
DirectiveMetadata.COMPONENT_TYPE);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('mapToDirectiveMetadata', () => {
|
it('mapToDirectiveMetadata', () => {
|
||||||
var map = MapWrapper.createFromPairs([
|
var map = MapWrapper.createFromPairs([
|
||||||
['compileChildren', false],
|
['compileChildren', false],
|
||||||
['hostListeners', MapWrapper.createFromPairs([['testKey', 'testVal']])],
|
['hostListeners', MapWrapper.createFromPairs([['testKey', 'testVal']])],
|
||||||
['hostProperties',
|
['hostProperties', MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']])],
|
||||||
MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']])],
|
['hostActions', MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']])],
|
||||||
['hostActions',
|
|
||||||
MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']])],
|
|
||||||
['id', 'testId'],
|
['id', 'testId'],
|
||||||
['properties', MapWrapper.createFromPairs([['propKey', 'propVal']])],
|
['properties', MapWrapper.createFromPairs([['propKey', 'propVal']])],
|
||||||
['readAttributes', ['readTest1', 'readTest2']],
|
['readAttributes', ['readTest1', 'readTest2']],
|
||||||
|
@ -53,15 +47,13 @@ export function main() {
|
||||||
]);
|
]);
|
||||||
var meta = directiveMetadataFromMap(map);
|
var meta = directiveMetadataFromMap(map);
|
||||||
expect(meta.compileChildren).toEqual(false);
|
expect(meta.compileChildren).toEqual(false);
|
||||||
expect(meta.hostListeners).toEqual(
|
expect(meta.hostListeners).toEqual(MapWrapper.createFromPairs([['testKey', 'testVal']]));
|
||||||
MapWrapper.createFromPairs([['testKey', 'testVal']]));
|
expect(meta.hostProperties)
|
||||||
expect(meta.hostProperties).toEqual(
|
.toEqual(MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]));
|
||||||
MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]));
|
expect(meta.hostActions)
|
||||||
expect(meta.hostActions).toEqual(
|
.toEqual(MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]));
|
||||||
MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]));
|
|
||||||
expect(meta.id).toEqual('testId');
|
expect(meta.id).toEqual('testId');
|
||||||
expect(meta.properties).toEqual(
|
expect(meta.properties).toEqual(MapWrapper.createFromPairs([['propKey', 'propVal']]));
|
||||||
MapWrapper.createFromPairs([['propKey', 'propVal']]));
|
|
||||||
expect(meta.readAttributes).toEqual(['readTest1', 'readTest2']);
|
expect(meta.readAttributes).toEqual(['readTest1', 'readTest2']);
|
||||||
expect(meta.selector).toEqual('testSelector');
|
expect(meta.selector).toEqual('testSelector');
|
||||||
expect(meta.type).toEqual(DirectiveMetadata.DIRECTIVE_TYPE);
|
expect(meta.type).toEqual(DirectiveMetadata.DIRECTIVE_TYPE);
|
|
@ -1,197 +0,0 @@
|
||||||
import {
|
|
||||||
AsyncTestCompleter,
|
|
||||||
beforeEach,
|
|
||||||
ddescribe,
|
|
||||||
describe,
|
|
||||||
el,
|
|
||||||
elementText,
|
|
||||||
expect,
|
|
||||||
iit,
|
|
||||||
inject,
|
|
||||||
it,
|
|
||||||
xit,
|
|
||||||
beforeEachBindings,
|
|
||||||
SpyObject,
|
|
||||||
} from 'angular2/test_lib';
|
|
||||||
|
|
||||||
import {MapWrapper} from 'angular2/src/facade/collection';
|
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
|
||||||
|
|
||||||
import {DomTestbed, TestView} from './dom_testbed';
|
|
||||||
|
|
||||||
import {ViewDefinition, DirectiveMetadata, RenderViewRef} from 'angular2/src/render/api';
|
|
||||||
|
|
||||||
export function main() {
|
|
||||||
describe('DomRenderer integration', () => {
|
|
||||||
beforeEachBindings(() => [
|
|
||||||
DomTestbed
|
|
||||||
]);
|
|
||||||
|
|
||||||
it('should create and destroy root host views while using the given elements in place',
|
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compiler.compileHost(someComponent).then( (hostProtoViewDto) => {
|
|
||||||
var view = new TestView(tb.renderer.createRootHostView(hostProtoViewDto.render, '#root'));
|
|
||||||
expect(view.rawView.rootNodes[0]).toEqual(tb.rootEl);
|
|
||||||
|
|
||||||
tb.renderer.destroyView(view.viewRef);
|
|
||||||
// destroying a root view should not disconnect it!
|
|
||||||
expect(tb.rootEl.parentNode).toBeTruthy();
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should create and destroy free host views',
|
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compiler.compileHost(someComponent).then( (hostProtoViewDto) => {
|
|
||||||
var view = new TestView(tb.renderer.createView(hostProtoViewDto.render));
|
|
||||||
var hostElement = tb.renderer.getHostElement(view.viewRef);
|
|
||||||
DOM.appendChild(tb.rootEl, hostElement);
|
|
||||||
|
|
||||||
tb.renderer.detachFreeHostView(null, view.viewRef);
|
|
||||||
expect(DOM.parentElement(hostElement)).toBeFalsy();
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should attach and detach component views',
|
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([
|
|
||||||
someComponent,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'someComponent',
|
|
||||||
template: 'hello',
|
|
||||||
directives: []
|
|
||||||
})
|
|
||||||
]).then( (protoViewDtos) => {
|
|
||||||
var rootView = tb.createRootView(protoViewDtos[0]);
|
|
||||||
var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]);
|
|
||||||
expect(tb.rootEl).toHaveText('hello');
|
|
||||||
tb.destroyComponentView(rootView.viewRef, 0, cmpView.viewRef);
|
|
||||||
expect(tb.rootEl).toHaveText('');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should update text nodes',
|
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([someComponent,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'someComponent',
|
|
||||||
template: '{{a}}',
|
|
||||||
directives: []
|
|
||||||
})
|
|
||||||
]).then( (protoViewDtos) => {
|
|
||||||
var rootView = tb.createRootView(protoViewDtos[0]);
|
|
||||||
var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]);
|
|
||||||
|
|
||||||
tb.renderer.setText(cmpView.viewRef, 0, 'hello');
|
|
||||||
expect(tb.rootEl).toHaveText('hello');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should update element properties',
|
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([someComponent,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'someComponent',
|
|
||||||
template: '<input [value]="someProp">asdf',
|
|
||||||
directives: []
|
|
||||||
})
|
|
||||||
]).then( (protoViewDtos) => {
|
|
||||||
var rootView = tb.createRootView(protoViewDtos[0]);
|
|
||||||
var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]);
|
|
||||||
|
|
||||||
tb.renderer.setElementProperty(cmpView.viewRef, 0, 'value', 'hello');
|
|
||||||
expect(DOM.childNodes(tb.rootEl)[0].value).toEqual('hello');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should call actions on the element',
|
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([someComponent,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'someComponent',
|
|
||||||
template: '<input with-host-actions></input>',
|
|
||||||
directives: [directiveWithHostActions]
|
|
||||||
})
|
|
||||||
]).then( (protoViewDtos) => {
|
|
||||||
var views = tb.createRootViews(protoViewDtos);
|
|
||||||
var componentView = views[1];
|
|
||||||
|
|
||||||
tb.renderer.callAction(componentView.viewRef, 0, 'value = "val"', null);
|
|
||||||
|
|
||||||
expect(DOM.getValue(DOM.childNodes(tb.rootEl)[0])).toEqual('val');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('should add and remove views to and from containers',
|
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([someComponent,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'someComponent',
|
|
||||||
template: '<template>hello</template>',
|
|
||||||
directives: []
|
|
||||||
})
|
|
||||||
]).then( (protoViewDtos) => {
|
|
||||||
var rootView = tb.createRootView(protoViewDtos[0]);
|
|
||||||
var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]);
|
|
||||||
|
|
||||||
var childProto = protoViewDtos[1].elementBinders[0].nestedProtoView;
|
|
||||||
expect(tb.rootEl).toHaveText('');
|
|
||||||
var childView = tb.createViewInContainer(cmpView.viewRef, 0, 0, childProto);
|
|
||||||
expect(tb.rootEl).toHaveText('hello');
|
|
||||||
tb.destroyViewInContainer(cmpView.viewRef, 0, 0, childView.viewRef);
|
|
||||||
expect(tb.rootEl).toHaveText('');
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should handle events',
|
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([someComponent,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'someComponent',
|
|
||||||
template: '<input (change)="doSomething()">',
|
|
||||||
directives: []
|
|
||||||
})
|
|
||||||
]).then( (protoViewDtos) => {
|
|
||||||
var rootView = tb.createRootView(protoViewDtos[0]);
|
|
||||||
var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]);
|
|
||||||
|
|
||||||
tb.triggerEvent(cmpView.viewRef, 0, 'change');
|
|
||||||
var eventEntry = cmpView.events[0];
|
|
||||||
// bound element index
|
|
||||||
expect(eventEntry[0]).toEqual(0);
|
|
||||||
// event type
|
|
||||||
expect(eventEntry[1]).toEqual('change');
|
|
||||||
// actual event
|
|
||||||
expect(MapWrapper.get(eventEntry[2], '$event').type).toEqual('change');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var someComponent = new DirectiveMetadata({
|
|
||||||
id: 'someComponent',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE,
|
|
||||||
selector: 'some-comp'
|
|
||||||
});
|
|
||||||
|
|
||||||
var directiveWithHostActions = new DirectiveMetadata({
|
|
||||||
id: 'withHostActions',
|
|
||||||
type: DirectiveMetadata.DIRECTIVE_TYPE,
|
|
||||||
selector: '[with-host-actions]',
|
|
||||||
hostActions: MapWrapper.createFromStringMap({
|
|
||||||
'setValue' : 'value = "val"'
|
|
||||||
})
|
|
||||||
});
|
|
|
@ -0,0 +1,194 @@
|
||||||
|
import {
|
||||||
|
AsyncTestCompleter,
|
||||||
|
beforeEach,
|
||||||
|
ddescribe,
|
||||||
|
describe,
|
||||||
|
el,
|
||||||
|
expect,
|
||||||
|
iit,
|
||||||
|
inject,
|
||||||
|
it,
|
||||||
|
xit,
|
||||||
|
beforeEachBindings,
|
||||||
|
SpyObject,
|
||||||
|
} from 'angular2/test_lib';
|
||||||
|
|
||||||
|
import {MapWrapper} from 'angular2/src/facade/collection';
|
||||||
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
|
|
||||||
|
import {DomTestbed, TestView} from './dom_testbed';
|
||||||
|
|
||||||
|
import {ViewDefinition, DirectiveMetadata, RenderViewRef} from 'angular2/src/render/api';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe('DomRenderer integration', () => {
|
||||||
|
beforeEachBindings(() => [DomTestbed]);
|
||||||
|
|
||||||
|
it('should create and destroy root host views while using the given elements in place',
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compiler.compileHost(someComponent)
|
||||||
|
.then((hostProtoViewDto) => {
|
||||||
|
var view =
|
||||||
|
new TestView(tb.renderer.createRootHostView(hostProtoViewDto.render, '#root'));
|
||||||
|
expect(view.rawView.rootNodes[0]).toEqual(tb.rootEl);
|
||||||
|
|
||||||
|
tb.renderer.destroyView(view.viewRef);
|
||||||
|
// destroying a root view should not disconnect it!
|
||||||
|
expect(tb.rootEl.parentNode).toBeTruthy();
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should create and destroy free host views',
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compiler.compileHost(someComponent)
|
||||||
|
.then((hostProtoViewDto) => {
|
||||||
|
var view = new TestView(tb.renderer.createView(hostProtoViewDto.render));
|
||||||
|
var hostElement = tb.renderer.getHostElement(view.viewRef);
|
||||||
|
DOM.appendChild(tb.rootEl, hostElement);
|
||||||
|
|
||||||
|
tb.renderer.detachFreeHostView(null, view.viewRef);
|
||||||
|
expect(DOM.parentElement(hostElement)).toBeFalsy();
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should attach and detach component views',
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
someComponent,
|
||||||
|
new ViewDefinition(
|
||||||
|
{componentId: 'someComponent', template: 'hello', directives: []})
|
||||||
|
])
|
||||||
|
.then((protoViewDtos) => {
|
||||||
|
var rootView = tb.createRootView(protoViewDtos[0]);
|
||||||
|
var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]);
|
||||||
|
expect(tb.rootEl).toHaveText('hello');
|
||||||
|
tb.destroyComponentView(rootView.viewRef, 0, cmpView.viewRef);
|
||||||
|
expect(tb.rootEl).toHaveText('');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should update text nodes', inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
someComponent,
|
||||||
|
new ViewDefinition(
|
||||||
|
{componentId: 'someComponent', template: '{{a}}', directives: []})
|
||||||
|
])
|
||||||
|
.then((protoViewDtos) => {
|
||||||
|
var rootView = tb.createRootView(protoViewDtos[0]);
|
||||||
|
var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]);
|
||||||
|
|
||||||
|
tb.renderer.setText(cmpView.viewRef, 0, 'hello');
|
||||||
|
expect(tb.rootEl).toHaveText('hello');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should update element properties', inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
someComponent,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'someComponent',
|
||||||
|
template: '<input [value]="someProp">asdf',
|
||||||
|
directives: []
|
||||||
|
})
|
||||||
|
])
|
||||||
|
.then((protoViewDtos) => {
|
||||||
|
var rootView = tb.createRootView(protoViewDtos[0]);
|
||||||
|
var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]);
|
||||||
|
|
||||||
|
tb.renderer.setElementProperty(cmpView.viewRef, 0, 'value', 'hello');
|
||||||
|
expect(DOM.childNodes(tb.rootEl)[0].value).toEqual('hello');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should call actions on the element',
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
someComponent,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'someComponent',
|
||||||
|
template: '<input with-host-actions></input>',
|
||||||
|
directives: [directiveWithHostActions]
|
||||||
|
})
|
||||||
|
])
|
||||||
|
.then((protoViewDtos) => {
|
||||||
|
var views = tb.createRootViews(protoViewDtos);
|
||||||
|
var componentView = views[1];
|
||||||
|
|
||||||
|
tb.renderer.callAction(componentView.viewRef, 0, 'value = "val"', null);
|
||||||
|
|
||||||
|
expect(DOM.getValue(DOM.childNodes(tb.rootEl)[0])).toEqual('val');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it('should add and remove views to and from containers',
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
someComponent,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'someComponent',
|
||||||
|
template: '<template>hello</template>',
|
||||||
|
directives: []
|
||||||
|
})
|
||||||
|
])
|
||||||
|
.then((protoViewDtos) => {
|
||||||
|
var rootView = tb.createRootView(protoViewDtos[0]);
|
||||||
|
var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]);
|
||||||
|
|
||||||
|
var childProto = protoViewDtos[1].elementBinders[0].nestedProtoView;
|
||||||
|
expect(tb.rootEl).toHaveText('');
|
||||||
|
var childView = tb.createViewInContainer(cmpView.viewRef, 0, 0, childProto);
|
||||||
|
expect(tb.rootEl).toHaveText('hello');
|
||||||
|
tb.destroyViewInContainer(cmpView.viewRef, 0, 0, childView.viewRef);
|
||||||
|
expect(tb.rootEl).toHaveText('');
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should handle events', inject([AsyncTestCompleter, DomTestbed], (async, tb: DomTestbed) => {
|
||||||
|
tb.compileAll([
|
||||||
|
someComponent,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'someComponent',
|
||||||
|
template: '<input (change)="doSomething()">',
|
||||||
|
directives: []
|
||||||
|
})
|
||||||
|
])
|
||||||
|
.then((protoViewDtos) => {
|
||||||
|
var rootView = tb.createRootView(protoViewDtos[0]);
|
||||||
|
var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]);
|
||||||
|
|
||||||
|
tb.triggerEvent(cmpView.viewRef, 0, 'change');
|
||||||
|
var eventEntry = cmpView.events[0];
|
||||||
|
// bound element index
|
||||||
|
expect(eventEntry[0]).toEqual(0);
|
||||||
|
// event type
|
||||||
|
expect(eventEntry[1]).toEqual('change');
|
||||||
|
// actual event
|
||||||
|
expect((<any>MapWrapper.get(eventEntry[2], '$event')).type).toEqual('change');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var someComponent = new DirectiveMetadata(
|
||||||
|
{id: 'someComponent', type: DirectiveMetadata.COMPONENT_TYPE, selector: 'some-comp'});
|
||||||
|
|
||||||
|
var directiveWithHostActions = new DirectiveMetadata({
|
||||||
|
id: 'withHostActions',
|
||||||
|
type: DirectiveMetadata.DIRECTIVE_TYPE,
|
||||||
|
selector: '[with-host-actions]',
|
||||||
|
hostActions: MapWrapper.createFromStringMap({'setValue': 'value = "val"'})
|
||||||
|
});
|
|
@ -1,4 +1,4 @@
|
||||||
import {Inject, Injectable} from 'angular2/src/di/annotations_impl';
|
import {Inject, Injectable} from 'angular2/di';
|
||||||
import {MapWrapper, ListWrapper, List, Map} from 'angular2/src/facade/collection';
|
import {MapWrapper, ListWrapper, List, Map} from 'angular2/src/facade/collection';
|
||||||
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
|
@ -6,16 +6,22 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {DomRenderer, DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer';
|
import {DomRenderer, DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer';
|
||||||
import {DefaultDomCompiler} from 'angular2/src/render/dom/compiler/compiler';
|
import {DefaultDomCompiler} from 'angular2/src/render/dom/compiler/compiler';
|
||||||
import {DomView} from 'angular2/src/render/dom/view/view';
|
import {DomView} from 'angular2/src/render/dom/view/view';
|
||||||
import {RenderViewRef, ProtoViewDto, ViewDefinition, EventDispatcher, DirectiveMetadata} from 'angular2/src/render/api';
|
import {
|
||||||
|
RenderViewRef,
|
||||||
|
ProtoViewDto,
|
||||||
|
ViewDefinition,
|
||||||
|
EventDispatcher,
|
||||||
|
DirectiveMetadata
|
||||||
|
} from 'angular2/src/render/api';
|
||||||
import {resolveInternalDomView} from 'angular2/src/render/dom/view/view';
|
import {resolveInternalDomView} from 'angular2/src/render/dom/view/view';
|
||||||
import {el, dispatchEvent} from 'angular2/test_lib';
|
import {el, dispatchEvent} from 'angular2/test_lib';
|
||||||
|
|
||||||
export class TestView {
|
export class TestView {
|
||||||
rawView:DomView;
|
rawView: DomView;
|
||||||
viewRef:RenderViewRef;
|
viewRef: RenderViewRef;
|
||||||
events:List;
|
events: List<List<any>>;
|
||||||
|
|
||||||
constructor(viewRef:RenderViewRef) {
|
constructor(viewRef: RenderViewRef) {
|
||||||
this.viewRef = viewRef;
|
this.viewRef = viewRef;
|
||||||
this.rawView = resolveInternalDomView(viewRef);
|
this.rawView = resolveInternalDomView(viewRef);
|
||||||
this.events = [];
|
this.events = [];
|
||||||
|
@ -23,17 +29,12 @@ export class TestView {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@IMPLEMENTS(EventDispatcher)
|
class LoggingEventDispatcher implements EventDispatcher {
|
||||||
class LoggingEventDispatcher {
|
log: List<List<any>>;
|
||||||
log:List;
|
|
||||||
|
|
||||||
constructor(log:List) {
|
constructor(log: List<List<any>>) { this.log = log; }
|
||||||
this.log = log;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatchEvent(
|
dispatchEvent(elementIndex: number, eventName: string, locals: Map<string, any>) {
|
||||||
elementIndex:number, eventName:string, locals:Map<string, any>
|
|
||||||
) {
|
|
||||||
ListWrapper.push(this.log, [elementIndex, eventName, locals]);
|
ListWrapper.push(this.log, [elementIndex, eventName, locals]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -42,84 +43,87 @@ class LoggingEventDispatcher {
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DomTestbed {
|
export class DomTestbed {
|
||||||
renderer:DomRenderer;
|
renderer: DomRenderer;
|
||||||
compiler:DefaultDomCompiler;
|
compiler: DefaultDomCompiler;
|
||||||
rootEl;
|
rootEl;
|
||||||
|
|
||||||
constructor(renderer:DomRenderer, compiler:DefaultDomCompiler, @Inject(DOCUMENT_TOKEN) document) {
|
constructor(renderer: DomRenderer, compiler: DefaultDomCompiler,
|
||||||
|
@Inject(DOCUMENT_TOKEN) document) {
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
this.compiler = compiler;
|
this.compiler = compiler;
|
||||||
this.rootEl = el('<div id="root"></div>');
|
this.rootEl = el('<div id="root"></div>');
|
||||||
var oldRoots = DOM.querySelectorAll(document, '#root');
|
var oldRoots = DOM.querySelectorAll(document, '#root');
|
||||||
for (var i=0; i<oldRoots.length; i++) {
|
for (var i = 0; i < oldRoots.length; i++) {
|
||||||
DOM.remove(oldRoots[i]);
|
DOM.remove(oldRoots[i]);
|
||||||
}
|
}
|
||||||
DOM.appendChild(DOM.querySelector(document, 'body'), this.rootEl);
|
DOM.appendChild(DOM.querySelector(document, 'body'), this.rootEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileAll(directivesOrViewDefinitions:List):Promise<List<ProtoViewDto>> {
|
compileAll(directivesOrViewDefinitions: List<DirectiveMetadata |
|
||||||
return PromiseWrapper.all(
|
ViewDefinition>): Promise<List<ProtoViewDto>> {
|
||||||
ListWrapper.map(directivesOrViewDefinitions, (entry) => {
|
return PromiseWrapper.all(ListWrapper.map(directivesOrViewDefinitions, (entry) => {
|
||||||
if (entry instanceof DirectiveMetadata) {
|
if (entry instanceof DirectiveMetadata) {
|
||||||
return this.compiler.compileHost(entry);
|
return this.compiler.compileHost(entry);
|
||||||
} else {
|
} else {
|
||||||
return this.compiler.compile(entry);
|
return this.compiler.compile(entry);
|
||||||
}
|
}
|
||||||
})
|
}));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_createTestView(viewRef:RenderViewRef) {
|
_createTestView(viewRef: RenderViewRef) {
|
||||||
var testView = new TestView(viewRef);
|
var testView = new TestView(viewRef);
|
||||||
this.renderer.setEventDispatcher(viewRef, new LoggingEventDispatcher(testView.events));
|
this.renderer.setEventDispatcher(viewRef, new LoggingEventDispatcher(testView.events));
|
||||||
return testView;
|
return testView;
|
||||||
}
|
}
|
||||||
|
|
||||||
createRootView(rootProtoView:ProtoViewDto):TestView {
|
createRootView(rootProtoView: ProtoViewDto): TestView {
|
||||||
var viewRef = this.renderer.createRootHostView(rootProtoView.render, '#root');
|
var viewRef = this.renderer.createRootHostView(rootProtoView.render, '#root');
|
||||||
this.renderer.hydrateView(viewRef);
|
this.renderer.hydrateView(viewRef);
|
||||||
return this._createTestView(viewRef);
|
return this._createTestView(viewRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
createComponentView(parentViewRef:RenderViewRef, boundElementIndex:number, componentProtoView:ProtoViewDto):TestView {
|
createComponentView(parentViewRef: RenderViewRef, boundElementIndex: number,
|
||||||
|
componentProtoView: ProtoViewDto): TestView {
|
||||||
var componentViewRef = this.renderer.createView(componentProtoView.render);
|
var componentViewRef = this.renderer.createView(componentProtoView.render);
|
||||||
this.renderer.attachComponentView(parentViewRef, boundElementIndex, componentViewRef);
|
this.renderer.attachComponentView(parentViewRef, boundElementIndex, componentViewRef);
|
||||||
this.renderer.hydrateView(componentViewRef);
|
this.renderer.hydrateView(componentViewRef);
|
||||||
return this._createTestView(componentViewRef);
|
return this._createTestView(componentViewRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
createRootViews(protoViews:List<ProtoViewDto>):List<TestView> {
|
createRootViews(protoViews: List<ProtoViewDto>): List<TestView> {
|
||||||
var views = [];
|
var views = [];
|
||||||
var lastView = this.createRootView(protoViews[0]);
|
var lastView = this.createRootView(protoViews[0]);
|
||||||
ListWrapper.push(views, lastView);
|
ListWrapper.push(views, lastView);
|
||||||
for (var i=1; i<protoViews.length; i++) {
|
for (var i = 1; i < protoViews.length; i++) {
|
||||||
lastView = this.createComponentView(lastView.viewRef, 0, protoViews[i]);
|
lastView = this.createComponentView(lastView.viewRef, 0, protoViews[i]);
|
||||||
ListWrapper.push(views, lastView);
|
ListWrapper.push(views, lastView);
|
||||||
}
|
}
|
||||||
return views;
|
return views;
|
||||||
}
|
}
|
||||||
|
|
||||||
destroyComponentView(parentViewRef:RenderViewRef, boundElementIndex:number, componentView:RenderViewRef) {
|
destroyComponentView(parentViewRef: RenderViewRef, boundElementIndex: number,
|
||||||
|
componentView: RenderViewRef) {
|
||||||
this.renderer.dehydrateView(componentView);
|
this.renderer.dehydrateView(componentView);
|
||||||
this.renderer.detachComponentView(parentViewRef, boundElementIndex, componentView);
|
this.renderer.detachComponentView(parentViewRef, boundElementIndex, componentView);
|
||||||
}
|
}
|
||||||
|
|
||||||
createViewInContainer(parentViewRef:RenderViewRef, boundElementIndex:number, atIndex:number, protoView:ProtoViewDto):TestView {
|
createViewInContainer(parentViewRef: RenderViewRef, boundElementIndex: number, atIndex: number,
|
||||||
|
protoView: ProtoViewDto): TestView {
|
||||||
var viewRef = this.renderer.createView(protoView.render);
|
var viewRef = this.renderer.createView(protoView.render);
|
||||||
this.renderer.attachViewInContainer(parentViewRef, boundElementIndex, atIndex, viewRef);
|
this.renderer.attachViewInContainer(parentViewRef, boundElementIndex, atIndex, viewRef);
|
||||||
this.renderer.hydrateView(viewRef);
|
this.renderer.hydrateView(viewRef);
|
||||||
return this._createTestView(viewRef);
|
return this._createTestView(viewRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
destroyViewInContainer(parentViewRef:RenderViewRef, boundElementIndex:number, atIndex:number, viewRef:RenderViewRef) {
|
destroyViewInContainer(parentViewRef: RenderViewRef, boundElementIndex: number, atIndex: number,
|
||||||
|
viewRef: RenderViewRef) {
|
||||||
this.renderer.dehydrateView(viewRef);
|
this.renderer.dehydrateView(viewRef);
|
||||||
this.renderer.detachViewInContainer(parentViewRef, boundElementIndex, atIndex, viewRef);
|
this.renderer.detachViewInContainer(parentViewRef, boundElementIndex, atIndex, viewRef);
|
||||||
this.renderer.destroyView(viewRef);
|
this.renderer.destroyView(viewRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
triggerEvent(viewRef:RenderViewRef, boundElementIndex:number, eventName:string) {
|
triggerEvent(viewRef: RenderViewRef, boundElementIndex: number, eventName: string) {
|
||||||
var element = resolveInternalDomView(viewRef).boundElements[boundElementIndex];
|
var element = resolveInternalDomView(viewRef).boundElements[boundElementIndex];
|
||||||
dispatchEvent(element, eventName);
|
dispatchEvent(element, eventName);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,19 @@
|
||||||
import {describe, ddescribe, it, iit, xit, xdescribe, expect, beforeEach, el} from 'angular2/test_lib';
|
import {
|
||||||
import {EventManager, EventManagerPlugin, DomEventsPlugin} from 'angular2/src/render/dom/events/event_manager';
|
describe,
|
||||||
|
ddescribe,
|
||||||
|
it,
|
||||||
|
iit,
|
||||||
|
xit,
|
||||||
|
xdescribe,
|
||||||
|
expect,
|
||||||
|
beforeEach,
|
||||||
|
el
|
||||||
|
} from 'angular2/test_lib';
|
||||||
|
import {
|
||||||
|
EventManager,
|
||||||
|
EventManagerPlugin,
|
||||||
|
DomEventsPlugin
|
||||||
|
} from 'angular2/src/render/dom/events/event_manager';
|
||||||
import {NgZone} from 'angular2/src/core/zone/ng_zone';
|
import {NgZone} from 'angular2/src/core/zone/ng_zone';
|
||||||
import {List, ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
|
@ -7,9 +21,7 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
export function main() {
|
export function main() {
|
||||||
var domEventPlugin;
|
var domEventPlugin;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => { domEventPlugin = new DomEventsPlugin(); });
|
||||||
domEventPlugin = new DomEventsPlugin();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('EventManager', () => {
|
describe('EventManager', () => {
|
||||||
|
|
||||||
|
@ -35,7 +47,7 @@ export function main() {
|
||||||
var element = el('<div></div>');
|
var element = el('<div></div>');
|
||||||
var clickHandler = (e) => e;
|
var clickHandler = (e) => e;
|
||||||
var dblClickHandler = (e) => e;
|
var dblClickHandler = (e) => e;
|
||||||
var plugin1= new FakeEventManagerPlugin(['dblclick']);
|
var plugin1 = new FakeEventManagerPlugin(['dblclick']);
|
||||||
var plugin2 = new FakeEventManagerPlugin(['click', 'dblclick']);
|
var plugin2 = new FakeEventManagerPlugin(['click', 'dblclick']);
|
||||||
var manager = new EventManager([plugin1, plugin2], new FakeNgZone());
|
var manager = new EventManager([plugin1, plugin2], new FakeNgZone());
|
||||||
manager.addEventListener(element, 'click', clickHandler);
|
manager.addEventListener(element, 'click', clickHandler);
|
||||||
|
@ -51,7 +63,7 @@ export function main() {
|
||||||
var plugin = new FakeEventManagerPlugin(['dblclick']);
|
var plugin = new FakeEventManagerPlugin(['dblclick']);
|
||||||
var manager = new EventManager([plugin], new FakeNgZone());
|
var manager = new EventManager([plugin], new FakeNgZone());
|
||||||
expect(() => manager.addEventListener(element, 'click', null))
|
expect(() => manager.addEventListener(element, 'click', null))
|
||||||
.toThrowError('No event manager plugin found for event click');
|
.toThrowError('No event manager plugin found for event click');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('by default events are only caught on same element', () => {
|
it('by default events are only caught on same element', () => {
|
||||||
|
@ -109,8 +121,8 @@ export function main() {
|
||||||
|
|
||||||
class FakeEventManagerPlugin extends EventManagerPlugin {
|
class FakeEventManagerPlugin extends EventManagerPlugin {
|
||||||
_supports: List<string>;
|
_supports: List<string>;
|
||||||
_nonBubbleEventHandlers: Map;
|
_nonBubbleEventHandlers: Map<string, Function>;
|
||||||
_bubbleEventHandlers: Map;
|
_bubbleEventHandlers: Map<string, Function>;
|
||||||
constructor(supports: List<string>) {
|
constructor(supports: List<string>) {
|
||||||
super();
|
super();
|
||||||
this._supports = supports;
|
this._supports = supports;
|
||||||
|
@ -118,28 +130,22 @@ class FakeEventManagerPlugin extends EventManagerPlugin {
|
||||||
this._bubbleEventHandlers = MapWrapper.create();
|
this._bubbleEventHandlers = MapWrapper.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
supports(eventName: string): boolean {
|
supports(eventName: string): boolean { return ListWrapper.contains(this._supports, eventName); }
|
||||||
return ListWrapper.contains(this._supports, eventName);
|
|
||||||
}
|
|
||||||
|
|
||||||
addEventListener(element, eventName: string, handler: Function, shouldSupportBubble: boolean) {
|
addEventListener(element, eventName: string, handler: Function, shouldSupportBubble: boolean) {
|
||||||
MapWrapper.set(shouldSupportBubble ? this._bubbleEventHandlers : this._nonBubbleEventHandlers,
|
MapWrapper.set(shouldSupportBubble ? this._bubbleEventHandlers : this._nonBubbleEventHandlers,
|
||||||
eventName, handler);
|
eventName, handler);
|
||||||
return () => {MapWrapper.delete(shouldSupportBubble ? this._bubbleEventHandlers : this._nonBubbleEventHandlers,
|
return () => {
|
||||||
eventName)};
|
MapWrapper.delete(
|
||||||
|
shouldSupportBubble ? this._bubbleEventHandlers : this._nonBubbleEventHandlers, eventName)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeNgZone extends NgZone {
|
class FakeNgZone extends NgZone {
|
||||||
constructor() {
|
constructor() { super({enableLongStackTrace: false}); }
|
||||||
super({enableLongStackTrace: false});
|
|
||||||
}
|
|
||||||
|
|
||||||
run(fn) {
|
run(fn) { fn(); }
|
||||||
fn();
|
|
||||||
}
|
|
||||||
|
|
||||||
runOutsideAngular(fn) {
|
runOutsideAngular(fn) { return fn(); }
|
||||||
return fn();
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,4 +1,14 @@
|
||||||
import {describe, ddescribe, it, iit, xit, xdescribe, expect, beforeEach, el} from 'angular2/test_lib';
|
import {
|
||||||
|
describe,
|
||||||
|
ddescribe,
|
||||||
|
it,
|
||||||
|
iit,
|
||||||
|
xit,
|
||||||
|
xdescribe,
|
||||||
|
expect,
|
||||||
|
beforeEach,
|
||||||
|
el
|
||||||
|
} from 'angular2/test_lib';
|
||||||
import {KeyEventsPlugin} from 'angular2/src/render/dom/events/key_events';
|
import {KeyEventsPlugin} from 'angular2/src/render/dom/events/key_events';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
|
@ -15,53 +25,33 @@ export function main() {
|
||||||
|
|
||||||
it('should correctly parse event names', () => {
|
it('should correctly parse event names', () => {
|
||||||
// key with no modifier
|
// key with no modifier
|
||||||
expect(KeyEventsPlugin.parseEventName('keydown.enter')).toEqual({
|
expect(KeyEventsPlugin.parseEventName('keydown.enter'))
|
||||||
'domEventName': 'keydown',
|
.toEqual({'domEventName': 'keydown', 'fullKey': 'enter'});
|
||||||
'fullKey': 'enter'
|
expect(KeyEventsPlugin.parseEventName('keyup.enter'))
|
||||||
});
|
.toEqual({'domEventName': 'keyup', 'fullKey': 'enter'});
|
||||||
expect(KeyEventsPlugin.parseEventName('keyup.enter')).toEqual({
|
|
||||||
'domEventName': 'keyup',
|
|
||||||
'fullKey': 'enter'
|
|
||||||
});
|
|
||||||
|
|
||||||
// key with modifiers:
|
// key with modifiers:
|
||||||
expect(KeyEventsPlugin.parseEventName('keydown.control.shift.enter')).toEqual({
|
expect(KeyEventsPlugin.parseEventName('keydown.control.shift.enter'))
|
||||||
'domEventName': 'keydown',
|
.toEqual({'domEventName': 'keydown', 'fullKey': 'control.shift.enter'});
|
||||||
'fullKey': 'control.shift.enter'
|
expect(KeyEventsPlugin.parseEventName('keyup.control.shift.enter'))
|
||||||
});
|
.toEqual({'domEventName': 'keyup', 'fullKey': 'control.shift.enter'});
|
||||||
expect(KeyEventsPlugin.parseEventName('keyup.control.shift.enter')).toEqual({
|
|
||||||
'domEventName': 'keyup',
|
|
||||||
'fullKey': 'control.shift.enter'
|
|
||||||
});
|
|
||||||
|
|
||||||
// key with modifiers in a different order:
|
// key with modifiers in a different order:
|
||||||
expect(KeyEventsPlugin.parseEventName('keydown.shift.control.enter')).toEqual({
|
expect(KeyEventsPlugin.parseEventName('keydown.shift.control.enter'))
|
||||||
'domEventName': 'keydown',
|
.toEqual({'domEventName': 'keydown', 'fullKey': 'control.shift.enter'});
|
||||||
'fullKey': 'control.shift.enter'
|
expect(KeyEventsPlugin.parseEventName('keyup.shift.control.enter'))
|
||||||
});
|
.toEqual({'domEventName': 'keyup', 'fullKey': 'control.shift.enter'});
|
||||||
expect(KeyEventsPlugin.parseEventName('keyup.shift.control.enter')).toEqual({
|
|
||||||
'domEventName': 'keyup',
|
|
||||||
'fullKey': 'control.shift.enter'
|
|
||||||
});
|
|
||||||
|
|
||||||
// key that is also a modifier:
|
// key that is also a modifier:
|
||||||
expect(KeyEventsPlugin.parseEventName('keydown.shift.control')).toEqual({
|
expect(KeyEventsPlugin.parseEventName('keydown.shift.control'))
|
||||||
'domEventName': 'keydown',
|
.toEqual({'domEventName': 'keydown', 'fullKey': 'shift.control'});
|
||||||
'fullKey': 'shift.control'
|
expect(KeyEventsPlugin.parseEventName('keyup.shift.control'))
|
||||||
});
|
.toEqual({'domEventName': 'keyup', 'fullKey': 'shift.control'});
|
||||||
expect(KeyEventsPlugin.parseEventName('keyup.shift.control')).toEqual({
|
|
||||||
'domEventName': 'keyup',
|
|
||||||
'fullKey': 'shift.control'
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(KeyEventsPlugin.parseEventName('keydown.control.shift')).toEqual({
|
expect(KeyEventsPlugin.parseEventName('keydown.control.shift'))
|
||||||
'domEventName': 'keydown',
|
.toEqual({'domEventName': 'keydown', 'fullKey': 'control.shift'});
|
||||||
'fullKey': 'control.shift'
|
expect(KeyEventsPlugin.parseEventName('keyup.control.shift'))
|
||||||
});
|
.toEqual({'domEventName': 'keyup', 'fullKey': 'control.shift'});
|
||||||
expect(KeyEventsPlugin.parseEventName('keyup.control.shift')).toEqual({
|
|
||||||
'domEventName': 'keyup',
|
|
||||||
'fullKey': 'control.shift'
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
import {describe, beforeEach, it, expect, ddescribe, iit, SpyObject, el, proxy} from 'angular2/test_lib';
|
import {
|
||||||
import {IMPLEMENTS} from 'angular2/src/facade/lang';
|
describe,
|
||||||
|
beforeEach,
|
||||||
|
it,
|
||||||
|
expect,
|
||||||
|
ddescribe,
|
||||||
|
iit,
|
||||||
|
SpyObject,
|
||||||
|
el,
|
||||||
|
proxy
|
||||||
|
} from 'angular2/test_lib';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {Content} from 'angular2/src/render/dom/shadow_dom/content_tag';
|
import {Content} from 'angular2/src/render/dom/shadow_dom/content_tag';
|
||||||
import {LightDom} from 'angular2/src/render/dom/shadow_dom/light_dom';
|
|
||||||
|
|
||||||
@proxy
|
|
||||||
@IMPLEMENTS(LightDom)
|
|
||||||
class DummyLightDom extends SpyObject {noSuchMethod(m){super.noSuchMethod(m)}}
|
|
||||||
|
|
||||||
var _scriptStart = `<script start=""></script>`;
|
var _scriptStart = `<script start=""></script>`;
|
||||||
var _scriptEnd = `<script end=""></script>`;
|
var _scriptEnd = `<script end=""></script>`;
|
||||||
|
@ -26,7 +30,8 @@ export function main() {
|
||||||
c.init(null);
|
c.init(null);
|
||||||
c.insert([el("<a></a>"), el("<b></b>")])
|
c.insert([el("<a></a>"), el("<b></b>")])
|
||||||
|
|
||||||
expect(DOM.getInnerHTML(parent)).toEqual(`${_scriptStart}<a></a><b></b>${_scriptEnd}`);
|
expect(DOM.getInnerHTML(parent))
|
||||||
|
.toEqual(`${_scriptStart}<a></a><b></b>${_scriptEnd}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should remove the nodes from the previous insertion", () => {
|
it("should remove the nodes from the previous insertion", () => {
|
|
@ -51,9 +51,9 @@ export function main() {
|
||||||
it('should rewrite style urls', () => {
|
it('should rewrite style urls', () => {
|
||||||
var styleElement = el('<style>.foo {background-image: url("img.jpg");}</style>');
|
var styleElement = el('<style>.foo {background-image: url("img.jpg");}</style>');
|
||||||
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
||||||
expect(styleElement).toHaveText(".foo[_ngcontent-0] {\n" +
|
expect(styleElement)
|
||||||
"background-image: url(http://base/img.jpg);\n" +
|
.toHaveText(".foo[_ngcontent-0] {\n" + "background-image: url(http://base/img.jpg);\n" +
|
||||||
"}");
|
"}");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should scope styles', () => {
|
it('should scope styles', () => {
|
||||||
|
@ -63,18 +63,19 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should inline @import rules', inject([AsyncTestCompleter], (async) => {
|
it('should inline @import rules', inject([AsyncTestCompleter], (async) => {
|
||||||
xhr.reply('http://base/one.css', '.one {}');
|
xhr.reply('http://base/one.css', '.one {}');
|
||||||
|
|
||||||
var styleElement = el('<style>@import "one.css";</style>');
|
var styleElement = el('<style>@import "one.css";</style>');
|
||||||
var stylePromise = strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
var stylePromise =
|
||||||
expect(stylePromise).toBePromise();
|
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
||||||
expect(styleElement).toHaveText('');
|
expect(stylePromise).toBePromise();
|
||||||
|
expect(styleElement).toHaveText('');
|
||||||
|
|
||||||
stylePromise.then((_) => {
|
stylePromise.then((_) => {
|
||||||
expect(styleElement).toHaveText('.one[_ngcontent-0] {\n\n}');
|
expect(styleElement).toHaveText('.one[_ngcontent-0] {\n\n}');
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should return the same style given the same component', () => {
|
it('should return the same style given the same component', () => {
|
||||||
var styleElement = el('<style>.foo {} :host {}</style>');
|
var styleElement = el('<style>.foo {} :host {}</style>');
|
||||||
|
@ -121,7 +122,7 @@ export function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeXHR extends XHR {
|
class FakeXHR extends XHR {
|
||||||
_responses: Map;
|
_responses: Map<string, string>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
@ -137,7 +138,5 @@ class FakeXHR extends XHR {
|
||||||
return PromiseWrapper.resolve(response);
|
return PromiseWrapper.resolve(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
reply(url: string, response: string) {
|
reply(url: string, response: string) { MapWrapper.set(this._responses, url, response); }
|
||||||
MapWrapper.set(this._responses, url, response);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -46,13 +46,12 @@ export function main() {
|
||||||
it('should rewrite style urls', () => {
|
it('should rewrite style urls', () => {
|
||||||
var styleElement = el('<style>.foo {background-image: url("img.jpg");}</style>');
|
var styleElement = el('<style>.foo {background-image: url("img.jpg");}</style>');
|
||||||
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
||||||
expect(styleElement).toHaveText(".foo {" +
|
expect(styleElement)
|
||||||
"background-image: url('http://base/img.jpg');" +
|
.toHaveText(".foo {" + "background-image: url('http://base/img.jpg');" + "}");
|
||||||
"}");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not inline import rules', () => {
|
it('should not inline import rules', () => {
|
||||||
var styleElement = el('<style>@import "other.css";</style>')
|
var styleElement = el('<style>@import "other.css";</style>');
|
||||||
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
||||||
expect(styleElement).toHaveText("@import 'http://base/other.css';");
|
expect(styleElement).toHaveText("@import 'http://base/other.css';");
|
||||||
});
|
});
|
||||||
|
@ -81,4 +80,3 @@ export function main() {
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,14 @@
|
||||||
import {describe, beforeEach, it, expect, ddescribe, iit, SpyObject, el, proxy} from 'angular2/test_lib';
|
import {
|
||||||
|
describe,
|
||||||
|
beforeEach,
|
||||||
|
it,
|
||||||
|
expect,
|
||||||
|
ddescribe,
|
||||||
|
iit,
|
||||||
|
SpyObject,
|
||||||
|
el,
|
||||||
|
proxy
|
||||||
|
} from 'angular2/test_lib';
|
||||||
import {IMPLEMENTS, isBlank, isPresent} from 'angular2/src/facade/lang';
|
import {IMPLEMENTS, isBlank, isPresent} from 'angular2/src/facade/lang';
|
||||||
import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
|
@ -9,12 +19,13 @@ import {DomViewContainer} from 'angular2/src/render/dom/view/view_container';
|
||||||
|
|
||||||
@proxy
|
@proxy
|
||||||
@IMPLEMENTS(DomView)
|
@IMPLEMENTS(DomView)
|
||||||
class FakeView {
|
class FakeView extends SpyObject {
|
||||||
boundElements;
|
boundElements;
|
||||||
contentTags;
|
contentTags;
|
||||||
viewContainers;
|
viewContainers;
|
||||||
|
|
||||||
constructor(containers = null) {
|
constructor(containers = null) {
|
||||||
|
super(DomView);
|
||||||
this.boundElements = [];
|
this.boundElements = [];
|
||||||
this.contentTags = [];
|
this.contentTags = [];
|
||||||
this.viewContainers = [];
|
this.viewContainers = [];
|
||||||
|
@ -38,62 +49,50 @@ class FakeView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
noSuchMethod(i) {
|
noSuchMethod(i) { super.noSuchMethod(i); }
|
||||||
super.noSuchMethod(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@proxy
|
@proxy
|
||||||
@IMPLEMENTS(DomViewContainer)
|
@IMPLEMENTS(DomViewContainer)
|
||||||
class FakeViewContainer {
|
class FakeViewContainer extends SpyObject {
|
||||||
_nodes;
|
_nodes;
|
||||||
_contentTagContainers;
|
_contentTagContainers;
|
||||||
templateElement;
|
templateElement;
|
||||||
|
|
||||||
constructor(templateEl, nodes = null, views = null) {
|
constructor(templateEl, nodes = null, views = null) {
|
||||||
|
super(DomViewContainer);
|
||||||
this.templateElement = templateEl;
|
this.templateElement = templateEl;
|
||||||
this._nodes = nodes;
|
this._nodes = nodes;
|
||||||
this._contentTagContainers = views;
|
this._contentTagContainers = views;
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes(){
|
nodes() { return this._nodes; }
|
||||||
return this._nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
contentTagContainers(){
|
contentTagContainers() { return this._contentTagContainers; }
|
||||||
return this._contentTagContainers;
|
|
||||||
}
|
|
||||||
|
|
||||||
noSuchMethod(i) {
|
noSuchMethod(i) { super.noSuchMethod(i); }
|
||||||
super.noSuchMethod(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@proxy
|
@proxy
|
||||||
@IMPLEMENTS(Content)
|
@IMPLEMENTS(Content)
|
||||||
class FakeContentTag {
|
class FakeContentTag extends SpyObject {
|
||||||
select;
|
select;
|
||||||
_nodes;
|
_nodes;
|
||||||
contentStartElement;
|
contentStartElement;
|
||||||
|
|
||||||
constructor(contentEl, select = '', nodes = null) {
|
constructor(contentEl, select = '', nodes = null) {
|
||||||
|
super(Content);
|
||||||
this.contentStartElement = contentEl;
|
this.contentStartElement = contentEl;
|
||||||
this.select = select;
|
this.select = select;
|
||||||
this._nodes = nodes;
|
this._nodes = nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
insert(nodes){
|
insert(nodes) { this._nodes = nodes; }
|
||||||
this._nodes = nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
nodes() {
|
nodes() { return this._nodes; }
|
||||||
return this._nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
noSuchMethod(i) {
|
noSuchMethod(i) { super.noSuchMethod(i); }
|
||||||
super.noSuchMethod(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createLightDom(hostView, shadowView, el) {
|
function createLightDom(hostView, shadowView, el) {
|
||||||
|
@ -106,29 +105,23 @@ export function main() {
|
||||||
describe('LightDom', function() {
|
describe('LightDom', function() {
|
||||||
var lightDomView;
|
var lightDomView;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => { lightDomView = new FakeView(); });
|
||||||
lightDomView = new FakeView();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("contentTags", () => {
|
describe("contentTags", () => {
|
||||||
it("should collect content tags from element injectors", () => {
|
it("should collect content tags from element injectors", () => {
|
||||||
var tag = new FakeContentTag(el('<script></script>'));
|
var tag = new FakeContentTag(el('<script></script>'));
|
||||||
var shadowDomView = new FakeView([tag]);
|
var shadowDomView = new FakeView([tag]);
|
||||||
|
|
||||||
var lightDom = createLightDom(lightDomView, shadowDomView,
|
var lightDom = createLightDom(lightDomView, shadowDomView, el("<div></div>"));
|
||||||
el("<div></div>"));
|
|
||||||
|
|
||||||
expect(lightDom.contentTags()).toEqual([tag]);
|
expect(lightDom.contentTags()).toEqual([tag]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should collect content tags from ViewContainers", () => {
|
it("should collect content tags from ViewContainers", () => {
|
||||||
var tag = new FakeContentTag(el('<script></script>'));
|
var tag = new FakeContentTag(el('<script></script>'));
|
||||||
var vc = new FakeViewContainer(null, null, [
|
var vc = new FakeViewContainer(null, null, [new FakeView([tag])]);
|
||||||
new FakeView([tag])
|
|
||||||
]);
|
|
||||||
var shadowDomView = new FakeView([vc]);
|
var shadowDomView = new FakeView([vc]);
|
||||||
var lightDom = createLightDom(lightDomView, shadowDomView,
|
var lightDom = createLightDom(lightDomView, shadowDomView, el("<div></div>"));
|
||||||
el("<div></div>"));
|
|
||||||
|
|
||||||
expect(lightDom.contentTags()).toEqual([tag]);
|
expect(lightDom.contentTags()).toEqual([tag]);
|
||||||
});
|
});
|
||||||
|
@ -136,7 +129,7 @@ export function main() {
|
||||||
|
|
||||||
describe("expandedDomNodes", () => {
|
describe("expandedDomNodes", () => {
|
||||||
it("should contain root nodes", () => {
|
it("should contain root nodes", () => {
|
||||||
var lightDomEl = el("<div><a></a></div>")
|
var lightDomEl = el("<div><a></a></div>");
|
||||||
var lightDom = createLightDom(lightDomView, new FakeView(), lightDomEl);
|
var lightDom = createLightDom(lightDomView, new FakeView(), lightDomEl);
|
||||||
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
|
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
|
||||||
});
|
});
|
||||||
|
@ -144,14 +137,11 @@ export function main() {
|
||||||
it("should include view container nodes", () => {
|
it("should include view container nodes", () => {
|
||||||
var lightDomEl = el("<div><template></template></div>");
|
var lightDomEl = el("<div><template></template></div>");
|
||||||
var lightDom = createLightDom(
|
var lightDom = createLightDom(
|
||||||
new FakeView([
|
new FakeView(
|
||||||
new FakeViewContainer(
|
[new FakeViewContainer(DOM.firstChild(lightDomEl), // template element
|
||||||
DOM.firstChild(lightDomEl), // template element
|
[el('<a></a>')] // light DOM nodes of view container
|
||||||
[el('<a></a>')] // light DOM nodes of view container
|
)]),
|
||||||
)
|
null, lightDomEl);
|
||||||
]),
|
|
||||||
null,
|
|
||||||
lightDomEl);
|
|
||||||
|
|
||||||
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
|
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
|
||||||
});
|
});
|
||||||
|
@ -159,15 +149,11 @@ export function main() {
|
||||||
it("should include content nodes", () => {
|
it("should include content nodes", () => {
|
||||||
var lightDomEl = el("<div><content></content></div>");
|
var lightDomEl = el("<div><content></content></div>");
|
||||||
var lightDom = createLightDom(
|
var lightDom = createLightDom(
|
||||||
new FakeView([
|
new FakeView([new FakeContentTag(DOM.firstChild(lightDomEl), // content element
|
||||||
new FakeContentTag(
|
'', // selector
|
||||||
DOM.firstChild(lightDomEl), // content element
|
[el('<a></a>')] // light DOM nodes of content tag
|
||||||
'', // selector
|
)]),
|
||||||
[el('<a></a>')] // light DOM nodes of content tag
|
null, lightDomEl);
|
||||||
)
|
|
||||||
]),
|
|
||||||
null,
|
|
||||||
lightDomEl);
|
|
||||||
|
|
||||||
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
|
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
|
||||||
});
|
});
|
||||||
|
@ -175,12 +161,9 @@ export function main() {
|
||||||
it("should work when the element injector array contains nulls", () => {
|
it("should work when the element injector array contains nulls", () => {
|
||||||
var lightDomEl = el("<div><a></a></div>")
|
var lightDomEl = el("<div><a></a></div>")
|
||||||
|
|
||||||
var lightDomView = new FakeView();
|
var lightDomView = new FakeView();
|
||||||
|
|
||||||
var lightDom = createLightDom(
|
var lightDom = createLightDom(lightDomView, new FakeView(), lightDomEl);
|
||||||
lightDomView,
|
|
||||||
new FakeView(),
|
|
||||||
lightDomEl);
|
|
||||||
|
|
||||||
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
|
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
|
||||||
});
|
});
|
||||||
|
@ -193,10 +176,8 @@ export function main() {
|
||||||
|
|
||||||
var lightDomEl = el("<div><a>1</a><b>2</b><a>3</a></div>")
|
var lightDomEl = el("<div><a>1</a><b>2</b><a>3</a></div>")
|
||||||
|
|
||||||
var lightDom = createLightDom(lightDomView, new FakeView([
|
var lightDom =
|
||||||
contentA,
|
createLightDom(lightDomView, new FakeView([contentA, contentB]), lightDomEl);
|
||||||
contentB
|
|
||||||
]), lightDomEl);
|
|
||||||
|
|
||||||
lightDom.redistribute();
|
lightDom.redistribute();
|
||||||
|
|
||||||
|
@ -210,10 +191,8 @@ export function main() {
|
||||||
|
|
||||||
var lightDomEl = el("<div><a>1</a><b>2</b><a>3</a></div>")
|
var lightDomEl = el("<div><a>1</a><b>2</b><a>3</a></div>")
|
||||||
|
|
||||||
var lightDom = createLightDom(lightDomView, new FakeView([
|
var lightDom =
|
||||||
wildcard,
|
createLightDom(lightDomView, new FakeView([wildcard, contentB]), lightDomEl);
|
||||||
contentB
|
|
||||||
]), lightDomEl);
|
|
||||||
|
|
||||||
lightDom.redistribute();
|
lightDom.redistribute();
|
||||||
|
|
||||||
|
@ -224,7 +203,7 @@ export function main() {
|
||||||
it("should remove all nodes if there are no content tags", () => {
|
it("should remove all nodes if there are no content tags", () => {
|
||||||
var lightDomEl = el("<div><a>1</a><b>2</b><a>3</a></div>")
|
var lightDomEl = el("<div><a>1</a><b>2</b><a>3</a></div>")
|
||||||
|
|
||||||
var lightDom = createLightDom(lightDomView, new FakeView([]), lightDomEl);
|
var lightDom = createLightDom(lightDomView, new FakeView([]), lightDomEl);
|
||||||
|
|
||||||
lightDom.redistribute();
|
lightDom.redistribute();
|
||||||
|
|
||||||
|
@ -235,9 +214,8 @@ export function main() {
|
||||||
var lightDomEl = el("<div><a>1</a><b>2</b><a>3</a></div>");
|
var lightDomEl = el("<div><a>1</a><b>2</b><a>3</a></div>");
|
||||||
var bNode = DOM.childNodes(lightDomEl)[1];
|
var bNode = DOM.childNodes(lightDomEl)[1];
|
||||||
|
|
||||||
var lightDom = createLightDom(lightDomView, new FakeView([
|
var lightDom =
|
||||||
new FakeContentTag(null, "a")
|
createLightDom(lightDomView, new FakeView([new FakeContentTag(null, "a")]), lightDomEl);
|
||||||
]), lightDomEl);
|
|
||||||
|
|
||||||
lightDom.redistribute();
|
lightDom.redistribute();
|
||||||
|
|
|
@ -40,13 +40,12 @@ export function main() {
|
||||||
it('should rewrite style urls', () => {
|
it('should rewrite style urls', () => {
|
||||||
var styleElement = el('<style>.foo {background-image: url("img.jpg");}</style>');
|
var styleElement = el('<style>.foo {background-image: url("img.jpg");}</style>');
|
||||||
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
||||||
expect(styleElement).toHaveText(".foo {" +
|
expect(styleElement)
|
||||||
"background-image: url('http://base/img.jpg');" +
|
.toHaveText(".foo {" + "background-image: url('http://base/img.jpg');" + "}");
|
||||||
"}");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not inline import rules', () => {
|
it('should not inline import rules', () => {
|
||||||
var styleElement = el('<style>@import "other.css";</style>')
|
var styleElement = el('<style>@import "other.css";</style>');
|
||||||
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
||||||
expect(styleElement).toHaveText("@import 'http://base/other.css';");
|
expect(styleElement).toHaveText("@import 'http://base/other.css';");
|
||||||
});
|
});
|
|
@ -6,16 +6,14 @@ import {RegExpWrapper, StringWrapper} from 'angular2/src/facade/lang';
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('ShadowCss', function() {
|
describe('ShadowCss', function() {
|
||||||
|
|
||||||
function s(css: string, contentAttr:string, hostAttr:string = '') {
|
function s(css: string, contentAttr: string, hostAttr: string = '') {
|
||||||
var shadowCss = new ShadowCss();
|
var shadowCss = new ShadowCss();
|
||||||
var shim = shadowCss.shimCssText(css, contentAttr, hostAttr);
|
var shim = shadowCss.shimCssText(css, contentAttr, hostAttr);
|
||||||
var nlRegexp = RegExpWrapper.create('\\n');
|
var nlRegexp = RegExpWrapper.create('\\n');
|
||||||
return StringWrapper.replaceAll(shim, nlRegexp, '');
|
return StringWrapper.replaceAll(shim, nlRegexp, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should handle empty string', () => {
|
it('should handle empty string', () => { expect(s('', 'a')).toEqual(''); });
|
||||||
expect(s('', 'a')).toEqual('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add an attribute to every rule', () => {
|
it('should add an attribute to every rule', () => {
|
||||||
var css = 'one {color: red;}two {color: red;}';
|
var css = 'one {color: red;}two {color: red;}';
|
||||||
|
@ -67,12 +65,14 @@ export function main() {
|
||||||
it('should handle :host', () => {
|
it('should handle :host', () => {
|
||||||
expect(s(':host {}', 'a', 'a-host')).toEqual('[a-host] {}');
|
expect(s(':host {}', 'a', 'a-host')).toEqual('[a-host] {}');
|
||||||
expect(s(':host(.x,.y) {}', 'a', 'a-host')).toEqual('[a-host].x, [a-host].y {}');
|
expect(s(':host(.x,.y) {}', 'a', 'a-host')).toEqual('[a-host].x, [a-host].y {}');
|
||||||
expect(s(':host(.x,.y) > .z {}', 'a', 'a-host')).toEqual('[a-host].x > .z, [a-host].y > .z {}');
|
expect(s(':host(.x,.y) > .z {}', 'a', 'a-host'))
|
||||||
|
.toEqual('[a-host].x > .z, [a-host].y > .z {}');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle :host-context', () => {
|
it('should handle :host-context', () => {
|
||||||
expect(s(':host-context(.x) {}', 'a', 'a-host')).toEqual('[a-host].x, .x [a-host] {}');
|
expect(s(':host-context(.x) {}', 'a', 'a-host')).toEqual('[a-host].x, .x [a-host] {}');
|
||||||
expect(s(':host-context(.x) > .y {}', 'a', 'a-host')).toEqual('[a-host].x > .y, .x [a-host] > .y {}');
|
expect(s(':host-context(.x) > .y {}', 'a', 'a-host'))
|
||||||
|
.toEqual('[a-host].x > .y, .x [a-host] > .y {}');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support polyfill-next-selector', () => {
|
it('should support polyfill-next-selector', () => {
|
|
@ -1,234 +0,0 @@
|
||||||
import {
|
|
||||||
AsyncTestCompleter,
|
|
||||||
beforeEach,
|
|
||||||
beforeEachBindings,
|
|
||||||
ddescribe,
|
|
||||||
describe,
|
|
||||||
el,
|
|
||||||
expect,
|
|
||||||
iit,
|
|
||||||
inject,
|
|
||||||
it,
|
|
||||||
xit,
|
|
||||||
} from 'angular2/test_lib';
|
|
||||||
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
|
|
||||||
|
|
||||||
import {isBlank} from 'angular2/src/facade/lang';
|
|
||||||
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
|
||||||
import {Map, MapWrapper} from 'angular2/src/facade/collection';
|
|
||||||
|
|
||||||
import {XHR} from 'angular2/src/services/xhr';
|
|
||||||
|
|
||||||
import {bind} from 'angular2/di';
|
|
||||||
|
|
||||||
export function main() {
|
|
||||||
describe('StyleInliner', () => {
|
|
||||||
beforeEachBindings(() => [
|
|
||||||
bind(XHR).toClass(FakeXHR),
|
|
||||||
]);
|
|
||||||
|
|
||||||
describe('loading', () => {
|
|
||||||
|
|
||||||
it('should return a string when there is no import statement', inject([StyleInliner], (inliner) => {
|
|
||||||
var css = '.main {}';
|
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
|
||||||
expect(loadedCss).toEqual(css);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should inline @import rules',
|
|
||||||
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
|
||||||
xhr.reply('http://base/one.css', '.one {}');
|
|
||||||
var css = '@import url("one.css");.main {}';
|
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
|
||||||
expect(loadedCss).toBePromise();
|
|
||||||
PromiseWrapper.then(
|
|
||||||
loadedCss,
|
|
||||||
function(css) {
|
|
||||||
expect(css).toEqual('.one {}\n.main {}');
|
|
||||||
async.done();
|
|
||||||
},
|
|
||||||
function(e) {
|
|
||||||
throw 'fail;'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should support url([unquoted url]) in @import rules',
|
|
||||||
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
|
||||||
xhr.reply('http://base/one.css', '.one {}');
|
|
||||||
var css = '@import url(one.css);.main {}';
|
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
|
||||||
expect(loadedCss).toBePromise();
|
|
||||||
PromiseWrapper.then(
|
|
||||||
loadedCss,
|
|
||||||
function(css) {
|
|
||||||
expect(css).toEqual('.one {}\n.main {}');
|
|
||||||
async.done();
|
|
||||||
},
|
|
||||||
function(e) {
|
|
||||||
throw 'fail;'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should handle @import error gracefuly',
|
|
||||||
inject([StyleInliner, AsyncTestCompleter], (inliner, async) => {
|
|
||||||
var css = '@import "one.css";.main {}';
|
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
|
||||||
expect(loadedCss).toBePromise();
|
|
||||||
PromiseWrapper.then(
|
|
||||||
loadedCss,
|
|
||||||
function(css) {
|
|
||||||
expect(css).toEqual('/* failed to import http://base/one.css */\n.main {}');
|
|
||||||
async.done();
|
|
||||||
},
|
|
||||||
function(e) {
|
|
||||||
throw 'fail;'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should inline multiple @import rules',
|
|
||||||
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
|
||||||
xhr.reply('http://base/one.css', '.one {}');
|
|
||||||
xhr.reply('http://base/two.css', '.two {}');
|
|
||||||
var css = '@import "one.css";@import "two.css";.main {}';
|
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
|
||||||
expect(loadedCss).toBePromise();
|
|
||||||
PromiseWrapper.then(
|
|
||||||
loadedCss,
|
|
||||||
function(css) {
|
|
||||||
expect(css).toEqual('.one {}\n.two {}\n.main {}');
|
|
||||||
async.done();
|
|
||||||
},
|
|
||||||
function(e) {
|
|
||||||
throw 'fail;'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should inline nested @import rules',
|
|
||||||
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
|
||||||
xhr.reply('http://base/one.css', '@import "two.css";.one {}');
|
|
||||||
xhr.reply('http://base/two.css', '.two {}');
|
|
||||||
var css = '@import "one.css";.main {}';
|
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
|
||||||
expect(loadedCss).toBePromise();
|
|
||||||
PromiseWrapper.then(
|
|
||||||
loadedCss,
|
|
||||||
function(css) {
|
|
||||||
expect(css).toEqual('.two {}\n.one {}\n.main {}');
|
|
||||||
async.done();
|
|
||||||
},
|
|
||||||
function(e) {
|
|
||||||
throw 'fail;'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should handle circular dependencies gracefuly',
|
|
||||||
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
|
||||||
xhr.reply('http://base/one.css', '@import "two.css";.one {}');
|
|
||||||
xhr.reply('http://base/two.css', '@import "one.css";.two {}');
|
|
||||||
var css = '@import "one.css";.main {}';
|
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
|
||||||
expect(loadedCss).toBePromise();
|
|
||||||
PromiseWrapper.then(
|
|
||||||
loadedCss,
|
|
||||||
function(css) {
|
|
||||||
expect(css).toEqual('.two {}\n.one {}\n.main {}');
|
|
||||||
async.done();
|
|
||||||
},
|
|
||||||
function(e) {
|
|
||||||
throw 'fail;'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should handle invalid @import fracefuly',
|
|
||||||
inject([StyleInliner, AsyncTestCompleter], (inliner, async) => {
|
|
||||||
// Invalid rule: the url is not quoted
|
|
||||||
var css = '@import one.css;.main {}';
|
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
|
||||||
expect(loadedCss).toBePromise();
|
|
||||||
PromiseWrapper.then(
|
|
||||||
loadedCss,
|
|
||||||
function(css) {
|
|
||||||
expect(css).toEqual('/* Invalid import rule: "@import one.css;" */.main {}');
|
|
||||||
async.done();
|
|
||||||
},
|
|
||||||
function(e) {
|
|
||||||
throw 'fail;'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('media query', () => {
|
|
||||||
it('should wrap inlined content in media query',
|
|
||||||
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
|
||||||
xhr.reply('http://base/one.css', '.one {}');
|
|
||||||
var css = '@import "one.css" (min-width: 700px) and (orientation: landscape);';
|
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
|
||||||
expect(loadedCss).toBePromise();
|
|
||||||
PromiseWrapper.then(
|
|
||||||
loadedCss,
|
|
||||||
function(css) {
|
|
||||||
expect(css).toEqual('@media (min-width: 700px) and (orientation: landscape) {\n.one {}\n}\n');
|
|
||||||
async.done();
|
|
||||||
},
|
|
||||||
function(e) {
|
|
||||||
throw 'fail;'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('url rewritting', () => {
|
|
||||||
it('should rewrite url in inlined content',
|
|
||||||
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
|
||||||
// it should rewrite both '@import' and 'url()'
|
|
||||||
xhr.reply('http://base/one.css', '@import "./nested/two.css";.one {background-image: url("one.jpg");}');
|
|
||||||
xhr.reply('http://base/nested/two.css', '.two {background-image: url("../img/two.jpg");}');
|
|
||||||
var css = '@import "one.css";'
|
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
|
||||||
expect(loadedCss).toBePromise();
|
|
||||||
PromiseWrapper.then(
|
|
||||||
loadedCss,
|
|
||||||
function(css) {
|
|
||||||
expect(css).toEqual(
|
|
||||||
".two {background-image: url('http://base/img/two.jpg');}\n" +
|
|
||||||
".one {background-image: url('http://base/one.jpg');}\n"
|
|
||||||
);
|
|
||||||
async.done();
|
|
||||||
},
|
|
||||||
function(e) {
|
|
||||||
throw 'fail;'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
class FakeXHR extends XHR {
|
|
||||||
_responses: Map;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this._responses = MapWrapper.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
get(url: string): Promise<string> {
|
|
||||||
var response = MapWrapper.get(this._responses, url);
|
|
||||||
if (isBlank(response)) {
|
|
||||||
return PromiseWrapper.reject('xhr error', null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return PromiseWrapper.resolve(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
reply(url: string, response: string) {
|
|
||||||
MapWrapper.set(this._responses, url, response);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,203 @@
|
||||||
|
import {
|
||||||
|
AsyncTestCompleter,
|
||||||
|
beforeEach,
|
||||||
|
beforeEachBindings,
|
||||||
|
ddescribe,
|
||||||
|
describe,
|
||||||
|
el,
|
||||||
|
expect,
|
||||||
|
iit,
|
||||||
|
inject,
|
||||||
|
it,
|
||||||
|
xit,
|
||||||
|
} from 'angular2/test_lib';
|
||||||
|
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
|
||||||
|
|
||||||
|
import {isBlank} from 'angular2/src/facade/lang';
|
||||||
|
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
|
import {Map, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
|
import {XHR} from 'angular2/src/services/xhr';
|
||||||
|
|
||||||
|
import {bind} from 'angular2/di';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe('StyleInliner', () => {
|
||||||
|
beforeEachBindings(() => [
|
||||||
|
bind(XHR)
|
||||||
|
.toClass(FakeXHR),
|
||||||
|
]);
|
||||||
|
|
||||||
|
describe('loading', () => {
|
||||||
|
|
||||||
|
it('should return a string when there is no import statement',
|
||||||
|
inject([StyleInliner], (inliner) => {
|
||||||
|
var css = '.main {}';
|
||||||
|
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||||
|
expect(loadedCss).toEqual(css);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should inline @import rules',
|
||||||
|
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
||||||
|
xhr.reply('http://base/one.css', '.one {}');
|
||||||
|
var css = '@import url("one.css");.main {}';
|
||||||
|
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||||
|
expect(loadedCss).toBePromise();
|
||||||
|
PromiseWrapper.then(loadedCss,
|
||||||
|
function(css) {
|
||||||
|
expect(css).toEqual('.one {}\n.main {}');
|
||||||
|
async.done();
|
||||||
|
},
|
||||||
|
function(e) { throw 'fail;' });
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should support url([unquoted url]) in @import rules',
|
||||||
|
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
||||||
|
xhr.reply('http://base/one.css', '.one {}');
|
||||||
|
var css = '@import url(one.css);.main {}';
|
||||||
|
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||||
|
expect(loadedCss).toBePromise();
|
||||||
|
PromiseWrapper.then(loadedCss,
|
||||||
|
function(css) {
|
||||||
|
expect(css).toEqual('.one {}\n.main {}');
|
||||||
|
async.done();
|
||||||
|
},
|
||||||
|
function(e) { throw 'fail;' });
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should handle @import error gracefuly',
|
||||||
|
inject([StyleInliner, AsyncTestCompleter], (inliner, async) => {
|
||||||
|
var css = '@import "one.css";.main {}';
|
||||||
|
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||||
|
expect(loadedCss).toBePromise();
|
||||||
|
PromiseWrapper.then(
|
||||||
|
loadedCss,
|
||||||
|
function(css) {
|
||||||
|
expect(css).toEqual('/* failed to import http://base/one.css */\n.main {}');
|
||||||
|
async.done();
|
||||||
|
},
|
||||||
|
function(e) { throw 'fail;' });
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should inline multiple @import rules',
|
||||||
|
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
||||||
|
xhr.reply('http://base/one.css', '.one {}');
|
||||||
|
xhr.reply('http://base/two.css', '.two {}');
|
||||||
|
var css = '@import "one.css";@import "two.css";.main {}';
|
||||||
|
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||||
|
expect(loadedCss).toBePromise();
|
||||||
|
PromiseWrapper.then(loadedCss,
|
||||||
|
function(css) {
|
||||||
|
expect(css).toEqual('.one {}\n.two {}\n.main {}');
|
||||||
|
async.done();
|
||||||
|
},
|
||||||
|
function(e) { throw 'fail;' });
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should inline nested @import rules',
|
||||||
|
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
||||||
|
xhr.reply('http://base/one.css', '@import "two.css";.one {}');
|
||||||
|
xhr.reply('http://base/two.css', '.two {}');
|
||||||
|
var css = '@import "one.css";.main {}';
|
||||||
|
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||||
|
expect(loadedCss).toBePromise();
|
||||||
|
PromiseWrapper.then(loadedCss,
|
||||||
|
function(css) {
|
||||||
|
expect(css).toEqual('.two {}\n.one {}\n.main {}');
|
||||||
|
async.done();
|
||||||
|
},
|
||||||
|
function(e) { throw 'fail;' });
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should handle circular dependencies gracefuly',
|
||||||
|
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
||||||
|
xhr.reply('http://base/one.css', '@import "two.css";.one {}');
|
||||||
|
xhr.reply('http://base/two.css', '@import "one.css";.two {}');
|
||||||
|
var css = '@import "one.css";.main {}';
|
||||||
|
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||||
|
expect(loadedCss).toBePromise();
|
||||||
|
PromiseWrapper.then(loadedCss,
|
||||||
|
function(css) {
|
||||||
|
expect(css).toEqual('.two {}\n.one {}\n.main {}');
|
||||||
|
async.done();
|
||||||
|
},
|
||||||
|
function(e) { throw 'fail;' });
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should handle invalid @import fracefuly',
|
||||||
|
inject([StyleInliner, AsyncTestCompleter], (inliner, async) => {
|
||||||
|
// Invalid rule: the url is not quoted
|
||||||
|
var css = '@import one.css;.main {}';
|
||||||
|
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||||
|
expect(loadedCss).toBePromise();
|
||||||
|
PromiseWrapper.then(
|
||||||
|
loadedCss,
|
||||||
|
function(css) {
|
||||||
|
expect(css).toEqual('/* Invalid import rule: "@import one.css;" */.main {}');
|
||||||
|
async.done();
|
||||||
|
},
|
||||||
|
function(e) { throw 'fail;' });
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('media query', () => {
|
||||||
|
it('should wrap inlined content in media query',
|
||||||
|
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
||||||
|
xhr.reply('http://base/one.css', '.one {}');
|
||||||
|
var css = '@import "one.css" (min-width: 700px) and (orientation: landscape);';
|
||||||
|
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||||
|
expect(loadedCss).toBePromise();
|
||||||
|
PromiseWrapper.then(
|
||||||
|
loadedCss,
|
||||||
|
function(css) {
|
||||||
|
expect(css).toEqual(
|
||||||
|
'@media (min-width: 700px) and (orientation: landscape) {\n.one {}\n}\n');
|
||||||
|
async.done();
|
||||||
|
},
|
||||||
|
function(e) { throw 'fail;' });
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('url rewritting', () => {
|
||||||
|
it('should rewrite url in inlined content',
|
||||||
|
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
||||||
|
// it should rewrite both '@import' and 'url()'
|
||||||
|
xhr.reply('http://base/one.css',
|
||||||
|
'@import "./nested/two.css";.one {background-image: url("one.jpg");}');
|
||||||
|
xhr.reply('http://base/nested/two.css',
|
||||||
|
'.two {background-image: url("../img/two.jpg");}');
|
||||||
|
var css = '@import "one.css";';
|
||||||
|
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||||
|
expect(loadedCss).toBePromise();
|
||||||
|
PromiseWrapper.then(
|
||||||
|
loadedCss,
|
||||||
|
function(css) {
|
||||||
|
expect(css).toEqual(".two {background-image: url('http://base/img/two.jpg');}\n" +
|
||||||
|
".one {background-image: url('http://base/one.jpg');}\n");
|
||||||
|
async.done();
|
||||||
|
},
|
||||||
|
function(e) { throw 'fail;' });
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeXHR extends XHR {
|
||||||
|
_responses: Map<string, string>;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._responses = MapWrapper.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
get(url: string): Promise<string> {
|
||||||
|
var response = MapWrapper.get(this._responses, url);
|
||||||
|
if (isBlank(response)) {
|
||||||
|
return PromiseWrapper.reject('xhr error', null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PromiseWrapper.resolve(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
reply(url: string, response: string) { MapWrapper.set(this._responses, url, response); }
|
||||||
|
}
|
|
@ -74,7 +74,5 @@ export function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeUrlResolver extends UrlResolver {
|
class FakeUrlResolver extends UrlResolver {
|
||||||
resolve(baseUrl: string, url: string): string {
|
resolve(baseUrl: string, url: string): string { return baseUrl + '/' + url; }
|
||||||
return baseUrl + '/' + url;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,507 +0,0 @@
|
||||||
import {
|
|
||||||
AsyncTestCompleter,
|
|
||||||
beforeEach,
|
|
||||||
ddescribe,
|
|
||||||
describe,
|
|
||||||
el,
|
|
||||||
elementText,
|
|
||||||
expect,
|
|
||||||
iit,
|
|
||||||
inject,
|
|
||||||
it,
|
|
||||||
xit,
|
|
||||||
beforeEachBindings,
|
|
||||||
SpyObject,
|
|
||||||
} from 'angular2/test_lib';
|
|
||||||
|
|
||||||
import {bind} from 'angular2/di';
|
|
||||||
import {MapWrapper, ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
|
||||||
|
|
||||||
import {
|
|
||||||
ViewDefinition, DirectiveMetadata
|
|
||||||
} from 'angular2/src/render/api';
|
|
||||||
|
|
||||||
import {ShadowDomStrategy} from 'angular2/src/render/dom/shadow_dom/shadow_dom_strategy';
|
|
||||||
import {EmulatedScopedShadowDomStrategy} from 'angular2/src/render/dom/shadow_dom/emulated_scoped_shadow_dom_strategy';
|
|
||||||
import {EmulatedUnscopedShadowDomStrategy} from 'angular2/src/render/dom/shadow_dom/emulated_unscoped_shadow_dom_strategy';
|
|
||||||
import {NativeShadowDomStrategy} from 'angular2/src/render/dom/shadow_dom/native_shadow_dom_strategy';
|
|
||||||
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
|
|
||||||
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
|
|
||||||
|
|
||||||
import {DomTestbed} from './dom_testbed';
|
|
||||||
|
|
||||||
export function main() {
|
|
||||||
describe('ShadowDom integration tests', function() {
|
|
||||||
var strategies = {
|
|
||||||
"scoped" : bind(ShadowDomStrategy).toFactory(
|
|
||||||
(styleInliner, styleUrlResolver) => new EmulatedScopedShadowDomStrategy(styleInliner, styleUrlResolver, null),
|
|
||||||
[StyleInliner, StyleUrlResolver]),
|
|
||||||
"unscoped" : bind(ShadowDomStrategy).toFactory(
|
|
||||||
(styleUrlResolver) => new EmulatedUnscopedShadowDomStrategy(styleUrlResolver, null),
|
|
||||||
[StyleUrlResolver])
|
|
||||||
}
|
|
||||||
if (DOM.supportsNativeShadowDOM()) {
|
|
||||||
StringMapWrapper.set(strategies, "native", bind(ShadowDomStrategy).toFactory(
|
|
||||||
(styleUrlResolver) => new NativeShadowDomStrategy(styleUrlResolver),
|
|
||||||
[StyleUrlResolver])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringMapWrapper.forEach(strategies,
|
|
||||||
(strategyBinding, name) => {
|
|
||||||
|
|
||||||
beforeEachBindings( () => {
|
|
||||||
return [strategyBinding, DomTestbed];
|
|
||||||
});
|
|
||||||
|
|
||||||
describe(`${name} shadow dom strategy`, () => {
|
|
||||||
|
|
||||||
it('should support simple components', inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([
|
|
||||||
mainDir,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'main',
|
|
||||||
template: '<simple>' +
|
|
||||||
'<div>A</div>' +
|
|
||||||
'</simple>',
|
|
||||||
directives: [simple]
|
|
||||||
}),
|
|
||||||
simpleTemplate
|
|
||||||
]).then( (protoViews) => {
|
|
||||||
tb.createRootViews(protoViews);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('SIMPLE(A)');
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should not show the light dom even if there is not content tag', inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([
|
|
||||||
mainDir,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'main',
|
|
||||||
template: '<empty>' +
|
|
||||||
'<div>A</div>' +
|
|
||||||
'</empty>',
|
|
||||||
directives: [empty]
|
|
||||||
}),
|
|
||||||
emptyTemplate
|
|
||||||
]).then( (protoViews) => {
|
|
||||||
tb.createRootViews(protoViews);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('');
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should support dynamic components', inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([
|
|
||||||
mainDir,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'main',
|
|
||||||
template: '<dynamic>' +
|
|
||||||
'<div>A</div>' +
|
|
||||||
'</dynamic>',
|
|
||||||
directives: [dynamicComponent]
|
|
||||||
}),
|
|
||||||
simpleTemplate
|
|
||||||
]).then( (protoViews) => {
|
|
||||||
var views = tb.createRootViews(ListWrapper.slice(protoViews, 0, 2));
|
|
||||||
tb.createComponentView(views[1].viewRef, 0, protoViews[2]);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('SIMPLE(A)');
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should support multiple content tags', inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([
|
|
||||||
mainDir,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'main',
|
|
||||||
template: '<multiple-content-tags>' +
|
|
||||||
'<div>B</div>' +
|
|
||||||
'<div>C</div>' +
|
|
||||||
'<div class="left">A</div>' +
|
|
||||||
'</multiple-content-tags>',
|
|
||||||
directives: [multipleContentTagsComponent]
|
|
||||||
}),
|
|
||||||
multipleContentTagsTemplate
|
|
||||||
]).then( (protoViews) => {
|
|
||||||
tb.createRootViews(protoViews);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('(A, BC)');
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should redistribute only direct children', inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([
|
|
||||||
mainDir,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'main',
|
|
||||||
template: '<multiple-content-tags>' +
|
|
||||||
'<div>B<div class="left">A</div></div>' +
|
|
||||||
'<div>C</div>' +
|
|
||||||
'</multiple-content-tags>',
|
|
||||||
directives: [multipleContentTagsComponent]
|
|
||||||
}),
|
|
||||||
multipleContentTagsTemplate
|
|
||||||
]).then( (protoViews) => {
|
|
||||||
tb.createRootViews(protoViews);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('(, BAC)');
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it("should redistribute direct child viewcontainers when the light dom changes",
|
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([
|
|
||||||
mainDir,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'main',
|
|
||||||
template: '<multiple-content-tags>' +
|
|
||||||
'<div><div template="manual" class="left">A</div></div>' +
|
|
||||||
'<div>B</div>' +
|
|
||||||
'</multiple-content-tags>',
|
|
||||||
directives: [multipleContentTagsComponent, manualViewportDirective]
|
|
||||||
}),
|
|
||||||
multipleContentTagsTemplate
|
|
||||||
]).then( (protoViews) => {
|
|
||||||
var views = tb.createRootViews(protoViews);
|
|
||||||
var childProtoView = protoViews[1].elementBinders[1].nestedProtoView;
|
|
||||||
expect(tb.rootEl).toHaveText('(, B)');
|
|
||||||
|
|
||||||
var childView = tb.createViewInContainer(views[1].viewRef, 1, 0, childProtoView);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('(, AB)');
|
|
||||||
|
|
||||||
tb.destroyViewInContainer(views[1].viewRef, 1, 0, childView.viewRef);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('(, B)');
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it("should redistribute when the light dom changes",
|
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([
|
|
||||||
mainDir,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'main',
|
|
||||||
template: '<multiple-content-tags>' +
|
|
||||||
'<div template="manual" class="left">A</div>' +
|
|
||||||
'<div>B</div>' +
|
|
||||||
'</multiple-content-tags>',
|
|
||||||
directives: [multipleContentTagsComponent, manualViewportDirective]
|
|
||||||
}),
|
|
||||||
multipleContentTagsTemplate
|
|
||||||
]).then( (protoViews) => {
|
|
||||||
var views = tb.createRootViews(protoViews);
|
|
||||||
var childProtoView = protoViews[1].elementBinders[1].nestedProtoView;
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('(, B)');
|
|
||||||
|
|
||||||
var childView = tb.createViewInContainer(views[1].viewRef, 1, 0, childProtoView);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('(A, B)');
|
|
||||||
|
|
||||||
tb.destroyViewInContainer(views[1].viewRef, 1, 0, childView.viewRef);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('(, B)');
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it("should support nested components", inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([
|
|
||||||
mainDir,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'main',
|
|
||||||
template: '<outer-with-indirect-nested>' +
|
|
||||||
'<div>A</div>' +
|
|
||||||
'<div>B</div>' +
|
|
||||||
'</outer-with-indirect-nested>',
|
|
||||||
directives: [outerWithIndirectNestedComponent]
|
|
||||||
}),
|
|
||||||
outerWithIndirectNestedTemplate,
|
|
||||||
simpleTemplate
|
|
||||||
]).then( (protoViews) => {
|
|
||||||
tb.createRootViews(protoViews);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('OUTER(SIMPLE(AB))');
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it("should support nesting with content being direct child of a nested component",
|
|
||||||
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([
|
|
||||||
mainDir,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'main',
|
|
||||||
template: '<outer>' +
|
|
||||||
'<div template="manual" class="left">A</div>' +
|
|
||||||
'<div>B</div>' +
|
|
||||||
'<div>C</div>' +
|
|
||||||
'</outer>',
|
|
||||||
directives: [outerComponent, manualViewportDirective]
|
|
||||||
}),
|
|
||||||
outerTemplate,
|
|
||||||
innerTemplate,
|
|
||||||
innerInnerTemplate
|
|
||||||
]).then( (protoViews) => {
|
|
||||||
var views = tb.createRootViews(protoViews);
|
|
||||||
var childProtoView = protoViews[1].elementBinders[1].nestedProtoView;
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('OUTER(INNER(INNERINNER(,BC)))');
|
|
||||||
|
|
||||||
tb.createViewInContainer(views[1].viewRef, 1, 0, childProtoView);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('OUTER(INNER(INNERINNER(A,BC)))');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should redistribute when the shadow dom changes', inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([
|
|
||||||
mainDir,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'main',
|
|
||||||
template: '<conditional-content>' +
|
|
||||||
'<div class="left">A</div>' +
|
|
||||||
'<div>B</div>' +
|
|
||||||
'<div>C</div>' +
|
|
||||||
'</conditional-content>',
|
|
||||||
directives: [conditionalContentComponent]
|
|
||||||
}),
|
|
||||||
conditionalContentTemplate
|
|
||||||
]).then( (protoViews) => {
|
|
||||||
var views = tb.createRootViews(protoViews);
|
|
||||||
var childProtoView = protoViews[2].elementBinders[0].nestedProtoView;
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('(, ABC)');
|
|
||||||
|
|
||||||
var childView = tb.createViewInContainer(views[2].viewRef, 0, 0, childProtoView);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('(A, BC)');
|
|
||||||
|
|
||||||
tb.destroyViewInContainer(views[2].viewRef, 0, 0, childView.viewRef);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('(, ABC)');
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it("should support tabs with view caching", inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
|
||||||
tb.compileAll([
|
|
||||||
mainDir,
|
|
||||||
new ViewDefinition({
|
|
||||||
componentId: 'main',
|
|
||||||
template:
|
|
||||||
'(<tab><span>0</span></tab>'+
|
|
||||||
'<tab><span>1</span></tab>'+
|
|
||||||
'<tab><span>2</span></tab>)',
|
|
||||||
directives: [tabComponent]
|
|
||||||
}),
|
|
||||||
tabTemplate
|
|
||||||
]).then( (protoViews) => {
|
|
||||||
var views = tb.createRootViews(ListWrapper.slice(protoViews, 0, 2));
|
|
||||||
var tabProtoView = protoViews[2];
|
|
||||||
var tabChildProtoView = tabProtoView.elementBinders[0].nestedProtoView;
|
|
||||||
|
|
||||||
var tab1View = tb.createComponentView(views[1].viewRef, 0, tabProtoView);
|
|
||||||
var tab2View = tb.createComponentView(views[1].viewRef, 1, tabProtoView);
|
|
||||||
var tab3View = tb.createComponentView(views[1].viewRef, 2, tabProtoView);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('()');
|
|
||||||
|
|
||||||
var tabChildView = tb.createViewInContainer(tab1View.viewRef, 0, 0, tabChildProtoView);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('(TAB(0))');
|
|
||||||
|
|
||||||
tb.renderer.dehydrateView(tabChildView.viewRef);
|
|
||||||
tb.renderer.detachViewInContainer(tab1View.viewRef, 0, 0, tabChildView.viewRef);
|
|
||||||
|
|
||||||
tb.renderer.attachViewInContainer(tab2View.viewRef, 0, 0, tabChildView.viewRef);
|
|
||||||
tb.renderer.hydrateView(tabChildView.viewRef);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('(TAB(1))');
|
|
||||||
|
|
||||||
tb.renderer.dehydrateView(tabChildView.viewRef);
|
|
||||||
tb.renderer.detachViewInContainer(tab2View.viewRef, 0, 0, tabChildView.viewRef);
|
|
||||||
|
|
||||||
tb.renderer.attachViewInContainer(tab3View.viewRef, 0, 0, tabChildView.viewRef);
|
|
||||||
tb.renderer.hydrateView(tabChildView.viewRef);
|
|
||||||
|
|
||||||
expect(tb.rootEl).toHaveText('(TAB(2))');
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
//Implement once ElementRef support changing a class
|
|
||||||
//it("should redistribute when a class has been added or removed");
|
|
||||||
//it('should not lose focus', () => {
|
|
||||||
// var temp = `<simple>aaa<input type="text" id="focused-input" ng-class="{'aClass' : showClass}"> bbb</simple>`;
|
|
||||||
//
|
|
||||||
// compile(temp, (view, lc) => {
|
|
||||||
// var input = view.rootNodes[1];
|
|
||||||
// input.focus();
|
|
||||||
//
|
|
||||||
// expect(document.activeElement.id).toEqual("focused-input");
|
|
||||||
//
|
|
||||||
// // update class of input
|
|
||||||
//
|
|
||||||
// expect(document.activeElement.id).toEqual("focused-input");
|
|
||||||
// });
|
|
||||||
//});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var mainDir = new DirectiveMetadata({
|
|
||||||
selector: 'main',
|
|
||||||
id: 'main',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var simple = new DirectiveMetadata({
|
|
||||||
selector: 'simple',
|
|
||||||
id: 'simple',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var empty = new DirectiveMetadata({
|
|
||||||
selector: 'empty',
|
|
||||||
id: 'empty',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var dynamicComponent = new DirectiveMetadata({
|
|
||||||
selector: 'dynamic',
|
|
||||||
id: 'dynamic',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var multipleContentTagsComponent = new DirectiveMetadata({
|
|
||||||
selector: 'multiple-content-tags',
|
|
||||||
id: 'multiple-content-tags',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var manualViewportDirective = new DirectiveMetadata({
|
|
||||||
selector: '[manual]',
|
|
||||||
id: 'manual',
|
|
||||||
type: DirectiveMetadata.DIRECTIVE_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var outerWithIndirectNestedComponent = new DirectiveMetadata({
|
|
||||||
selector: 'outer-with-indirect-nested',
|
|
||||||
id: 'outer-with-indirect-nested',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var outerComponent = new DirectiveMetadata({
|
|
||||||
selector: 'outer',
|
|
||||||
id: 'outer',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var innerComponent = new DirectiveMetadata({
|
|
||||||
selector: 'inner',
|
|
||||||
id: 'inner',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var innerInnerComponent = new DirectiveMetadata({
|
|
||||||
selector: 'innerinner',
|
|
||||||
id: 'innerinner',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var conditionalContentComponent = new DirectiveMetadata({
|
|
||||||
selector: 'conditional-content',
|
|
||||||
id: 'conditional-content',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var autoViewportDirective = new DirectiveMetadata({
|
|
||||||
selector: '[auto]',
|
|
||||||
id: '[auto]',
|
|
||||||
type: DirectiveMetadata.DIRECTIVE_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var tabComponent = new DirectiveMetadata({
|
|
||||||
selector: 'tab',
|
|
||||||
id: 'tab',
|
|
||||||
type: DirectiveMetadata.COMPONENT_TYPE
|
|
||||||
});
|
|
||||||
|
|
||||||
var simpleTemplate = new ViewDefinition({
|
|
||||||
componentId: 'simple',
|
|
||||||
template: 'SIMPLE(<content></content>)',
|
|
||||||
directives: []
|
|
||||||
});
|
|
||||||
|
|
||||||
var emptyTemplate = new ViewDefinition({
|
|
||||||
componentId: 'empty',
|
|
||||||
template: '',
|
|
||||||
directives: []
|
|
||||||
});
|
|
||||||
|
|
||||||
var multipleContentTagsTemplate = new ViewDefinition({
|
|
||||||
componentId: 'multiple-content-tags',
|
|
||||||
template: '(<content select=".left"></content>, <content></content>)',
|
|
||||||
directives: []
|
|
||||||
});
|
|
||||||
|
|
||||||
var outerWithIndirectNestedTemplate = new ViewDefinition({
|
|
||||||
componentId: 'outer-with-indirect-nested',
|
|
||||||
template: 'OUTER(<simple><div><content></content></div></simple>)',
|
|
||||||
directives: [simple]
|
|
||||||
});
|
|
||||||
|
|
||||||
var outerTemplate = new ViewDefinition({
|
|
||||||
componentId: 'outer',
|
|
||||||
template: 'OUTER(<inner><content></content></inner>)',
|
|
||||||
directives: [innerComponent]
|
|
||||||
});
|
|
||||||
|
|
||||||
var innerTemplate = new ViewDefinition({
|
|
||||||
componentId: 'inner',
|
|
||||||
template: 'INNER(<innerinner><content></content></innerinner>)',
|
|
||||||
directives: [innerInnerComponent]
|
|
||||||
});
|
|
||||||
|
|
||||||
var innerInnerTemplate = new ViewDefinition({
|
|
||||||
componentId: 'innerinner',
|
|
||||||
template: 'INNERINNER(<content select=".left"></content>,<content></content>)',
|
|
||||||
directives: []
|
|
||||||
});
|
|
||||||
|
|
||||||
var conditionalContentTemplate = new ViewDefinition({
|
|
||||||
componentId: 'conditional-content',
|
|
||||||
template: '<div>(<div *auto="cond"><content select=".left"></content></div>, <content></content>)</div>',
|
|
||||||
directives: [autoViewportDirective]
|
|
||||||
});
|
|
||||||
|
|
||||||
var tabTemplate = new ViewDefinition({
|
|
||||||
componentId: 'tab',
|
|
||||||
template: '<div><div *auto="cond">TAB(<content></content>)</div></div>',
|
|
||||||
directives: [autoViewportDirective]
|
|
||||||
});
|
|
|
@ -0,0 +1,495 @@
|
||||||
|
import {
|
||||||
|
AsyncTestCompleter,
|
||||||
|
beforeEach,
|
||||||
|
ddescribe,
|
||||||
|
describe,
|
||||||
|
el,
|
||||||
|
expect,
|
||||||
|
iit,
|
||||||
|
inject,
|
||||||
|
it,
|
||||||
|
xit,
|
||||||
|
beforeEachBindings,
|
||||||
|
SpyObject,
|
||||||
|
} from 'angular2/test_lib';
|
||||||
|
|
||||||
|
import {bind} from 'angular2/di';
|
||||||
|
import {MapWrapper, ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
|
|
||||||
|
import {ViewDefinition, DirectiveMetadata} from 'angular2/src/render/api';
|
||||||
|
|
||||||
|
import {ShadowDomStrategy} from 'angular2/src/render/dom/shadow_dom/shadow_dom_strategy';
|
||||||
|
import {
|
||||||
|
EmulatedScopedShadowDomStrategy
|
||||||
|
} from 'angular2/src/render/dom/shadow_dom/emulated_scoped_shadow_dom_strategy';
|
||||||
|
import {
|
||||||
|
EmulatedUnscopedShadowDomStrategy
|
||||||
|
} from 'angular2/src/render/dom/shadow_dom/emulated_unscoped_shadow_dom_strategy';
|
||||||
|
import {
|
||||||
|
NativeShadowDomStrategy
|
||||||
|
} from 'angular2/src/render/dom/shadow_dom/native_shadow_dom_strategy';
|
||||||
|
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
|
||||||
|
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
|
||||||
|
|
||||||
|
import {DomTestbed} from './dom_testbed';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe('ShadowDom integration tests', function() {
|
||||||
|
var strategies = {
|
||||||
|
"scoped":
|
||||||
|
bind(ShadowDomStrategy)
|
||||||
|
.toFactory((styleInliner, styleUrlResolver) => new EmulatedScopedShadowDomStrategy(
|
||||||
|
styleInliner, styleUrlResolver, null),
|
||||||
|
[StyleInliner, StyleUrlResolver]),
|
||||||
|
"unscoped": bind(ShadowDomStrategy)
|
||||||
|
.toFactory((styleUrlResolver) =>
|
||||||
|
new EmulatedUnscopedShadowDomStrategy(styleUrlResolver, null),
|
||||||
|
[StyleUrlResolver])
|
||||||
|
};
|
||||||
|
if (DOM.supportsNativeShadowDOM()) {
|
||||||
|
StringMapWrapper.set(
|
||||||
|
strategies, "native",
|
||||||
|
bind(ShadowDomStrategy)
|
||||||
|
.toFactory((styleUrlResolver) => new NativeShadowDomStrategy(styleUrlResolver),
|
||||||
|
[StyleUrlResolver]));
|
||||||
|
}
|
||||||
|
|
||||||
|
StringMapWrapper.forEach(strategies, (strategyBinding, name) => {
|
||||||
|
|
||||||
|
beforeEachBindings(() => { return [strategyBinding, DomTestbed]; });
|
||||||
|
|
||||||
|
describe(`${name} shadow dom strategy`, () => {
|
||||||
|
|
||||||
|
it('should support simple components',
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
mainDir,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'main',
|
||||||
|
template: '<simple>' +
|
||||||
|
'<div>A</div>' +
|
||||||
|
'</simple>',
|
||||||
|
directives: [simple]
|
||||||
|
}),
|
||||||
|
simpleTemplate
|
||||||
|
])
|
||||||
|
.then((protoViews) => {
|
||||||
|
tb.createRootViews(protoViews);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('SIMPLE(A)');
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should not show the light dom even if there is not content tag',
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
mainDir,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'main',
|
||||||
|
template: '<empty>' +
|
||||||
|
'<div>A</div>' +
|
||||||
|
'</empty>',
|
||||||
|
directives: [empty]
|
||||||
|
}),
|
||||||
|
emptyTemplate
|
||||||
|
])
|
||||||
|
.then((protoViews) => {
|
||||||
|
tb.createRootViews(protoViews);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('');
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should support dynamic components',
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
mainDir,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'main',
|
||||||
|
template: '<dynamic>' +
|
||||||
|
'<div>A</div>' +
|
||||||
|
'</dynamic>',
|
||||||
|
directives: [dynamicComponent]
|
||||||
|
}),
|
||||||
|
simpleTemplate
|
||||||
|
])
|
||||||
|
.then((protoViews) => {
|
||||||
|
var views = tb.createRootViews(ListWrapper.slice(protoViews, 0, 2));
|
||||||
|
tb.createComponentView(views[1].viewRef, 0, protoViews[2]);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('SIMPLE(A)');
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should support multiple content tags',
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
mainDir,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'main',
|
||||||
|
template: '<multiple-content-tags>' +
|
||||||
|
'<div>B</div>' +
|
||||||
|
'<div>C</div>' +
|
||||||
|
'<div class="left">A</div>' +
|
||||||
|
'</multiple-content-tags>',
|
||||||
|
directives: [multipleContentTagsComponent]
|
||||||
|
}),
|
||||||
|
multipleContentTagsTemplate
|
||||||
|
])
|
||||||
|
.then((protoViews) => {
|
||||||
|
tb.createRootViews(protoViews);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('(A, BC)');
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should redistribute only direct children',
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
mainDir,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'main',
|
||||||
|
template: '<multiple-content-tags>' +
|
||||||
|
'<div>B<div class="left">A</div></div>' +
|
||||||
|
'<div>C</div>' +
|
||||||
|
'</multiple-content-tags>',
|
||||||
|
directives: [multipleContentTagsComponent]
|
||||||
|
}),
|
||||||
|
multipleContentTagsTemplate
|
||||||
|
])
|
||||||
|
.then((protoViews) => {
|
||||||
|
tb.createRootViews(protoViews);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('(, BAC)');
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it("should redistribute direct child viewcontainers when the light dom changes",
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
mainDir,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'main',
|
||||||
|
template: '<multiple-content-tags>' +
|
||||||
|
'<div><div template="manual" class="left">A</div></div>' +
|
||||||
|
'<div>B</div>' +
|
||||||
|
'</multiple-content-tags>',
|
||||||
|
directives: [multipleContentTagsComponent, manualViewportDirective]
|
||||||
|
}),
|
||||||
|
multipleContentTagsTemplate
|
||||||
|
])
|
||||||
|
.then((protoViews) => {
|
||||||
|
var views = tb.createRootViews(protoViews);
|
||||||
|
var childProtoView = protoViews[1].elementBinders[1].nestedProtoView;
|
||||||
|
expect(tb.rootEl).toHaveText('(, B)');
|
||||||
|
|
||||||
|
var childView = tb.createViewInContainer(views[1].viewRef, 1, 0, childProtoView);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('(, AB)');
|
||||||
|
|
||||||
|
tb.destroyViewInContainer(views[1].viewRef, 1, 0, childView.viewRef);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('(, B)');
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it("should redistribute when the light dom changes",
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
mainDir,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'main',
|
||||||
|
template: '<multiple-content-tags>' +
|
||||||
|
'<div template="manual" class="left">A</div>' +
|
||||||
|
'<div>B</div>' +
|
||||||
|
'</multiple-content-tags>',
|
||||||
|
directives: [multipleContentTagsComponent, manualViewportDirective]
|
||||||
|
}),
|
||||||
|
multipleContentTagsTemplate
|
||||||
|
])
|
||||||
|
.then((protoViews) => {
|
||||||
|
var views = tb.createRootViews(protoViews);
|
||||||
|
var childProtoView = protoViews[1].elementBinders[1].nestedProtoView;
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('(, B)');
|
||||||
|
|
||||||
|
var childView = tb.createViewInContainer(views[1].viewRef, 1, 0, childProtoView);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('(A, B)');
|
||||||
|
|
||||||
|
tb.destroyViewInContainer(views[1].viewRef, 1, 0, childView.viewRef);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('(, B)');
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it("should support nested components",
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
mainDir,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'main',
|
||||||
|
template: '<outer-with-indirect-nested>' +
|
||||||
|
'<div>A</div>' +
|
||||||
|
'<div>B</div>' +
|
||||||
|
'</outer-with-indirect-nested>',
|
||||||
|
directives: [outerWithIndirectNestedComponent]
|
||||||
|
}),
|
||||||
|
outerWithIndirectNestedTemplate,
|
||||||
|
simpleTemplate
|
||||||
|
])
|
||||||
|
.then((protoViews) => {
|
||||||
|
tb.createRootViews(protoViews);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('OUTER(SIMPLE(AB))');
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it("should support nesting with content being direct child of a nested component",
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
mainDir,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'main',
|
||||||
|
template: '<outer>' +
|
||||||
|
'<div template="manual" class="left">A</div>' +
|
||||||
|
'<div>B</div>' +
|
||||||
|
'<div>C</div>' +
|
||||||
|
'</outer>',
|
||||||
|
directives: [outerComponent, manualViewportDirective]
|
||||||
|
}),
|
||||||
|
outerTemplate,
|
||||||
|
innerTemplate,
|
||||||
|
innerInnerTemplate
|
||||||
|
])
|
||||||
|
.then((protoViews) => {
|
||||||
|
var views = tb.createRootViews(protoViews);
|
||||||
|
var childProtoView = protoViews[1].elementBinders[1].nestedProtoView;
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('OUTER(INNER(INNERINNER(,BC)))');
|
||||||
|
|
||||||
|
tb.createViewInContainer(views[1].viewRef, 1, 0, childProtoView);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('OUTER(INNER(INNERINNER(A,BC)))');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should redistribute when the shadow dom changes',
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
mainDir,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'main',
|
||||||
|
template: '<conditional-content>' +
|
||||||
|
'<div class="left">A</div>' +
|
||||||
|
'<div>B</div>' +
|
||||||
|
'<div>C</div>' +
|
||||||
|
'</conditional-content>',
|
||||||
|
directives: [conditionalContentComponent]
|
||||||
|
}),
|
||||||
|
conditionalContentTemplate
|
||||||
|
])
|
||||||
|
.then((protoViews) => {
|
||||||
|
var views = tb.createRootViews(protoViews);
|
||||||
|
var childProtoView = protoViews[2].elementBinders[0].nestedProtoView;
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('(, ABC)');
|
||||||
|
|
||||||
|
var childView = tb.createViewInContainer(views[2].viewRef, 0, 0, childProtoView);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('(A, BC)');
|
||||||
|
|
||||||
|
tb.destroyViewInContainer(views[2].viewRef, 0, 0, childView.viewRef);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('(, ABC)');
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it("should support tabs with view caching",
|
||||||
|
inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
|
||||||
|
tb.compileAll([
|
||||||
|
mainDir,
|
||||||
|
new ViewDefinition({
|
||||||
|
componentId: 'main',
|
||||||
|
template: '(<tab><span>0</span></tab>' +
|
||||||
|
'<tab><span>1</span></tab>' +
|
||||||
|
'<tab><span>2</span></tab>)',
|
||||||
|
directives: [tabComponent]
|
||||||
|
}),
|
||||||
|
tabTemplate
|
||||||
|
])
|
||||||
|
.then((protoViews) => {
|
||||||
|
var views = tb.createRootViews(ListWrapper.slice(protoViews, 0, 2));
|
||||||
|
var tabProtoView = protoViews[2];
|
||||||
|
var tabChildProtoView = tabProtoView.elementBinders[0].nestedProtoView;
|
||||||
|
|
||||||
|
var tab1View = tb.createComponentView(views[1].viewRef, 0, tabProtoView);
|
||||||
|
var tab2View = tb.createComponentView(views[1].viewRef, 1, tabProtoView);
|
||||||
|
var tab3View = tb.createComponentView(views[1].viewRef, 2, tabProtoView);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('()');
|
||||||
|
|
||||||
|
var tabChildView =
|
||||||
|
tb.createViewInContainer(tab1View.viewRef, 0, 0, tabChildProtoView);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('(TAB(0))');
|
||||||
|
|
||||||
|
tb.renderer.dehydrateView(tabChildView.viewRef);
|
||||||
|
tb.renderer.detachViewInContainer(tab1View.viewRef, 0, 0, tabChildView.viewRef);
|
||||||
|
|
||||||
|
tb.renderer.attachViewInContainer(tab2View.viewRef, 0, 0, tabChildView.viewRef);
|
||||||
|
tb.renderer.hydrateView(tabChildView.viewRef);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('(TAB(1))');
|
||||||
|
|
||||||
|
tb.renderer.dehydrateView(tabChildView.viewRef);
|
||||||
|
tb.renderer.detachViewInContainer(tab2View.viewRef, 0, 0, tabChildView.viewRef);
|
||||||
|
|
||||||
|
tb.renderer.attachViewInContainer(tab3View.viewRef, 0, 0, tabChildView.viewRef);
|
||||||
|
tb.renderer.hydrateView(tabChildView.viewRef);
|
||||||
|
|
||||||
|
expect(tb.rootEl).toHaveText('(TAB(2))');
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Implement once ElementRef support changing a class
|
||||||
|
// it("should redistribute when a class has been added or removed");
|
||||||
|
// it('should not lose focus', () => {
|
||||||
|
// var temp = `<simple>aaa<input type="text" id="focused-input" ng-class="{'aClass' :
|
||||||
|
// showClass}"> bbb</simple>`;
|
||||||
|
//
|
||||||
|
// compile(temp, (view, lc) => {
|
||||||
|
// var input = view.rootNodes[1];
|
||||||
|
// input.focus();
|
||||||
|
//
|
||||||
|
// expect(document.activeElement.id).toEqual("focused-input");
|
||||||
|
//
|
||||||
|
// // update class of input
|
||||||
|
//
|
||||||
|
// expect(document.activeElement.id).toEqual("focused-input");
|
||||||
|
// });
|
||||||
|
//});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var mainDir =
|
||||||
|
new DirectiveMetadata({selector: 'main', id: 'main', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||||
|
|
||||||
|
var simple = new DirectiveMetadata(
|
||||||
|
{selector: 'simple', id: 'simple', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||||
|
|
||||||
|
var empty = new DirectiveMetadata(
|
||||||
|
{selector: 'empty', id: 'empty', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||||
|
|
||||||
|
var dynamicComponent = new DirectiveMetadata(
|
||||||
|
{selector: 'dynamic', id: 'dynamic', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||||
|
|
||||||
|
var multipleContentTagsComponent = new DirectiveMetadata({
|
||||||
|
selector: 'multiple-content-tags',
|
||||||
|
id: 'multiple-content-tags',
|
||||||
|
type: DirectiveMetadata.COMPONENT_TYPE
|
||||||
|
});
|
||||||
|
|
||||||
|
var manualViewportDirective = new DirectiveMetadata(
|
||||||
|
{selector: '[manual]', id: 'manual', type: DirectiveMetadata.DIRECTIVE_TYPE});
|
||||||
|
|
||||||
|
var outerWithIndirectNestedComponent = new DirectiveMetadata({
|
||||||
|
selector: 'outer-with-indirect-nested',
|
||||||
|
id: 'outer-with-indirect-nested',
|
||||||
|
type: DirectiveMetadata.COMPONENT_TYPE
|
||||||
|
});
|
||||||
|
|
||||||
|
var outerComponent = new DirectiveMetadata(
|
||||||
|
{selector: 'outer', id: 'outer', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||||
|
|
||||||
|
var innerComponent = new DirectiveMetadata(
|
||||||
|
{selector: 'inner', id: 'inner', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||||
|
|
||||||
|
var innerInnerComponent = new DirectiveMetadata(
|
||||||
|
{selector: 'innerinner', id: 'innerinner', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||||
|
|
||||||
|
var conditionalContentComponent = new DirectiveMetadata({
|
||||||
|
selector: 'conditional-content',
|
||||||
|
id: 'conditional-content',
|
||||||
|
type: DirectiveMetadata.COMPONENT_TYPE
|
||||||
|
});
|
||||||
|
|
||||||
|
var autoViewportDirective = new DirectiveMetadata(
|
||||||
|
{selector: '[auto]', id: '[auto]', type: DirectiveMetadata.DIRECTIVE_TYPE});
|
||||||
|
|
||||||
|
var tabComponent =
|
||||||
|
new DirectiveMetadata({selector: 'tab', id: 'tab', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||||
|
|
||||||
|
var simpleTemplate = new ViewDefinition(
|
||||||
|
{componentId: 'simple', template: 'SIMPLE(<content></content>)', directives: []});
|
||||||
|
|
||||||
|
var emptyTemplate = new ViewDefinition({componentId: 'empty', template: '', directives: []});
|
||||||
|
|
||||||
|
var multipleContentTagsTemplate = new ViewDefinition({
|
||||||
|
componentId: 'multiple-content-tags',
|
||||||
|
template: '(<content select=".left"></content>, <content></content>)',
|
||||||
|
directives: []
|
||||||
|
});
|
||||||
|
|
||||||
|
var outerWithIndirectNestedTemplate = new ViewDefinition({
|
||||||
|
componentId: 'outer-with-indirect-nested',
|
||||||
|
template: 'OUTER(<simple><div><content></content></div></simple>)',
|
||||||
|
directives: [simple]
|
||||||
|
});
|
||||||
|
|
||||||
|
var outerTemplate = new ViewDefinition({
|
||||||
|
componentId: 'outer',
|
||||||
|
template: 'OUTER(<inner><content></content></inner>)',
|
||||||
|
directives: [innerComponent]
|
||||||
|
});
|
||||||
|
|
||||||
|
var innerTemplate = new ViewDefinition({
|
||||||
|
componentId: 'inner',
|
||||||
|
template: 'INNER(<innerinner><content></content></innerinner>)',
|
||||||
|
directives: [innerInnerComponent]
|
||||||
|
});
|
||||||
|
|
||||||
|
var innerInnerTemplate = new ViewDefinition({
|
||||||
|
componentId: 'innerinner',
|
||||||
|
template: 'INNERINNER(<content select=".left"></content>,<content></content>)',
|
||||||
|
directives: []
|
||||||
|
});
|
||||||
|
|
||||||
|
var conditionalContentTemplate = new ViewDefinition({
|
||||||
|
componentId: 'conditional-content',
|
||||||
|
template:
|
||||||
|
'<div>(<div *auto="cond"><content select=".left"></content></div>, <content></content>)</div>',
|
||||||
|
directives: [autoViewportDirective]
|
||||||
|
});
|
||||||
|
|
||||||
|
var tabTemplate = new ViewDefinition({
|
||||||
|
componentId: 'tab',
|
||||||
|
template: '<div><div *auto="cond">TAB(<content></content>)</div></div>',
|
||||||
|
directives: [autoViewportDirective]
|
||||||
|
});
|
|
@ -1,12 +1,20 @@
|
||||||
import {describe, ddescribe, it, iit, xit, xdescribe, expect, beforeEach, el} from 'angular2/test_lib';
|
import {
|
||||||
|
describe,
|
||||||
|
ddescribe,
|
||||||
|
it,
|
||||||
|
iit,
|
||||||
|
xit,
|
||||||
|
xdescribe,
|
||||||
|
expect,
|
||||||
|
beforeEach,
|
||||||
|
el
|
||||||
|
} from 'angular2/test_lib';
|
||||||
import {setterFactory} from 'angular2/src/render/dom/view/property_setter_factory';
|
import {setterFactory} from 'angular2/src/render/dom/view/property_setter_factory';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
var div;
|
var div;
|
||||||
beforeEach( () => {
|
beforeEach(() => { div = el('<div></div>'); });
|
||||||
div = el('<div></div>');
|
|
||||||
});
|
|
||||||
describe('property setter factory', () => {
|
describe('property setter factory', () => {
|
||||||
|
|
||||||
it('should return a setter for a property', () => {
|
it('should return a setter for a property', () => {
|
||||||
|
@ -24,9 +32,8 @@ export function main() {
|
||||||
expect(DOM.getAttribute(div, 'role')).toEqual('button');
|
expect(DOM.getAttribute(div, 'role')).toEqual('button');
|
||||||
setterFn(div, null);
|
setterFn(div, null);
|
||||||
expect(DOM.getAttribute(div, 'role')).toEqual(null);
|
expect(DOM.getAttribute(div, 'role')).toEqual(null);
|
||||||
expect(() => {
|
expect(() => { setterFn(div, 4); })
|
||||||
setterFn(div, 4);
|
.toThrowError("Invalid role attribute, only string values are allowed, got '4'");
|
||||||
}).toThrowError("Invalid role attribute, only string values are allowed, got '4'");
|
|
||||||
|
|
||||||
var otherSetterFn = setterFactory('attr.role');
|
var otherSetterFn = setterFactory('attr.role');
|
||||||
expect(setterFn).toBe(otherSetterFn);
|
expect(setterFn).toBe(otherSetterFn);
|
|
@ -12,7 +12,8 @@ import {
|
||||||
beforeEachBindings,
|
beforeEachBindings,
|
||||||
it,
|
it,
|
||||||
xit,
|
xit,
|
||||||
SpyObject, proxy
|
SpyObject,
|
||||||
|
proxy
|
||||||
} from 'angular2/test_lib';
|
} from 'angular2/test_lib';
|
||||||
import {IMPLEMENTS, isBlank} from 'angular2/src/facade/lang';
|
import {IMPLEMENTS, isBlank} from 'angular2/src/facade/lang';
|
||||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||||
|
@ -24,58 +25,48 @@ import {LightDom} from 'angular2/src/render/dom/shadow_dom/light_dom';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
|
|
||||||
describe('DomView', () => {
|
describe('DomView', () => {
|
||||||
function createProtoView(binders = null) {
|
function createProtoView(binders = null) {
|
||||||
if (isBlank(binders)) {
|
if (isBlank(binders)) {
|
||||||
binders = [];
|
binders = [];
|
||||||
}
|
}
|
||||||
var rootEl = el('<div></div>');
|
var rootEl = el('<div></div>');
|
||||||
return new DomProtoView({
|
return new DomProtoView({element: rootEl, elementBinders: binders});
|
||||||
element: rootEl,
|
|
||||||
elementBinders: binders
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createView(pv=null, boundElementCount=0) {
|
function createView(pv = null, boundElementCount = 0) {
|
||||||
if (isBlank(pv)) {
|
if (isBlank(pv)) {
|
||||||
pv = createProtoView();
|
pv = createProtoView();
|
||||||
}
|
}
|
||||||
var root = el('<div><div></div></div>');
|
var root = el('<div><div></div></div>');
|
||||||
var boundElements = [];
|
var boundElements = [];
|
||||||
for (var i=0; i<boundElementCount; i++) {
|
for (var i = 0; i < boundElementCount; i++) {
|
||||||
ListWrapper.push(boundElements, el('<span></span'));
|
ListWrapper.push(boundElements, el('<span></span'));
|
||||||
}
|
}
|
||||||
return new DomView(pv, [DOM.childNodes(root)[0]],
|
return new DomView(pv, [DOM.childNodes(root)[0]], [], boundElements, []);
|
||||||
[], boundElements, []);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('getDirectParentLightDom', () => {
|
describe('getDirectParentLightDom', () => {
|
||||||
|
|
||||||
it('should return the LightDom of the direct parent', () => {
|
it('should return the LightDom of the direct parent', () => {
|
||||||
var pv = createProtoView(
|
var pv = createProtoView(
|
||||||
[new ElementBinder(), new ElementBinder({
|
[new ElementBinder(), new ElementBinder({parentIndex: 0, distanceToParent: 1})]);
|
||||||
parentIndex: 0,
|
|
||||||
distanceToParent: 1
|
|
||||||
})]
|
|
||||||
);
|
|
||||||
var view = createView(pv, 2);
|
var view = createView(pv, 2);
|
||||||
view.lightDoms[0] = new SpyLightDom();
|
view.lightDoms[0] = <any>new SpyLightDom();
|
||||||
view.lightDoms[1] = new SpyLightDom();
|
view.lightDoms[1] = <any>new SpyLightDom();
|
||||||
expect(view.getDirectParentLightDom(1)).toBe(view.lightDoms[0]);
|
expect(view.getDirectParentLightDom(1)).toBe(view.lightDoms[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return null if the direct parent is not bound', () => {
|
it('should return null if the direct parent is not bound', () => {
|
||||||
var pv = createProtoView(
|
var pv = createProtoView([
|
||||||
[new ElementBinder(), new ElementBinder(), new ElementBinder({
|
new ElementBinder(),
|
||||||
parentIndex: 0,
|
new ElementBinder(),
|
||||||
distanceToParent: 2
|
new ElementBinder({parentIndex: 0, distanceToParent: 2})
|
||||||
})]
|
]);
|
||||||
);
|
|
||||||
var view = createView(pv, 3);
|
var view = createView(pv, 3);
|
||||||
view.lightDoms[0] = new SpyLightDom();
|
view.lightDoms[0] = <any>new SpyLightDom();
|
||||||
view.lightDoms[1] = new SpyLightDom();
|
view.lightDoms[1] = <any>new SpyLightDom();
|
||||||
view.lightDoms[2] = new SpyLightDom();
|
view.lightDoms[2] = <any>new SpyLightDom();
|
||||||
expect(view.getDirectParentLightDom(2)).toBe(null);
|
expect(view.getDirectParentLightDom(2)).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -87,7 +78,6 @@ export function main() {
|
||||||
@proxy
|
@proxy
|
||||||
@IMPLEMENTS(LightDom)
|
@IMPLEMENTS(LightDom)
|
||||||
class SpyLightDom extends SpyObject {
|
class SpyLightDom extends SpyObject {
|
||||||
constructor(){super(LightDom);}
|
constructor() { super(LightDom); }
|
||||||
noSuchMethod(m){return super.noSuchMethod(m)}
|
noSuchMethod(m) { return super.noSuchMethod(m) }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue